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 | } |