Complete changes needed for valueObjects

This commit is contained in:
amir.gholami 2023-05-27 01:08:08 +03:30
parent 5c5be8eef8
commit f639619940
47 changed files with 1863 additions and 164 deletions

3
.gitignore vendored
View File

@ -435,4 +435,5 @@ fabric.properties
*.jwk
**/keys
**/keys
/src/ApiGateway/back.txt

View File

@ -0,0 +1,12 @@
namespace Flight.Aircrafts.Exceptions;
using System;
using BuildingBlocks.Exception;
public class InvalidAircraftIdExceptions : BadRequestException
{
public InvalidAircraftIdExceptions(Guid aircraftId)
: base($"AircraftId: '{aircraftId}' is invalid.")
{
}
}

View File

@ -1,9 +1,10 @@
using Flight.Aircrafts.Models;
using Flight.Aircrafts.Models;
using Mapster;
namespace Flight.Aircrafts.Features;
using CreatingAircraft.V1;
using Flight.Aircrafts.Models.ValueObjects;
using MassTransit;
public class AircraftMappings : IRegister
@ -11,12 +12,12 @@ public class AircraftMappings : IRegister
public void Register(TypeAdapterConfig config)
{
config.NewConfig<CreateAircraftMongo, AircraftReadModel>()
.Map(d => d.Id, s => NewId.NextGuid())
.Map(d => d.AircraftId, s => s.Id);
.Map(d => d.Id, s => NewId.NextGuid())
.Map(d => d.AircraftId, s => AircraftId.Of(s.Id));
config.NewConfig<Aircraft, AircraftReadModel>()
.Map(d => d.Id, s => NewId.NextGuid())
.Map(d => d.AircraftId, s => s.Id);
.Map(d => d.AircraftId, s => AircraftId.Of(s.Id));
config.NewConfig<CreateAircraftRequestDto, CreatingAircraft.V1.CreateAircraft>()
.ConstructUsing(x => new CreatingAircraft.V1.CreateAircraft(x.Name, x.Model, x.ManufacturingYear));

View File

@ -1,6 +1,7 @@
namespace Flight.Aircrafts.Features.CreatingAircraft.V1;
using System;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Ardalis.GuardClauses;
@ -17,7 +18,6 @@ using MediatR;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Routing;
using Microsoft.EntityFrameworkCore;
using Models;
using Models.ValueObjects;
@ -27,7 +27,7 @@ public record CreateAircraft(string Name, string Model, int ManufacturingYear) :
public Guid Id { get; init; } = NewId.NextGuid();
}
public record CreateAircraftResult(Guid Id);
public record CreateAircraftResult(AircraftId Id);
public record AircraftCreatedDomainEvent
(Guid Id, string Name, string Model, int ManufacturingYear, bool IsDeleted) : IDomainEvent;
@ -89,15 +89,19 @@ internal class CreateAircraftHandler : IRequestHandler<CreateAircraft, CreateAir
{
Guard.Against.Null(request, nameof(request));
var aircraft =
await _flightDbContext.Aircraft.SingleOrDefaultAsync(x => x.Model == request.Model, cancellationToken);
//var aircraft =
// await _flightDbContext.Aircraft.SingleOrDefaultAsync(x => x.Model == Model.Of(request.Model), cancellationToken);
var aircraft = _flightDbContext.Aircraft.AsEnumerable()
.FirstOrDefault(a => a.Model.Equals(Model.Of(request.Model)));
if (aircraft is not null)
{
throw new AircraftAlreadyExistException();
}
var aircraftEntity = Aircraft.Create(request.Id, NameValue.Of(request.Name), ModelValue.Of(request.Model), ManufacturingYearValue.Of(request.ManufacturingYear));
var aircraftEntity = Aircraft.Create(AircraftId.Of(request.Id), Name.Of(request.Name), Model.Of(request.Model), ManufacturingYear.Of(request.ManufacturingYear));
var newAircraft = (await _flightDbContext.Aircraft.AddAsync(aircraftEntity, cancellationToken))?.Entity;

View File

@ -1,4 +1,4 @@
namespace Flight.Aircrafts.Features.CreatingAircraft.V1;
namespace Flight.Aircrafts.Features.CreatingAircraft.V1;
using System;
using System.Threading;
@ -6,11 +6,12 @@ using System.Threading.Tasks;
using Ardalis.GuardClauses;
using BuildingBlocks.Core.CQRS;
using BuildingBlocks.Core.Event;
using Exceptions;
using Models;
using Data;
using Exceptions;
using MapsterMapper;
using MediatR;
using Models;
using Models.ValueObjects;
using MongoDB.Driver;
using MongoDB.Driver.Linq;
@ -36,7 +37,7 @@ public class CreateAircraftMongoHandler : ICommandHandler<CreateAircraftMongo>
var aircraftReadModel = _mapper.Map<AircraftReadModel>(request);
var aircraft = await _flightReadDbContext.Aircraft.AsQueryable()
.FirstOrDefaultAsync(x => x.AircraftId == aircraftReadModel.AircraftId, cancellationToken);
.FirstOrDefaultAsync(x => x.AircraftId == AircraftId.Of(aircraftReadModel.AircraftId), cancellationToken);
if (aircraft is not null)
{

View File

@ -2,17 +2,16 @@ using BuildingBlocks.Core.Model;
namespace Flight.Aircrafts.Models;
using System;
using Features.CreatingAircraft.V1;
using ValueObjects;
public record Aircraft : Aggregate<Guid>
public record Aircraft : Aggregate<AircraftId>
{
public NameValue Name { get; private set; }
public ModelValue Model { get; private set; }
public ManufacturingYearValue ManufacturingYear { get; private set; }
public Name Name { get; private set; }
public Model Model { get; private set; }
public ManufacturingYear ManufacturingYear { get; private set; }
public static Aircraft Create(Guid id, NameValue name, ModelValue model, ManufacturingYearValue manufacturingYear, bool isDeleted = false)
public static Aircraft Create(AircraftId id, Name name, Model model, ManufacturingYear manufacturingYear, bool isDeleted = false)
{
var aircraft = new Aircraft
{

View File

@ -1,13 +1,14 @@
namespace Flight.Aircrafts.Models;
namespace Flight.Aircrafts.Models;
using System;
using Flight.Aircrafts.Models.ValueObjects;
public class AircraftReadModel
{
public required Guid Id { get; init; }
public required Guid AircraftId { get; init; }
public required string Name { get; init; }
public required string Model { get; init; }
public required int ManufacturingYear { get; init; }
public required AircraftId AircraftId { get; init; }
public required Name Name { get; init; }
public required Model Model { get; init; }
public required ManufacturingYear ManufacturingYear { get; init; }
public required bool IsDeleted { get; init; }
}

View File

@ -0,0 +1,28 @@
namespace Flight.Aircrafts.Models.ValueObjects;
using System;
using Exceptions;
public record AircraftId
{
public Guid Value { get; }
private AircraftId(Guid value)
{
if (value == Guid.Empty)
{
throw new InvalidAircraftIdExceptions(value);
}
Value = value;
}
public static AircraftId Of(Guid value)
{
return new AircraftId(value);
}
public static implicit operator Guid(AircraftId aircraftId)
{
return aircraftId.Value;
}
}

View File

@ -0,0 +1,19 @@
namespace Flight.Aircrafts.Models.ValueObjects;
using System;
public record ManufacturingYear : GenericValueObject<int>
{
public ManufacturingYear(int value) : base(value)
{
if (string.IsNullOrWhiteSpace(value.ToString()))
{
throw new ArgumentException("ManufacturingYear cannot be empty or whitespace.");
}
}
public static ManufacturingYear Of(int value)
{
return new ManufacturingYear(value);
}
}

View File

@ -1,18 +0,0 @@
namespace Flight.Aircrafts.Models.ValueObjects;
using System;
public record ManufacturingYearValue : GenericValueObject<int>
{
public ManufacturingYearValue(int value) : base(value)
{
if (value < 1900 || value > DateTime.Now.Year)
{
throw new ArgumentException("Manufacturing year is invalid.");
}
}
public static ManufacturingYearValue Of(int value)
{
return new ManufacturingYearValue(value);
}
}

View File

@ -1,8 +1,8 @@
namespace Flight.Aircrafts.Models.ValueObjects;
using System;
public record ModelValue : GenericValueObject<string>
public record Model : GenericValueObject<string>
{
public ModelValue(string value) : base(value)
public Model(string value) : base(value)
{
if (string.IsNullOrWhiteSpace(value))
{
@ -10,8 +10,8 @@ public record ModelValue : GenericValueObject<string>
}
}
public static ModelValue Of(string value)
public static Model Of(string value)
{
return new ModelValue(value);
return new Model(value);
}
}

View File

@ -1,9 +1,9 @@
namespace Flight.Aircrafts.Models.ValueObjects;
using System;
public record NameValue : GenericValueObject<string>
public record Name : GenericValueObject<string>
{
public NameValue(string value) : base(value)
public Name(string value) : base(value)
{
if (string.IsNullOrWhiteSpace(value))
{
@ -11,8 +11,8 @@ public record NameValue : GenericValueObject<string>
}
}
public static NameValue Of(string value)
public static Name Of(string value)
{
return new NameValue(value);
return new Name(value);
}
}

View File

@ -4,17 +4,53 @@ using Microsoft.EntityFrameworkCore.Metadata.Builders;
namespace Flight.Data.Configurations;
using System;
using Flight.Aircrafts.Models.ValueObjects;
public class AircraftConfiguration : IEntityTypeConfiguration<Aircraft>
{
public void Configure(EntityTypeBuilder<Aircraft> builder)
{
builder.ToTable(nameof(Aircraft));
builder.HasKey(r => r.Id);
builder.Property(r => r.Id).ValueGeneratedNever();
builder.Property(r => r.Id).ValueGeneratedNever()
.HasConversion<Guid>(aircraftId => aircraftId.Value, dbId => AircraftId.Of(dbId));
// // ref: https://learn.microsoft.com/en-us/ef/core/saving/concurrency?tabs=fluent-api
builder.Property(r => r.Version).IsConcurrencyToken();
builder.OwnsOne(
x => x.Name,
a =>
{
a.Property(p => p.Value)
.HasColumnName(nameof(Aircraft.Name))
.HasMaxLength(50)
.IsRequired();
}
);
builder.OwnsOne(
x => x.Model,
a =>
{
a.Property(p => p.Value)
.HasColumnName(nameof(Aircraft.Model))
.HasMaxLength(50)
.IsRequired();
}
);
builder.OwnsOne(
x => x.ManufacturingYear,
a =>
{
a.Property(p => p.Value)
.HasColumnName(nameof(Aircraft.ManufacturingYear))
.HasMaxLength(5)
.IsRequired();
}
);
}
}

View File

@ -0,0 +1,363 @@
// <auto-generated />
using System;
using Flight.Data;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
#nullable disable
namespace Flight.Data.Migrations
{
[DbContext(typeof(FlightDbContext))]
[Migration("20230525075149_aircraftValueObjects")]
partial class aircraftValueObjects
{
/// <inheritdoc />
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "7.0.2")
.HasAnnotation("Relational:MaxIdentifierLength", 63);
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
modelBuilder.Entity("Flight.Aircrafts.Models.Aircraft", b =>
{
b.Property<Guid>("Id")
.HasColumnType("uuid")
.HasColumnName("id");
b.Property<DateTime?>("CreatedAt")
.HasColumnType("timestamp with time zone")
.HasColumnName("created_at");
b.Property<long?>("CreatedBy")
.HasColumnType("bigint")
.HasColumnName("created_by");
b.Property<bool>("IsDeleted")
.HasColumnType("boolean")
.HasColumnName("is_deleted");
b.Property<DateTime?>("LastModified")
.HasColumnType("timestamp with time zone")
.HasColumnName("last_modified");
b.Property<long?>("LastModifiedBy")
.HasColumnType("bigint")
.HasColumnName("last_modified_by");
b.Property<long>("Version")
.IsConcurrencyToken()
.HasColumnType("bigint")
.HasColumnName("version");
b.HasKey("Id")
.HasName("pk_aircraft");
b.ToTable("aircraft", (string)null);
});
modelBuilder.Entity("Flight.Airports.Models.Airport", b =>
{
b.Property<Guid>("Id")
.HasColumnType("uuid")
.HasColumnName("id");
b.Property<string>("Address")
.HasColumnType("text")
.HasColumnName("address");
b.Property<string>("Code")
.HasColumnType("text")
.HasColumnName("code");
b.Property<DateTime?>("CreatedAt")
.HasColumnType("timestamp with time zone")
.HasColumnName("created_at");
b.Property<long?>("CreatedBy")
.HasColumnType("bigint")
.HasColumnName("created_by");
b.Property<bool>("IsDeleted")
.HasColumnType("boolean")
.HasColumnName("is_deleted");
b.Property<DateTime?>("LastModified")
.HasColumnType("timestamp with time zone")
.HasColumnName("last_modified");
b.Property<long?>("LastModifiedBy")
.HasColumnType("bigint")
.HasColumnName("last_modified_by");
b.Property<string>("Name")
.HasColumnType("text")
.HasColumnName("name");
b.Property<long>("Version")
.IsConcurrencyToken()
.HasColumnType("bigint")
.HasColumnName("version");
b.HasKey("Id")
.HasName("pk_airport");
b.ToTable("airport", (string)null);
});
modelBuilder.Entity("Flight.Flights.Models.Flight", b =>
{
b.Property<Guid>("Id")
.HasColumnType("uuid")
.HasColumnName("id");
b.Property<Guid?>("AircraftId")
.HasColumnType("uuid")
.HasColumnName("aircraft_id");
b.Property<Guid>("ArriveAirportId")
.HasColumnType("uuid")
.HasColumnName("arrive_airport_id");
b.Property<DateTime>("ArriveDate")
.HasColumnType("timestamp with time zone")
.HasColumnName("arrive_date");
b.Property<DateTime?>("CreatedAt")
.HasColumnType("timestamp with time zone")
.HasColumnName("created_at");
b.Property<long?>("CreatedBy")
.HasColumnType("bigint")
.HasColumnName("created_by");
b.Property<Guid>("DepartureAirportId")
.HasColumnType("uuid")
.HasColumnName("departure_airport_id");
b.Property<DateTime>("DepartureDate")
.HasColumnType("timestamp with time zone")
.HasColumnName("departure_date");
b.Property<decimal>("DurationMinutes")
.HasColumnType("numeric")
.HasColumnName("duration_minutes");
b.Property<DateTime>("FlightDate")
.HasColumnType("timestamp with time zone")
.HasColumnName("flight_date");
b.Property<string>("FlightNumber")
.HasColumnType("text")
.HasColumnName("flight_number");
b.Property<bool>("IsDeleted")
.HasColumnType("boolean")
.HasColumnName("is_deleted");
b.Property<DateTime?>("LastModified")
.HasColumnType("timestamp with time zone")
.HasColumnName("last_modified");
b.Property<long?>("LastModifiedBy")
.HasColumnType("bigint")
.HasColumnName("last_modified_by");
b.Property<decimal>("Price")
.HasColumnType("numeric")
.HasColumnName("price");
b.Property<string>("Status")
.IsRequired()
.ValueGeneratedOnAdd()
.HasColumnType("text")
.HasDefaultValue("Unknown")
.HasColumnName("status");
b.Property<long>("Version")
.IsConcurrencyToken()
.HasColumnType("bigint")
.HasColumnName("version");
b.HasKey("Id")
.HasName("pk_flight");
b.HasIndex("AircraftId")
.HasDatabaseName("ix_flight_aircraft_id");
b.HasIndex("ArriveAirportId")
.HasDatabaseName("ix_flight_arrive_airport_id");
b.ToTable("flight", (string)null);
});
modelBuilder.Entity("Flight.Seats.Models.Seat", b =>
{
b.Property<Guid>("Id")
.HasColumnType("uuid")
.HasColumnName("id");
b.Property<string>("Class")
.IsRequired()
.ValueGeneratedOnAdd()
.HasColumnType("text")
.HasDefaultValue("Unknown")
.HasColumnName("class");
b.Property<DateTime?>("CreatedAt")
.HasColumnType("timestamp with time zone")
.HasColumnName("created_at");
b.Property<long?>("CreatedBy")
.HasColumnType("bigint")
.HasColumnName("created_by");
b.Property<Guid>("FlightId")
.HasColumnType("uuid")
.HasColumnName("flight_id");
b.Property<bool>("IsDeleted")
.HasColumnType("boolean")
.HasColumnName("is_deleted");
b.Property<DateTime?>("LastModified")
.HasColumnType("timestamp with time zone")
.HasColumnName("last_modified");
b.Property<long?>("LastModifiedBy")
.HasColumnType("bigint")
.HasColumnName("last_modified_by");
b.Property<string>("SeatNumber")
.HasColumnType("text")
.HasColumnName("seat_number");
b.Property<string>("Type")
.IsRequired()
.ValueGeneratedOnAdd()
.HasColumnType("text")
.HasDefaultValue("Unknown")
.HasColumnName("type");
b.Property<long>("Version")
.IsConcurrencyToken()
.HasColumnType("bigint")
.HasColumnName("version");
b.HasKey("Id")
.HasName("pk_seat");
b.HasIndex("FlightId")
.HasDatabaseName("ix_seat_flight_id");
b.ToTable("seat", (string)null);
});
modelBuilder.Entity("Flight.Aircrafts.Models.Aircraft", b =>
{
b.OwnsOne("Flight.Aircrafts.Models.ValueObjects.ManufacturingYearValue", "ManufacturingYear", b1 =>
{
b1.Property<Guid>("AircraftId")
.HasColumnType("uuid")
.HasColumnName("id");
b1.Property<int>("Value")
.HasMaxLength(5)
.HasColumnType("integer")
.HasColumnName("manufacturing_year");
b1.HasKey("AircraftId")
.HasName("pk_aircraft");
b1.ToTable("aircraft");
b1.WithOwner()
.HasForeignKey("AircraftId")
.HasConstraintName("fk_aircraft_aircraft_id");
});
b.OwnsOne("Flight.Aircrafts.Models.ValueObjects.ModelValue", "Model", b1 =>
{
b1.Property<Guid>("AircraftId")
.HasColumnType("uuid")
.HasColumnName("id");
b1.Property<string>("Value")
.IsRequired()
.HasMaxLength(50)
.HasColumnType("character varying(50)")
.HasColumnName("model");
b1.HasKey("AircraftId")
.HasName("pk_aircraft");
b1.ToTable("aircraft");
b1.WithOwner()
.HasForeignKey("AircraftId")
.HasConstraintName("fk_aircraft_aircraft_id");
});
b.OwnsOne("Flight.Aircrafts.Models.ValueObjects.NameValue", "Name", b1 =>
{
b1.Property<Guid>("AircraftId")
.HasColumnType("uuid")
.HasColumnName("id");
b1.Property<string>("Value")
.IsRequired()
.HasMaxLength(50)
.HasColumnType("character varying(50)")
.HasColumnName("name");
b1.HasKey("AircraftId")
.HasName("pk_aircraft");
b1.ToTable("aircraft");
b1.WithOwner()
.HasForeignKey("AircraftId")
.HasConstraintName("fk_aircraft_aircraft_id");
});
b.Navigation("ManufacturingYear");
b.Navigation("Model");
b.Navigation("Name");
});
modelBuilder.Entity("Flight.Flights.Models.Flight", b =>
{
b.HasOne("Flight.Aircrafts.Models.Aircraft", null)
.WithMany()
.HasForeignKey("AircraftId")
.HasConstraintName("fk_flight_aircraft_aircraft_id");
b.HasOne("Flight.Airports.Models.Airport", null)
.WithMany()
.HasForeignKey("ArriveAirportId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired()
.HasConstraintName("fk_flight_airport_arrive_airport_id");
});
modelBuilder.Entity("Flight.Seats.Models.Seat", b =>
{
b.HasOne("Flight.Flights.Models.Flight", null)
.WithMany()
.HasForeignKey("FlightId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired()
.HasConstraintName("fk_seat_flight_flight_id");
});
#pragma warning restore 612, 618
}
}
}

View File

@ -0,0 +1,120 @@
using System;
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace Flight.Data.Migrations
{
/// <inheritdoc />
public partial class aircraftValueObjects : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropForeignKey(
name: "fk_flight_aircraft_aircraft_id",
table: "flight");
migrationBuilder.AlterColumn<Guid>(
name: "aircraft_id",
table: "flight",
type: "uuid",
nullable: true,
oldClrType: typeof(Guid),
oldType: "uuid");
migrationBuilder.AlterColumn<string>(
name: "name",
table: "aircraft",
type: "character varying(50)",
maxLength: 50,
nullable: true,
oldClrType: typeof(string),
oldType: "text",
oldNullable: true);
migrationBuilder.AlterColumn<string>(
name: "model",
table: "aircraft",
type: "character varying(50)",
maxLength: 50,
nullable: true,
oldClrType: typeof(string),
oldType: "text",
oldNullable: true);
migrationBuilder.AlterColumn<int>(
name: "manufacturing_year",
table: "aircraft",
type: "integer",
maxLength: 5,
nullable: true,
oldClrType: typeof(int),
oldType: "integer");
migrationBuilder.AddForeignKey(
name: "fk_flight_aircraft_aircraft_id",
table: "flight",
column: "aircraft_id",
principalTable: "aircraft",
principalColumn: "id");
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropForeignKey(
name: "fk_flight_aircraft_aircraft_id",
table: "flight");
migrationBuilder.AlterColumn<Guid>(
name: "aircraft_id",
table: "flight",
type: "uuid",
nullable: false,
defaultValue: new Guid("00000000-0000-0000-0000-000000000000"),
oldClrType: typeof(Guid),
oldType: "uuid",
oldNullable: true);
migrationBuilder.AlterColumn<string>(
name: "name",
table: "aircraft",
type: "text",
nullable: true,
oldClrType: typeof(string),
oldType: "character varying(50)",
oldMaxLength: 50,
oldNullable: true);
migrationBuilder.AlterColumn<string>(
name: "model",
table: "aircraft",
type: "text",
nullable: true,
oldClrType: typeof(string),
oldType: "character varying(50)",
oldMaxLength: 50,
oldNullable: true);
migrationBuilder.AlterColumn<int>(
name: "manufacturing_year",
table: "aircraft",
type: "integer",
nullable: false,
defaultValue: 0,
oldClrType: typeof(int),
oldType: "integer",
oldMaxLength: 5,
oldNullable: true);
migrationBuilder.AddForeignKey(
name: "fk_flight_aircraft_aircraft_id",
table: "flight",
column: "aircraft_id",
principalTable: "aircraft",
principalColumn: "id",
onDelete: ReferentialAction.Cascade);
}
}
}

View File

@ -0,0 +1,363 @@
// <auto-generated />
using System;
using Flight.Data;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
#nullable disable
namespace Flight.Data.Migrations
{
[DbContext(typeof(FlightDbContext))]
[Migration("20230526093041_aircraftValueObject")]
partial class aircraftValueObject
{
/// <inheritdoc />
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "7.0.2")
.HasAnnotation("Relational:MaxIdentifierLength", 63);
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
modelBuilder.Entity("Flight.Aircrafts.Models.Aircraft", b =>
{
b.Property<Guid>("Id")
.HasColumnType("uuid")
.HasColumnName("id");
b.Property<DateTime?>("CreatedAt")
.HasColumnType("timestamp with time zone")
.HasColumnName("created_at");
b.Property<long?>("CreatedBy")
.HasColumnType("bigint")
.HasColumnName("created_by");
b.Property<bool>("IsDeleted")
.HasColumnType("boolean")
.HasColumnName("is_deleted");
b.Property<DateTime?>("LastModified")
.HasColumnType("timestamp with time zone")
.HasColumnName("last_modified");
b.Property<long?>("LastModifiedBy")
.HasColumnType("bigint")
.HasColumnName("last_modified_by");
b.Property<long>("Version")
.IsConcurrencyToken()
.HasColumnType("bigint")
.HasColumnName("version");
b.HasKey("Id")
.HasName("pk_aircraft");
b.ToTable("aircraft", (string)null);
});
modelBuilder.Entity("Flight.Airports.Models.Airport", b =>
{
b.Property<Guid>("Id")
.HasColumnType("uuid")
.HasColumnName("id");
b.Property<string>("Address")
.HasColumnType("text")
.HasColumnName("address");
b.Property<string>("Code")
.HasColumnType("text")
.HasColumnName("code");
b.Property<DateTime?>("CreatedAt")
.HasColumnType("timestamp with time zone")
.HasColumnName("created_at");
b.Property<long?>("CreatedBy")
.HasColumnType("bigint")
.HasColumnName("created_by");
b.Property<bool>("IsDeleted")
.HasColumnType("boolean")
.HasColumnName("is_deleted");
b.Property<DateTime?>("LastModified")
.HasColumnType("timestamp with time zone")
.HasColumnName("last_modified");
b.Property<long?>("LastModifiedBy")
.HasColumnType("bigint")
.HasColumnName("last_modified_by");
b.Property<string>("Name")
.HasColumnType("text")
.HasColumnName("name");
b.Property<long>("Version")
.IsConcurrencyToken()
.HasColumnType("bigint")
.HasColumnName("version");
b.HasKey("Id")
.HasName("pk_airport");
b.ToTable("airport", (string)null);
});
modelBuilder.Entity("Flight.Flights.Models.Flight", b =>
{
b.Property<Guid>("Id")
.HasColumnType("uuid")
.HasColumnName("id");
b.Property<Guid?>("AircraftId")
.HasColumnType("uuid")
.HasColumnName("aircraft_id");
b.Property<Guid>("ArriveAirportId")
.HasColumnType("uuid")
.HasColumnName("arrive_airport_id");
b.Property<DateTime>("ArriveDate")
.HasColumnType("timestamp with time zone")
.HasColumnName("arrive_date");
b.Property<DateTime?>("CreatedAt")
.HasColumnType("timestamp with time zone")
.HasColumnName("created_at");
b.Property<long?>("CreatedBy")
.HasColumnType("bigint")
.HasColumnName("created_by");
b.Property<Guid>("DepartureAirportId")
.HasColumnType("uuid")
.HasColumnName("departure_airport_id");
b.Property<DateTime>("DepartureDate")
.HasColumnType("timestamp with time zone")
.HasColumnName("departure_date");
b.Property<decimal>("DurationMinutes")
.HasColumnType("numeric")
.HasColumnName("duration_minutes");
b.Property<DateTime>("FlightDate")
.HasColumnType("timestamp with time zone")
.HasColumnName("flight_date");
b.Property<string>("FlightNumber")
.HasColumnType("text")
.HasColumnName("flight_number");
b.Property<bool>("IsDeleted")
.HasColumnType("boolean")
.HasColumnName("is_deleted");
b.Property<DateTime?>("LastModified")
.HasColumnType("timestamp with time zone")
.HasColumnName("last_modified");
b.Property<long?>("LastModifiedBy")
.HasColumnType("bigint")
.HasColumnName("last_modified_by");
b.Property<decimal>("Price")
.HasColumnType("numeric")
.HasColumnName("price");
b.Property<string>("Status")
.IsRequired()
.ValueGeneratedOnAdd()
.HasColumnType("text")
.HasDefaultValue("Unknown")
.HasColumnName("status");
b.Property<long>("Version")
.IsConcurrencyToken()
.HasColumnType("bigint")
.HasColumnName("version");
b.HasKey("Id")
.HasName("pk_flight");
b.HasIndex("AircraftId")
.HasDatabaseName("ix_flight_aircraft_id");
b.HasIndex("ArriveAirportId")
.HasDatabaseName("ix_flight_arrive_airport_id");
b.ToTable("flight", (string)null);
});
modelBuilder.Entity("Flight.Seats.Models.Seat", b =>
{
b.Property<Guid>("Id")
.HasColumnType("uuid")
.HasColumnName("id");
b.Property<string>("Class")
.IsRequired()
.ValueGeneratedOnAdd()
.HasColumnType("text")
.HasDefaultValue("Unknown")
.HasColumnName("class");
b.Property<DateTime?>("CreatedAt")
.HasColumnType("timestamp with time zone")
.HasColumnName("created_at");
b.Property<long?>("CreatedBy")
.HasColumnType("bigint")
.HasColumnName("created_by");
b.Property<Guid>("FlightId")
.HasColumnType("uuid")
.HasColumnName("flight_id");
b.Property<bool>("IsDeleted")
.HasColumnType("boolean")
.HasColumnName("is_deleted");
b.Property<DateTime?>("LastModified")
.HasColumnType("timestamp with time zone")
.HasColumnName("last_modified");
b.Property<long?>("LastModifiedBy")
.HasColumnType("bigint")
.HasColumnName("last_modified_by");
b.Property<string>("SeatNumber")
.HasColumnType("text")
.HasColumnName("seat_number");
b.Property<string>("Type")
.IsRequired()
.ValueGeneratedOnAdd()
.HasColumnType("text")
.HasDefaultValue("Unknown")
.HasColumnName("type");
b.Property<long>("Version")
.IsConcurrencyToken()
.HasColumnType("bigint")
.HasColumnName("version");
b.HasKey("Id")
.HasName("pk_seat");
b.HasIndex("FlightId")
.HasDatabaseName("ix_seat_flight_id");
b.ToTable("seat", (string)null);
});
modelBuilder.Entity("Flight.Aircrafts.Models.Aircraft", b =>
{
b.OwnsOne("Flight.Aircrafts.Models.ValueObjects.ManufacturingYearValue", "ManufacturingYear", b1 =>
{
b1.Property<Guid>("AircraftId")
.HasColumnType("uuid")
.HasColumnName("id");
b1.Property<int>("Value")
.HasMaxLength(5)
.HasColumnType("integer")
.HasColumnName("manufacturing_year");
b1.HasKey("AircraftId")
.HasName("pk_aircraft");
b1.ToTable("aircraft");
b1.WithOwner()
.HasForeignKey("AircraftId")
.HasConstraintName("fk_aircraft_aircraft_id");
});
b.OwnsOne("Flight.Aircrafts.Models.ValueObjects.ModelValue", "Model", b1 =>
{
b1.Property<Guid>("AircraftId")
.HasColumnType("uuid")
.HasColumnName("id");
b1.Property<string>("Value")
.IsRequired()
.HasMaxLength(50)
.HasColumnType("character varying(50)")
.HasColumnName("model");
b1.HasKey("AircraftId")
.HasName("pk_aircraft");
b1.ToTable("aircraft");
b1.WithOwner()
.HasForeignKey("AircraftId")
.HasConstraintName("fk_aircraft_aircraft_id");
});
b.OwnsOne("Flight.Aircrafts.Models.ValueObjects.NameValue", "Name", b1 =>
{
b1.Property<Guid>("AircraftId")
.HasColumnType("uuid")
.HasColumnName("id");
b1.Property<string>("Value")
.IsRequired()
.HasMaxLength(50)
.HasColumnType("character varying(50)")
.HasColumnName("name");
b1.HasKey("AircraftId")
.HasName("pk_aircraft");
b1.ToTable("aircraft");
b1.WithOwner()
.HasForeignKey("AircraftId")
.HasConstraintName("fk_aircraft_aircraft_id");
});
b.Navigation("ManufacturingYear");
b.Navigation("Model");
b.Navigation("Name");
});
modelBuilder.Entity("Flight.Flights.Models.Flight", b =>
{
b.HasOne("Flight.Aircrafts.Models.Aircraft", null)
.WithMany()
.HasForeignKey("AircraftId")
.HasConstraintName("fk_flight_aircraft_aircraft_id");
b.HasOne("Flight.Airports.Models.Airport", null)
.WithMany()
.HasForeignKey("ArriveAirportId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired()
.HasConstraintName("fk_flight_airport_arrive_airport_id");
});
modelBuilder.Entity("Flight.Seats.Models.Seat", b =>
{
b.HasOne("Flight.Flights.Models.Flight", null)
.WithMany()
.HasForeignKey("FlightId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired()
.HasConstraintName("fk_seat_flight_flight_id");
});
#pragma warning restore 612, 618
}
}
}

View File

@ -0,0 +1,22 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace Flight.Data.Migrations
{
/// <inheritdoc />
public partial class aircraftValueObject : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
}
}
}

View File

@ -48,18 +48,6 @@ namespace Flight.Data.Migrations
.HasColumnType("bigint")
.HasColumnName("last_modified_by");
b.Property<int>("ManufacturingYear")
.HasColumnType("integer")
.HasColumnName("manufacturing_year");
b.Property<string>("Model")
.HasColumnType("text")
.HasColumnName("model");
b.Property<string>("Name")
.HasColumnType("text")
.HasColumnName("name");
b.Property<long>("Version")
.IsConcurrencyToken()
.HasColumnType("bigint")
@ -126,7 +114,7 @@ namespace Flight.Data.Migrations
.HasColumnType("uuid")
.HasColumnName("id");
b.Property<Guid>("AircraftId")
b.Property<Guid?>("AircraftId")
.HasColumnType("uuid")
.HasColumnName("aircraft_id");
@ -268,13 +256,85 @@ namespace Flight.Data.Migrations
b.ToTable("seat", (string)null);
});
modelBuilder.Entity("Flight.Aircrafts.Models.Aircraft", b =>
{
b.OwnsOne("Flight.Aircrafts.Models.ValueObjects.ManufacturingYearValue", "ManufacturingYear", b1 =>
{
b1.Property<Guid>("AircraftId")
.HasColumnType("uuid")
.HasColumnName("id");
b1.Property<int>("Value")
.HasMaxLength(5)
.HasColumnType("integer")
.HasColumnName("manufacturing_year");
b1.HasKey("AircraftId")
.HasName("pk_aircraft");
b1.ToTable("aircraft");
b1.WithOwner()
.HasForeignKey("AircraftId")
.HasConstraintName("fk_aircraft_aircraft_id");
});
b.OwnsOne("Flight.Aircrafts.Models.ValueObjects.ModelValue", "Model", b1 =>
{
b1.Property<Guid>("AircraftId")
.HasColumnType("uuid")
.HasColumnName("id");
b1.Property<string>("Value")
.IsRequired()
.HasMaxLength(50)
.HasColumnType("character varying(50)")
.HasColumnName("model");
b1.HasKey("AircraftId")
.HasName("pk_aircraft");
b1.ToTable("aircraft");
b1.WithOwner()
.HasForeignKey("AircraftId")
.HasConstraintName("fk_aircraft_aircraft_id");
});
b.OwnsOne("Flight.Aircrafts.Models.ValueObjects.NameValue", "Name", b1 =>
{
b1.Property<Guid>("AircraftId")
.HasColumnType("uuid")
.HasColumnName("id");
b1.Property<string>("Value")
.IsRequired()
.HasMaxLength(50)
.HasColumnType("character varying(50)")
.HasColumnName("name");
b1.HasKey("AircraftId")
.HasName("pk_aircraft");
b1.ToTable("aircraft");
b1.WithOwner()
.HasForeignKey("AircraftId")
.HasConstraintName("fk_aircraft_aircraft_id");
});
b.Navigation("ManufacturingYear");
b.Navigation("Model");
b.Navigation("Name");
});
modelBuilder.Entity("Flight.Flights.Models.Flight", b =>
{
b.HasOne("Flight.Aircrafts.Models.Aircraft", null)
.WithMany()
.HasForeignKey("AircraftId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired()
.HasConstraintName("fk_flight_aircraft_aircraft_id");
b.HasOne("Flight.Airports.Models.Airport", null)

View File

@ -28,9 +28,9 @@ public static class InitialData
Aircrafts = new List<Aircraft>
{
Aircraft.Create(new Guid("3c5c0000-97c6-fc34-fcd3-08db322230c8"), NameValue.Of("Boeing 737"), ModelValue.Of("B737"), ManufacturingYearValue.Of(2005)),
Aircraft.Create(new Guid("3c5c0000-97c6-fc34-2e04-08db322230c9"), NameValue.Of("Airbus 300"), ModelValue.Of("A300"), ManufacturingYearValue.Of(2000)),
Aircraft.Create(new Guid("3c5c0000-97c6-fc34-2e11-08db322230c9"), NameValue.Of("Airbus 320"), ModelValue.Of("A320"), ManufacturingYearValue.Of(2003))
Aircraft.Create(AircraftId.Of(new Guid("3c5c0000-97c6-fc34-fcd3-08db322230c8")), Name.Of("Boeing 737"), Model.Of("B737"), ManufacturingYear.Of(2005)),
Aircraft.Create(AircraftId.Of(new Guid("3c5c0000-97c6-fc34-2e04-08db322230c9")), Name.Of("Airbus 300"), Model.Of("A300"), ManufacturingYear.Of(2000)),
Aircraft.Create(AircraftId.Of(new Guid("3c5c0000-97c6-fc34-2e11-08db322230c9")), Name.Of("Airbus 320"), Model.Of("A320"), ManufacturingYear.Of(2003))
};

View File

@ -3,6 +3,7 @@ namespace Flight.Flights.Features.CreatingFlight.V1;
using System;
using System.Threading;
using System.Threading.Tasks;
using Aircrafts.Models.ValueObjects;
using Ardalis.GuardClauses;
using BuildingBlocks.Core.CQRS;
using BuildingBlocks.Core.Event;
@ -111,7 +112,7 @@ internal class CreateFlightHandler : ICommandHandler<CreateFlight, CreateFlightR
throw new FlightAlreadyExistException();
}
var flightEntity = Models.Flight.Create(request.Id, request.FlightNumber, request.AircraftId,
var flightEntity = Models.Flight.Create(request.Id, request.FlightNumber, AircraftId.Of(request.AircraftId),
request.DepartureAirportId, request.DepartureDate,
request.ArriveDate, request.ArriveAirportId, request.DurationMinutes, request.FlightDate, request.Status,
request.Price);

View File

@ -3,6 +3,7 @@ namespace Flight.Flights.Features.UpdatingFlight.V1;
using System;
using System.Threading;
using System.Threading.Tasks;
using Aircrafts.Models.ValueObjects;
using Ardalis.GuardClauses;
using BuildingBlocks.Caching;
using BuildingBlocks.Core.CQRS;
@ -110,7 +111,7 @@ internal class UpdateFlightHandler : ICommandHandler<UpdateFlight, UpdateFlightR
}
flight.Update(request.Id, request.FlightNumber, request.AircraftId, request.DepartureAirportId,
flight.Update(request.Id, request.FlightNumber, AircraftId.Of(request.AircraftId), request.DepartureAirportId,
request.DepartureDate,
request.ArriveDate, request.ArriveAirportId, request.DurationMinutes, request.FlightDate, request.Status,
request.Price, request.IsDeleted);

View File

@ -6,11 +6,12 @@ namespace Flight.Flights.Models;
using Features.CreatingFlight.V1;
using Features.DeletingFlight.V1;
using Features.UpdatingFlight.V1;
using global::Flight.Aircrafts.Models.ValueObjects;
public record Flight : Aggregate<Guid>
{
public string FlightNumber { get; private set; }
public Guid AircraftId { get; private set; }
public AircraftId AircraftId { get; private set; }
public DateTime DepartureDate { get; private set; }
public Guid DepartureAirportId { get; private set; }
public DateTime ArriveDate { get; private set; }
@ -20,7 +21,7 @@ public record Flight : Aggregate<Guid>
public Enums.FlightStatus Status { get; private set; }
public decimal Price { get; private set; }
public static Flight Create(Guid id, string flightNumber, Guid aircraftId,
public static Flight Create(Guid id, string flightNumber, AircraftId aircraftId,
Guid departureAirportId, DateTime departureDate, DateTime arriveDate,
Guid arriveAirportId, decimal durationMinutes, DateTime flightDate, Enums.FlightStatus status,
decimal price, bool isDeleted = false)
@ -52,7 +53,7 @@ public record Flight : Aggregate<Guid>
}
public void Update(Guid id, string flightNumber, Guid aircraftId,
public void Update(Guid id, string flightNumber, AircraftId aircraftId,
Guid departureAirportId, DateTime departureDate, DateTime arriveDate,
Guid arriveAirportId, decimal durationMinutes, DateTime flightDate, Enums.FlightStatus status,
decimal price, bool isDeleted = false)
@ -75,7 +76,7 @@ public record Flight : Aggregate<Guid>
AddDomainEvent(@event);
}
public void Delete(Guid id, string flightNumber, Guid aircraftId,
public void Delete(Guid id, string flightNumber, AircraftId aircraftId,
Guid departureAirportId, DateTime departureDate, DateTime arriveDate,
Guid arriveAirportId, decimal durationMinutes, DateTime flightDate, Enums.FlightStatus status,
decimal price, bool isDeleted = true)

View File

@ -46,16 +46,16 @@ public static class DbContextFactory
var aircrafts = new List<global::Flight.Aircrafts.Models.Aircraft>
{
global::Flight.Aircrafts.Models.Aircraft.Create(_aircraft1, NameValue.Of("Boeing 737"), ModelValue.Of("B737"), ManufacturingYearValue.Of(2005)),
global::Flight.Aircrafts.Models.Aircraft.Create(_aircraft2, NameValue.Of("Airbus 300"), ModelValue.Of("A300"), ManufacturingYearValue.Of(2000)),
global::Flight.Aircrafts.Models.Aircraft.Create(_aircraft3, NameValue.Of("Airbus 320"), ModelValue.Of("A320"), ManufacturingYearValue.Of(2003))
global::Flight.Aircrafts.Models.Aircraft.Create(AircraftId.Of(_aircraft1), Name.Of("Boeing 737"), Model.Of("B737"), ManufacturingYear.Of(2005)),
global::Flight.Aircrafts.Models.Aircraft.Create(AircraftId.Of(_aircraft2), Name.Of("Airbus 300"), Model.Of("A300"), ManufacturingYear.Of(2000)),
global::Flight.Aircrafts.Models.Aircraft.Create(AircraftId.Of(_aircraft3), Name.Of("Airbus 320"), Model.Of("A320"), ManufacturingYear.Of(2003))
};
context.Aircraft.AddRange(aircrafts);
var flights = new List<global::Flight.Flights.Models.Flight>
{
global::Flight.Flights.Models.Flight.Create(_flightId1, "BD467", _aircraft1, _airportId1,
global::Flight.Flights.Models.Flight.Create(_flightId1, "BD467", AircraftId.Of(_aircraft1), _airportId1,
new DateTime(2022, 1, 31, 12, 0, 0),
new DateTime(2022, 1, 31, 14, 0, 0),
_airportId2, 120m,

View File

@ -1,4 +1,4 @@
using AutoBogus;
using AutoBogus;
namespace Unit.Test.Fakes;

View File

@ -1,4 +1,6 @@
namespace Unit.Test.Fakes;
namespace Unit.Test.Fakes;
using global::Flight.Aircrafts.Models.ValueObjects;
public static class FakeFlightCreate
{
@ -7,7 +9,7 @@ public static class FakeFlightCreate
var command = new FakeCreateFlightCommand().Generate();
return global::Flight.Flights.Models.Flight.Create(command.Id, command.FlightNumber,
command.AircraftId, command.DepartureAirportId, command.DepartureDate,
AircraftId.Of(command.AircraftId), command.DepartureAirportId, command.DepartureDate,
command.ArriveDate, command.ArriveAirportId, command.DurationMinutes,
command.FlightDate, command.Status, command.Price);
}

View File

@ -3,16 +3,58 @@ using Microsoft.EntityFrameworkCore.Metadata.Builders;
namespace Passenger.Data.Configurations;
public class PassengerConfiguration: IEntityTypeConfiguration<Passengers.Models.Passenger>
using Passengers.Models.ValueObjects;
public class PassengerConfiguration : IEntityTypeConfiguration<Passengers.Models.Passenger>
{
public void Configure(EntityTypeBuilder<Passengers.Models.Passenger> builder)
{
builder.ToTable(nameof(Passenger));
builder.ToTable(nameof(Passengers.Models.Passenger));
builder.HasKey(r => r.Id);
builder.Property(r => r.Id).ValueGeneratedNever();
builder.Property(r => r.Id).ValueGeneratedNever()
.HasConversion<Guid>(passengerId => passengerId.Value, dbId => PassengerId.Of(dbId));
// // ref: https://learn.microsoft.com/en-us/ef/core/saving/concurrency?tabs=fluent-api
builder.Property(r => r.Version).IsConcurrencyToken();
builder.OwnsOne(
x => x.Name,
a =>
{
a.Property(p => p.Value)
.HasColumnName(nameof(Passengers.Models.Passenger.Name))
.HasMaxLength(50)
.IsRequired();
}
);
builder.OwnsOne(
x => x.PassportNumber,
a =>
{
a.Property(p => p.Value)
.HasColumnName(nameof(Passengers.Models.Passenger.PassportNumber))
.HasMaxLength(10)
.IsRequired();
}
);
builder.OwnsOne(
x => x.Age,
a =>
{
a.Property(p => p.Value)
.HasColumnName(nameof(Passengers.Models.Passenger.Age))
.HasMaxLength(3)
.IsRequired();
}
);
builder.Property(x => x.PassengerType)
.IsRequired()
.HasDefaultValue(Passengers.Enums.PassengerType.Unknown)
.HasConversion(
x => x.ToString(),
x => (Passengers.Enums.PassengerType)Enum.Parse(typeof(Passengers.Enums.PassengerType), x));
}
}

View File

@ -0,0 +1,148 @@
// <auto-generated />
using System;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
using Passenger.Data;
#nullable disable
namespace Passenger.Data.Migrations
{
[DbContext(typeof(PassengerDbContext))]
[Migration("20230524195049_AddValueObject")]
partial class AddValueObject
{
/// <inheritdoc />
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "7.0.5")
.HasAnnotation("Relational:MaxIdentifierLength", 63);
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
modelBuilder.Entity("Passenger.Passengers.Models.Passenger", b =>
{
b.Property<Guid>("Id")
.HasColumnType("uuid")
.HasColumnName("id");
b.Property<DateTime?>("CreatedAt")
.HasColumnType("timestamp without time zone")
.HasColumnName("created_at");
b.Property<long?>("CreatedBy")
.HasColumnType("bigint")
.HasColumnName("created_by");
b.Property<bool>("IsDeleted")
.HasColumnType("boolean")
.HasColumnName("is_deleted");
b.Property<DateTime?>("LastModified")
.HasColumnType("timestamp without time zone")
.HasColumnName("last_modified");
b.Property<long?>("LastModifiedBy")
.HasColumnType("bigint")
.HasColumnName("last_modified_by");
b.Property<string>("PassengerType")
.IsRequired()
.ValueGeneratedOnAdd()
.HasColumnType("text")
.HasDefaultValue("Unknown")
.HasColumnName("passenger_type");
b.Property<long>("Version")
.IsConcurrencyToken()
.HasColumnType("bigint")
.HasColumnName("version");
b.HasKey("Id")
.HasName("pk_passenger");
b.ToTable("passenger", (string)null);
});
modelBuilder.Entity("Passenger.Passengers.Models.Passenger", b =>
{
b.OwnsOne("Passenger.Passengers.Models.ValueObjects.Age", "Age", b1 =>
{
b1.Property<Guid>("PassengerId")
.HasColumnType("uuid")
.HasColumnName("id");
b1.Property<int>("Value")
.HasMaxLength(3)
.HasColumnType("integer")
.HasColumnName("age");
b1.HasKey("PassengerId")
.HasName("pk_passenger");
b1.ToTable("passenger");
b1.WithOwner()
.HasForeignKey("PassengerId")
.HasConstraintName("fk_passenger_passenger_id");
});
b.OwnsOne("Passenger.Passengers.Models.ValueObjects.Name", "Name", b1 =>
{
b1.Property<Guid>("PassengerId")
.HasColumnType("uuid")
.HasColumnName("id");
b1.Property<string>("Value")
.IsRequired()
.HasMaxLength(50)
.HasColumnType("character varying(50)")
.HasColumnName("name");
b1.HasKey("PassengerId")
.HasName("pk_passenger");
b1.ToTable("passenger");
b1.WithOwner()
.HasForeignKey("PassengerId")
.HasConstraintName("fk_passenger_passenger_id");
});
b.OwnsOne("Passenger.Passengers.Models.ValueObjects.PassportNumber", "PassportNumber", b1 =>
{
b1.Property<Guid>("PassengerId")
.HasColumnType("uuid")
.HasColumnName("id");
b1.Property<string>("Value")
.IsRequired()
.HasMaxLength(10)
.HasColumnType("character varying(10)")
.HasColumnName("passport_number");
b1.HasKey("PassengerId")
.HasName("pk_passenger");
b1.ToTable("passenger");
b1.WithOwner()
.HasForeignKey("PassengerId")
.HasConstraintName("fk_passenger_passenger_id");
});
b.Navigation("Age");
b.Navigation("Name");
b.Navigation("PassportNumber");
});
#pragma warning restore 612, 618
}
}
}

View File

@ -0,0 +1,133 @@
using System;
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace Passenger.Data.Migrations
{
/// <inheritdoc />
public partial class AddValueObject : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AlterColumn<string>(
name: "passport_number",
table: "passenger",
type: "character varying(10)",
maxLength: 10,
nullable: true,
oldClrType: typeof(string),
oldType: "text",
oldNullable: true);
migrationBuilder.AlterColumn<string>(
name: "passenger_type",
table: "passenger",
type: "text",
nullable: false,
defaultValue: "Unknown",
oldClrType: typeof(int),
oldType: "integer");
migrationBuilder.AlterColumn<string>(
name: "name",
table: "passenger",
type: "character varying(50)",
maxLength: 50,
nullable: true,
oldClrType: typeof(string),
oldType: "text",
oldNullable: true);
migrationBuilder.AlterColumn<DateTime>(
name: "last_modified",
table: "passenger",
type: "timestamp without time zone",
nullable: true,
oldClrType: typeof(DateTime),
oldType: "timestamp with time zone",
oldNullable: true);
migrationBuilder.AlterColumn<DateTime>(
name: "created_at",
table: "passenger",
type: "timestamp without time zone",
nullable: true,
oldClrType: typeof(DateTime),
oldType: "timestamp with time zone",
oldNullable: true);
migrationBuilder.AlterColumn<int>(
name: "age",
table: "passenger",
type: "integer",
maxLength: 3,
nullable: true,
oldClrType: typeof(int),
oldType: "integer");
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.AlterColumn<string>(
name: "passport_number",
table: "passenger",
type: "text",
nullable: true,
oldClrType: typeof(string),
oldType: "character varying(10)",
oldMaxLength: 10,
oldNullable: true);
migrationBuilder.AlterColumn<int>(
name: "passenger_type",
table: "passenger",
type: "integer",
nullable: false,
oldClrType: typeof(string),
oldType: "text",
oldDefaultValue: "Unknown");
migrationBuilder.AlterColumn<string>(
name: "name",
table: "passenger",
type: "text",
nullable: true,
oldClrType: typeof(string),
oldType: "character varying(50)",
oldMaxLength: 50,
oldNullable: true);
migrationBuilder.AlterColumn<DateTime>(
name: "last_modified",
table: "passenger",
type: "timestamp with time zone",
nullable: true,
oldClrType: typeof(DateTime),
oldType: "timestamp without time zone",
oldNullable: true);
migrationBuilder.AlterColumn<DateTime>(
name: "created_at",
table: "passenger",
type: "timestamp with time zone",
nullable: true,
oldClrType: typeof(DateTime),
oldType: "timestamp without time zone",
oldNullable: true);
migrationBuilder.AlterColumn<int>(
name: "age",
table: "passenger",
type: "integer",
nullable: false,
defaultValue: 0,
oldClrType: typeof(int),
oldType: "integer",
oldMaxLength: 3,
oldNullable: true);
}
}
}

View File

@ -0,0 +1,148 @@
// <auto-generated />
using System;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
using Passenger.Data;
#nullable disable
namespace Passenger.Data.Migrations
{
[DbContext(typeof(PassengerDbContext))]
[Migration("20230526085126_change-behavior")]
partial class changebehavior
{
/// <inheritdoc />
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "7.0.2")
.HasAnnotation("Relational:MaxIdentifierLength", 63);
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
modelBuilder.Entity("Passenger.Passengers.Models.Passenger", b =>
{
b.Property<Guid>("Id")
.HasColumnType("uuid")
.HasColumnName("id");
b.Property<DateTime?>("CreatedAt")
.HasColumnType("timestamp with time zone")
.HasColumnName("created_at");
b.Property<long?>("CreatedBy")
.HasColumnType("bigint")
.HasColumnName("created_by");
b.Property<bool>("IsDeleted")
.HasColumnType("boolean")
.HasColumnName("is_deleted");
b.Property<DateTime?>("LastModified")
.HasColumnType("timestamp with time zone")
.HasColumnName("last_modified");
b.Property<long?>("LastModifiedBy")
.HasColumnType("bigint")
.HasColumnName("last_modified_by");
b.Property<string>("PassengerType")
.IsRequired()
.ValueGeneratedOnAdd()
.HasColumnType("text")
.HasDefaultValue("Unknown")
.HasColumnName("passenger_type");
b.Property<long>("Version")
.IsConcurrencyToken()
.HasColumnType("bigint")
.HasColumnName("version");
b.HasKey("Id")
.HasName("pk_passenger");
b.ToTable("passenger", (string)null);
});
modelBuilder.Entity("Passenger.Passengers.Models.Passenger", b =>
{
b.OwnsOne("Passenger.Passengers.Models.ValueObjects.Age", "Age", b1 =>
{
b1.Property<Guid>("PassengerId")
.HasColumnType("uuid")
.HasColumnName("id");
b1.Property<int>("Value")
.HasMaxLength(3)
.HasColumnType("integer")
.HasColumnName("age");
b1.HasKey("PassengerId")
.HasName("pk_passenger");
b1.ToTable("passenger");
b1.WithOwner()
.HasForeignKey("PassengerId")
.HasConstraintName("fk_passenger_passenger_id");
});
b.OwnsOne("Passenger.Passengers.Models.ValueObjects.Name", "Name", b1 =>
{
b1.Property<Guid>("PassengerId")
.HasColumnType("uuid")
.HasColumnName("id");
b1.Property<string>("Value")
.IsRequired()
.HasMaxLength(50)
.HasColumnType("character varying(50)")
.HasColumnName("name");
b1.HasKey("PassengerId")
.HasName("pk_passenger");
b1.ToTable("passenger");
b1.WithOwner()
.HasForeignKey("PassengerId")
.HasConstraintName("fk_passenger_passenger_id");
});
b.OwnsOne("Passenger.Passengers.Models.ValueObjects.PassportNumber", "PassportNumber", b1 =>
{
b1.Property<Guid>("PassengerId")
.HasColumnType("uuid")
.HasColumnName("id");
b1.Property<string>("Value")
.IsRequired()
.HasMaxLength(10)
.HasColumnType("character varying(10)")
.HasColumnName("passport_number");
b1.HasKey("PassengerId")
.HasName("pk_passenger");
b1.ToTable("passenger");
b1.WithOwner()
.HasForeignKey("PassengerId")
.HasConstraintName("fk_passenger_passenger_id");
});
b.Navigation("Age");
b.Navigation("Name");
b.Navigation("PassportNumber");
});
#pragma warning restore 612, 618
}
}
}

View File

@ -0,0 +1,55 @@
using System;
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace Passenger.Data.Migrations
{
/// <inheritdoc />
public partial class changebehavior : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AlterColumn<DateTime>(
name: "last_modified",
table: "passenger",
type: "timestamp with time zone",
nullable: true,
oldClrType: typeof(DateTime),
oldType: "timestamp without time zone",
oldNullable: true);
migrationBuilder.AlterColumn<DateTime>(
name: "created_at",
table: "passenger",
type: "timestamp with time zone",
nullable: true,
oldClrType: typeof(DateTime),
oldType: "timestamp without time zone",
oldNullable: true);
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.AlterColumn<DateTime>(
name: "last_modified",
table: "passenger",
type: "timestamp without time zone",
nullable: true,
oldClrType: typeof(DateTime),
oldType: "timestamp with time zone",
oldNullable: true);
migrationBuilder.AlterColumn<DateTime>(
name: "created_at",
table: "passenger",
type: "timestamp without time zone",
nullable: true,
oldClrType: typeof(DateTime),
oldType: "timestamp with time zone",
oldNullable: true);
}
}
}

View File

@ -28,10 +28,6 @@ namespace Passenger.Data.Migrations
.HasColumnType("uuid")
.HasColumnName("id");
b.Property<int>("Age")
.HasColumnType("integer")
.HasColumnName("age");
b.Property<DateTime?>("CreatedAt")
.HasColumnType("timestamp with time zone")
.HasColumnName("created_at");
@ -52,18 +48,13 @@ namespace Passenger.Data.Migrations
.HasColumnType("bigint")
.HasColumnName("last_modified_by");
b.Property<string>("Name")
b.Property<string>("PassengerType")
.IsRequired()
.ValueGeneratedOnAdd()
.HasColumnType("text")
.HasColumnName("name");
b.Property<int>("PassengerType")
.HasColumnType("integer")
.HasDefaultValue("Unknown")
.HasColumnName("passenger_type");
b.Property<string>("PassportNumber")
.HasColumnType("text")
.HasColumnName("passport_number");
b.Property<long>("Version")
.IsConcurrencyToken()
.HasColumnType("bigint")
@ -74,6 +65,80 @@ namespace Passenger.Data.Migrations
b.ToTable("passenger", (string)null);
});
modelBuilder.Entity("Passenger.Passengers.Models.Passenger", b =>
{
b.OwnsOne("Passenger.Passengers.Models.ValueObjects.Age", "Age", b1 =>
{
b1.Property<Guid>("PassengerId")
.HasColumnType("uuid")
.HasColumnName("id");
b1.Property<int>("Value")
.HasMaxLength(3)
.HasColumnType("integer")
.HasColumnName("age");
b1.HasKey("PassengerId")
.HasName("pk_passenger");
b1.ToTable("passenger");
b1.WithOwner()
.HasForeignKey("PassengerId")
.HasConstraintName("fk_passenger_passenger_id");
});
b.OwnsOne("Passenger.Passengers.Models.ValueObjects.Name", "Name", b1 =>
{
b1.Property<Guid>("PassengerId")
.HasColumnType("uuid")
.HasColumnName("id");
b1.Property<string>("Value")
.IsRequired()
.HasMaxLength(50)
.HasColumnType("character varying(50)")
.HasColumnName("name");
b1.HasKey("PassengerId")
.HasName("pk_passenger");
b1.ToTable("passenger");
b1.WithOwner()
.HasForeignKey("PassengerId")
.HasConstraintName("fk_passenger_passenger_id");
});
b.OwnsOne("Passenger.Passengers.Models.ValueObjects.PassportNumber", "PassportNumber", b1 =>
{
b1.Property<Guid>("PassengerId")
.HasColumnType("uuid")
.HasColumnName("id");
b1.Property<string>("Value")
.IsRequired()
.HasMaxLength(10)
.HasColumnType("character varying(10)")
.HasColumnName("passport_number");
b1.HasKey("PassengerId")
.HasName("pk_passenger");
b1.ToTable("passenger");
b1.WithOwner()
.HasForeignKey("PassengerId")
.HasConstraintName("fk_passenger_passenger_id");
});
b.Navigation("Age");
b.Navigation("Name");
b.Navigation("PassportNumber");
});
#pragma warning restore 612, 618
}
}

View File

@ -1,7 +1,7 @@
using System.Reflection;
using BuildingBlocks.EFCore;
using Microsoft.EntityFrameworkCore;
using BuildingBlocks.Web;
using Microsoft.EntityFrameworkCore;
namespace Passenger.Data;

View File

@ -0,0 +1,12 @@
namespace Passenger.Exceptions;
using System;
using BuildingBlocks.Exception;
public class InvalidPassengerIdExceptions : BadRequestException
{
public InvalidPassengerIdExceptions(Guid passengerId)
: base($"PassengerId: '{passengerId}' is invalid.")
{
}
}

View File

@ -38,15 +38,15 @@ public class RegisterNewUserHandler : IConsumer<UserCreated>
_logger.LogInformation($"consumer for {nameof(UserCreated).Underscore()} in {_options.Name}");
var passengerExist =
await _passengerDbContext.Passengers.AnyAsync(x => x.PassportNumber == context.Message.PassportNumber);
await _passengerDbContext.Passengers.AnyAsync(x => x.PassportNumber == PassportNumber.Of(context.Message.PassportNumber));
if (passengerExist)
{
return;
}
var passenger = Passengers.Models.Passenger.Create(NewId.NextGuid(), NameValue.Of(context.Message.Name),
PassportNumberValue.Of(context.Message.PassportNumber));
var passenger = Passengers.Models.Passenger.Create(PassengerId.Of(NewId.NextGuid()), Name.Of(context.Message.Name),
PassportNumber.Of(context.Message.PassportNumber));
await _passengerDbContext.AddAsync(passenger);

View File

@ -1,3 +1,2 @@
namespace Passenger.Passengers.Dtos;
public record PassengerDto(Guid Id, string Name, string PassportNumber, Enums.PassengerType PassengerType, int Age);

View File

@ -96,8 +96,11 @@ internal class CompleteRegisterPassengerCommandHandler : ICommandHandler<Complet
{
Guard.Against.Null(request, nameof(request));
var passenger = await _passengerDbContext.Passengers.AsNoTracking().SingleOrDefaultAsync(
x => x.PassportNumber == request.PassportNumber, cancellationToken);
//var passenger = await _passengerDbContext.Passengers.AsNoTracking().SingleOrDefaultAsync(
// x => x.PassportNumber == PassportNumber.Of(request.PassportNumber), cancellationToken);
var passenger = _passengerDbContext.Passengers.AsEnumerable()
.FirstOrDefault(a => a.PassportNumber.Equals(PassportNumber.Of(request.PassportNumber)));
if (passenger is null)
{
@ -105,7 +108,7 @@ internal class CompleteRegisterPassengerCommandHandler : ICommandHandler<Complet
}
var passengerEntity = passenger.CompleteRegistrationPassenger(passenger.Id, passenger.Name,
passenger.PassportNumber, request.PassengerType, AgeValue.Of(request.Age));
passenger.PassportNumber, request.PassengerType, Age.Of(request.Age));
var updatePassenger = _passengerDbContext.Passengers.Update(passengerEntity);

View File

@ -1,14 +1,15 @@
namespace Passenger.Passengers.Features.CompletingRegisterPassenger.V1;
namespace Passenger.Passengers.Features.CompletingRegisterPassenger.V1;
using Ardalis.GuardClauses;
using BuildingBlocks.Core.CQRS;
using BuildingBlocks.Core.Event;
using Data;
using MapsterMapper;
using MediatR;
using Models;
using Models.ValueObjects;
using MongoDB.Driver;
using MongoDB.Driver.Linq;
using Data;
public record CompleteRegisterPassengerMongoCommand(Guid Id, string PassportNumber, string Name,
Enums.PassengerType PassengerType, int Age, bool IsDeleted = false) : InternalCommand;
@ -34,14 +35,14 @@ internal class CompleteRegisterPassengerMongoHandler : ICommandHandler<CompleteR
var passengerReadModel = _mapper.Map<PassengerReadModel>(request);
var passenger = await _passengerReadDbContext.Passenger.AsQueryable()
.FirstOrDefaultAsync(x => x.PassengerId == passengerReadModel.PassengerId && !x.IsDeleted, cancellationToken);
.FirstOrDefaultAsync(x => x.PassengerId == PassengerId.Of(passengerReadModel.PassengerId) && !x.IsDeleted, cancellationToken);
if (passenger is not null)
{
await _passengerReadDbContext.Passenger.UpdateOneAsync(
x => x.PassengerId == passengerReadModel.PassengerId,
x => x.PassengerId == PassengerId.Of(passengerReadModel.PassengerId),
Builders<PassengerReadModel>.Update
.Set(x => x.PassengerId, passengerReadModel.PassengerId)
.Set(x => x.PassengerId, PassengerId.Of(passengerReadModel.PassengerId))
.Set(x => x.Age, passengerReadModel.Age)
.Set(x => x.Name, passengerReadModel.Name)
.Set(x => x.IsDeleted, passengerReadModel.IsDeleted)

View File

@ -1,18 +1,19 @@
namespace Passenger.Passengers.Features.GettingPassengerById.Queries.V1;
using Ardalis.GuardClauses;
using BuildingBlocks.Core.CQRS;
using BuildingBlocks.Web;
using Data;
using Dtos;
using FluentValidation;
using MapsterMapper;
using Ardalis.GuardClauses;
using BuildingBlocks.Web;
using Duende.IdentityServer.EntityFramework.Entities;
using Exceptions;
using FluentValidation;
using MapsterMapper;
using MediatR;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Routing;
using Models.ValueObjects;
using MongoDB.Driver;
using MongoDB.Driver.Linq;
@ -74,7 +75,7 @@ internal class GetPassengerByIdHandler : IQueryHandler<GetPassengerById, GetPass
var passenger =
await _passengerReadDbContext.Passenger.AsQueryable()
.SingleOrDefaultAsync(x => x.PassengerId == query.Id && x.IsDeleted == false, cancellationToken);
.SingleOrDefaultAsync(x => x.PassengerId == PassengerId.Of(query.Id) && x.IsDeleted == false, cancellationToken);
if (passenger is null)
{

View File

@ -6,14 +6,15 @@ using CompletingRegisterPassenger.V1;
using Dtos;
using MassTransit;
using Models;
using Passenger.Passengers.Models.ValueObjects;
public class PassengerMappings : IRegister
{
public void Register(TypeAdapterConfig config)
{
config.NewConfig<CompleteRegisterPassengerMongoCommand, PassengerReadModel>()
.Map(d => d.Id, s => NewId.NextGuid())
.Map(d => d.PassengerId, s => s.Id);
.Map(d => d.Id, s => NewId.NextGuid())
.Map(d => d.PassengerId, s => PassengerId.Of(s.Id));
config.NewConfig<CompleteRegisterPassengerRequestDto, CompleteRegisterPassenger>()
.ConstructUsing(x => new CompleteRegisterPassenger(x.PassportNumber, x.PassengerType, x.Age));

View File

@ -6,9 +6,14 @@ using Features.CompletingRegisterPassenger.V1;
using global::Passenger.Passengers.Models.ValueObjects;
using Identity.Consumers.RegisteringNewUser.V1;
public record Passenger : Aggregate<Guid>
public record Passenger : Aggregate<PassengerId>
{
public Passenger CompleteRegistrationPassenger(Guid id, NameValue name, PassportNumberValue passportNumber, Enums.PassengerType passengerType, AgeValue age, bool isDeleted = false)
public PassportNumber PassportNumber { get; private set; }
public Name Name { get; private set; }
public Enums.PassengerType PassengerType { get; private set; }
public Age Age { get; private set; }
public Passenger CompleteRegistrationPassenger(PassengerId id, Name name, PassportNumber passportNumber, Enums.PassengerType passengerType, Age age, bool isDeleted = false)
{
var passenger = new Passenger
{
@ -29,7 +34,7 @@ public record Passenger : Aggregate<Guid>
}
public static Passenger Create(Guid id, NameValue name, PassportNumberValue passportNumber, bool isDeleted = false)
public static Passenger Create(PassengerId id, Name name, PassportNumber passportNumber, bool isDeleted = false)
{
var passenger = new Passenger { Id = id, Name = name, PassportNumber = passportNumber, IsDeleted = isDeleted };
@ -39,10 +44,4 @@ public record Passenger : Aggregate<Guid>
return passenger;
}
public PassportNumberValue PassportNumber { get; private set; }
public NameValue Name { get; private set; }
public Enums.PassengerType PassengerType { get; private set; }
public AgeValue Age { get; private set; }
}

View File

@ -1,5 +1,4 @@
namespace Passenger.Passengers.Models;
namespace Passenger.Passengers.Models;
public class PassengerReadModel
{
public required Guid Id { get; init; }

View File

@ -1,9 +1,9 @@
namespace Passenger.Passengers.Models.ValueObjects;
using System;
public record AgeValue : GenericValueObject<int>
public record Age : GenericValueObject<int>
{
public AgeValue(int value) : base(value)
public Age(int value) : base(value)
{
if (value < 0)
{
@ -11,8 +11,8 @@ public record AgeValue : GenericValueObject<int>
}
Value = value;
}
public static AgeValue Of(int value)
public static Age Of(int value)
{
return new AgeValue(value);
return new Age(value);
}
}

View File

@ -1,9 +1,9 @@
namespace Passenger.Passengers.Models.ValueObjects;
using System;
public record NameValue : GenericValueObject<string>
public record Name : GenericValueObject<string>
{
public NameValue(string value) : base(value)
public Name(string value) : base(value)
{
if (string.IsNullOrWhiteSpace(value))
{
@ -11,8 +11,8 @@ public record NameValue : GenericValueObject<string>
}
Value = value;
}
public static NameValue Of(string value)
public static Name Of(string value)
{
return new NameValue(value);
return new Name(value);
}
}

View File

@ -0,0 +1,28 @@
namespace Passenger.Passengers.Models.ValueObjects;
using System;
using global::Passenger.Exceptions;
public record PassengerId
{
public Guid Value { get; }
private PassengerId(Guid value)
{
if (value == Guid.Empty)
{
throw new InvalidPassengerIdExceptions(value);
}
Value = value;
}
public static PassengerId Of(Guid value)
{
return new PassengerId(value);
}
public static implicit operator Guid(PassengerId passengerId)
{
return passengerId.Value;
}
}

View File

@ -0,0 +1,67 @@
namespace Passenger.Passengers.Models.ValueObjects;
using System;
//public record PassportNumber : GenericValueObject<string>
//{
// public PassportNumber(string value) : base(value)
// {
// if (string.IsNullOrWhiteSpace(value))
// {
// throw new ArgumentException("Passport number cannot be empty or whitespace.");
// }
// Value = value;
// }
// public static PassportNumber Of(string value)
// {
// return new PassportNumber(value);
// }
//}
//public record PassportNumber
//{
// public string Value { get; }
// public PassportNumber(string value)
// {
// if (string.IsNullOrWhiteSpace(value))
// {
// throw new ArgumentException("Passport number cannot be empty or whitespace.");
// }
// Value = value;
// }
// public static PassportNumber Of(string value)
// {
// return new PassportNumber(value);
// }
// public static implicit operator string(PassportNumber aircraftId)
// {
// return aircraftId.Value;
// }
//}
public record PassportNumber
{
public string Value { get; }
public override string ToString()
{
return Value;
}
private PassportNumber(string value)
{
if (string.IsNullOrWhiteSpace(value))
{
throw new ArgumentException("Passport number cannot be empty or whitespace.");
}
Value = value;
}
public static PassportNumber Of(string value)
{
return new PassportNumber(value);
}
public static implicit operator string(PassportNumber passportNumber) => passportNumber.Value;
}

View File

@ -1,19 +0,0 @@
namespace Passenger.Passengers.Models.ValueObjects;
using System;
public record PassportNumberValue : GenericValueObject<string>
{
public PassportNumberValue(string value) : base(value)
{
if (string.IsNullOrWhiteSpace(value))
{
throw new ArgumentException("Passport number cannot be empty or whitespace.");
}
Value = value;
}
public static PassportNumberValue Of(string value)
{
return new PassportNumberValue(value);
}
}

View File

@ -1,4 +1,4 @@
using System.Threading.Tasks;
using System.Threading.Tasks;
using BuildingBlocks.Contracts.EventBus.Messages;
using BuildingBlocks.TestBase;
using FluentAssertions;
@ -8,9 +8,9 @@ using Passenger.Data;
using Xunit;
namespace Integration.Test.Passenger.Features;
public class CompleteRegisterPassengerTests : PassengerIntegrationTestBase
{
public CompleteRegisterPassengerTests(
TestFixture<Program, PassengerDbContext, PassengerReadDbContext> integrationTestFactory) : base(integrationTestFactory)
{
@ -23,8 +23,8 @@ public class CompleteRegisterPassengerTests : PassengerIntegrationTestBase
var userCreated = new FakeUserCreated().Generate();
await Fixture.Publish(userCreated);
await Fixture.WaitForPublishing<UserCreated>();
await Fixture.WaitForConsuming<UserCreated>();
(await Fixture.WaitForPublishing<UserCreated>()).Should().Be(true);
(await Fixture.WaitForConsuming<UserCreated>()).Should().Be(true);
var command = new FakeCompleteRegisterPassengerCommand(userCreated.PassportNumber).Generate();