SHOW:
|
|
- or go back to the newest paste.
| 1 | namespace PetClinic.Domain.Appointments.Factories | |
| 2 | {
| |
| 3 | using Appointments.Models; | |
| 4 | using Common.Exceptions; | |
| 5 | using Common.SharedKernel; | |
| 6 | using PetClinic.Domain.Common; | |
| 7 | using System; | |
| 8 | using System.Collections.Generic; | |
| 9 | using System.Linq.Expressions; | |
| 10 | ||
| 11 | internal class AppointmentFactory : IAppointmentFactory | |
| 12 | {
| |
| 13 | private readonly IClientFactory clientFactory; | |
| 14 | private readonly IDoctorFactory doctorFactory; | |
| 15 | ||
| 16 | private AppointmentDate appointmentDate = default!; | |
| 17 | private Client client = default!; | |
| 18 | private Doctor doctor = default!; | |
| 19 | private OfficeRoom officeRoom = default!; | |
| 20 | ||
| 21 | internal AppointmentFactory( | |
| 22 | IClientFactory clientFactory, | |
| 23 | IDoctorFactory doctorFactory) | |
| 24 | {
| |
| 25 | this.clientFactory = clientFactory; | |
| 26 | this.doctorFactory = doctorFactory; | |
| 27 | } | |
| 28 | ||
| 29 | public Appointment Build() | |
| 30 | {
| |
| 31 | if (this.appointmentDate is null | |
| 32 | || this.client is null | |
| 33 | || this.doctor is null | |
| 34 | || this.officeRoom is null) | |
| 35 | {
| |
| 36 | throw new InvalidAppointmentException("Invalid appointment input.");
| |
| 37 | } | |
| 38 | ||
| 39 | return new Appointment(this.doctor, this.client, this.appointmentDate, this.officeRoom); | |
| 40 | } | |
| 41 | ||
| 42 | public IAppointmentFactory WithAppointmentDate(DateTime startDate, DateTime endDate) | |
| 43 | {
| |
| 44 | this.appointmentDate = new AppointmentDate(startDate, endDate); | |
| 45 | return this; | |
| 46 | } | |
| 47 | ||
| 48 | public IAppointmentFactory WithClient(Expression<Action<IClientFactory>> clientExpression) | |
| 49 | {
| |
| 50 | var dict = new Dictionary<string, string>(); | |
| 51 | this.ParseExpression(clientExpression, string.Empty, dict); | |
| 52 | ||
| 53 | this.client = this.clientFactory | |
| 54 | .WithName(dict[nameof(IClientFactory.WithName)]) | |
| 55 | .WithUserId(dict[nameof(IClientFactory.WithUserId)]) | |
| 56 | .Build(); | |
| 57 | ||
| 58 | return this; | |
| 59 | } | |
| 60 | ||
| 61 | public IAppointmentFactory WithDoctor(Expression<Action<IDoctorFactory>> doctorExpression) | |
| 62 | {
| |
| 63 | var dict = new Dictionary<string, string>(); | |
| 64 | this.ParseExpression(doctorExpression, string.Empty, dict); | |
| 65 | ||
| 66 | this.doctor = this.doctorFactory | |
| 67 | .WithName(dict[nameof(IDoctorFactory.WithName)]) | |
| 68 | .WithUserId(dict[nameof(IDoctorFactory.WithUserId)]) | |
| 69 | .WithDoctorType( | |
| 70 | Enumeration.FromValue<DoctorType>( | |
| 71 | int.Parse(dict[nameof(IDoctorFactory.WithDoctorType)]))) | |
| 72 | .Build(); | |
| 73 | ||
| 74 | return this; | |
| 75 | } | |
| 76 | ||
| 77 | public IAppointmentFactory WithOfficeRoom(int number, OfficeRoomType officeRoomType) | |
| 78 | {
| |
| 79 | this.officeRoom = new OfficeRoom(false, number, officeRoomType); | |
| 80 | return this; | |
| 81 | } | |
| 82 | ||
| 83 | private void ParseExpression(Expression expression, string key, IDictionary<string, string> dict) | |
| 84 | {
| |
| 85 | // expression starts here in type lambda | |
| 86 | if (expression.NodeType == ExpressionType.Lambda) | |
| 87 | {
| |
| 88 | var lambdaExpression = (LambdaExpression)expression; | |
| 89 | foreach (var parameter in lambdaExpression.Parameters) | |
| 90 | {
| |
| 91 | ParseExpression(parameter, string.Empty, dict); | |
| 92 | } | |
| 93 | ||
| 94 | var body = lambdaExpression.Body; | |
| 95 | ParseExpression(body, string.Empty, dict); | |
| 96 | } | |
| 97 | // here we get the actual parameter of the method | |
| 98 | else if (expression.NodeType == ExpressionType.Constant) | |
| 99 | {
| |
| 100 | var constantExpression = (ConstantExpression)expression; | |
| 101 | var value = constantExpression.Value; | |
| 102 | ||
| 103 | // set the method value: for instance WithName("Gosho") so we add Gosho
| |
| 104 | dict[key] = value.ToString()!; | |
| 105 | } | |
| 106 | // here we get the name of the method | |
| 107 | else if (expression.NodeType == ExpressionType.Call) | |
| 108 | {
| |
| 109 | var methodCallExpression = (MethodCallExpression)expression; | |
| 110 | ||
| 111 | // set the method name: for instance WithName | |
| 112 | if (!dict.ContainsKey(methodCallExpression.Method.Name)) | |
| 113 | {
| |
| 114 | dict.Add(methodCallExpression.Method.Name, string.Empty); | |
| 115 | } | |
| 116 | ||
| 117 | ParseExpression(methodCallExpression.Object, methodCallExpression.Method.Name, dict); | |
| 118 | ||
| 119 | foreach (var argument in methodCallExpression.Arguments) | |
| 120 | {
| |
| 121 | ParseExpression(argument, methodCallExpression.Method.Name, dict); | |
| 122 | } | |
| 123 | } | |
| 124 | } | |
| 125 | } | |
| 126 | } | |
| 127 | ||
| 128 | namespace PetClinic.Application.Appointments.Commands.MakeAsDoctor | |
| 129 | {
| |
| 130 | using Common; | |
| 131 | using Common.Contracts; | |
| 132 | using Domain.Appointments.Factories; | |
| 133 | using Domain.Appointments.Models; | |
| 134 | using Domain.Common; | |
| 135 | using Domain.Common.SharedKernel; | |
| 136 | using MediatR; | |
| 137 | using System; | |
| 138 | using System.Threading; | |
| 139 | using System.Threading.Tasks; | |
| 140 | ||
| 141 | public class MakeAsDoctorAppointmentCommand : IRequest<Result> | |
| 142 | {
| |
| 143 | public string UserIdClient { get; set; } = default!;
| |
| 144 | public string Name { get; set; } = default!;
| |
| 145 | public int DoctorType { get; set; }
| |
| 146 | public int RoomNumber { get; set; }
| |
| 147 | public int OfficeRoomType { get; set; }
| |
| 148 | public DateTime StartDate { get; set; }
| |
| 149 | public DateTime EndDate { get; set; }
| |
| 150 | ||
| 151 | public class MakeAsDoctorAppointmentCommandHandler : IRequestHandler<MakeAsDoctorAppointmentCommand, Result> | |
| 152 | {
| |
| 153 | private readonly IAppointmentRepository appointmentRepository; | |
| 154 | private readonly ICurrentUser currentUser; | |
| 155 | private readonly IAppointmentFactory appointmentFactory; | |
| 156 | ||
| 157 | public MakeAsDoctorAppointmentCommandHandler( | |
| 158 | IAppointmentRepository appointmentRepository, | |
| 159 | ICurrentUser currentUser, | |
| 160 | IAppointmentFactory appointmentFactory) | |
| 161 | {
| |
| 162 | this.appointmentRepository = appointmentRepository; | |
| 163 | this.currentUser = currentUser; | |
| 164 | this.appointmentFactory = appointmentFactory; | |
| 165 | } | |
| 166 | ||
| 167 | public async Task<Result> Handle(MakeAsDoctorAppointmentCommand request, CancellationToken cancellationToken) | |
| 168 | {
| |
| 169 | var isDateAvailable = await this.appointmentRepository.IsDateAvailable( | |
| 170 | this.currentUser.UserId, | |
| 171 | request.RoomNumber, | |
| 172 | request.StartDate, | |
| 173 | request.EndDate, | |
| 174 | cancellationToken); | |
| 175 | ||
| 176 | if (!isDateAvailable) | |
| 177 | {
| |
| 178 | return "The chosen date is not available."; | |
| 179 | } | |
| 180 | ||
| 181 | var appointment = this.appointmentFactory | |
| 182 | .WithDoctor(doctor => doctor | |
| 183 | .WithDoctorType(Enumeration.FromValue<DoctorType>(request.DoctorType)) | |
| 184 | .WithName(this.currentUser.UserName) | |
| 185 | .WithUserId(this.currentUser.UserId) | |
| 186 | .Build()) | |
| 187 | .WithClient(client => client | |
| 188 | .WithName(request.Name) | |
| 189 | .WithUserId(request.UserIdClient) | |
| 190 | .Build()) | |
| 191 | .WithOfficeRoom(request.RoomNumber, Enumeration.FromValue<OfficeRoomType>(request.OfficeRoomType)) | |
| 192 | .WithAppointmentDate(request.StartDate, request.EndDate) | |
| 193 | .Build(); | |
| 194 | ||
| 195 | await this.appointmentRepository.Save(appointment, cancellationToken); | |
| 196 | ||
| 197 | return Result.Success; | |
| 198 | } | |
| 199 | } | |
| 200 | } | |
| 201 | } |