View difference between Paste ID: kpyfJc7i and sfkm59yJ
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
}