public async Task <Registration> CreateRegistrationAsync(
            int eventId,
            string userId,
            Action <Registration> fillAction,
            CancellationToken cancellationToken)
        {
            var @event = await _eventInfoRetrievalService.GetEventInfoByIdAsync(eventId, null, cancellationToken); // To check event reference only

            var user = await _userRetrievalService.GetUserByIdAsync(userId, cancellationToken);

            var registration = new Registration
            {
                EventInfoId     = eventId,
                UserId          = userId,
                ParticipantName = user.Name // TODO: remove this property?
            };

            fillAction?.Invoke(registration);

            await _registrationAccessControlService.CheckRegistrationCreateAccessAsync(registration, cancellationToken);

            await _context.CreateAsync(registration, cancellationToken);

            return(registration);
        }
        public async Task <Registration> CreateRegistrationAsync(
            int eventId,
            string userId,
            RegistrationOptions options,
            CancellationToken cancellationToken)
        {
            var existingRegistration = await _context.Registrations
                                       .FirstOrDefaultAsync(m => m.EventInfoId == eventId &&
                                                            m.UserId == userId, cancellationToken : cancellationToken);

            if (existingRegistration != null)
            {
                throw new DuplicateException("Found existing registration for user on event.");
            }

            var eventInfo = await _eventInfoRetrievalService.GetEventInfoByIdAsync(eventId,
                                                                                   new EventInfoRetrievalOptions
            {
                ForUpdate         = true,
                LoadRegistrations = true,
                LoadProducts      = true
            },
                                                                                   cancellationToken);

            var user = await _userRetrievalService.GetUserByIdAsync(userId, null, cancellationToken);

            var registration = new Registration
            {
                EventInfoId     = eventId,
                UserId          = userId,
                ParticipantName = user.Name // TODO: remove this property?
            };

            await _registrationAccessControlService.CheckRegistrationCreateAccessAsync(registration, cancellationToken);

            if (eventInfo.Status == EventInfo.EventInfoStatus.WaitingList)
            {
                registration.Status = Registration.RegistrationStatus.WaitingList;
            }

            await _context.CreateAsync(registration, cancellationToken : cancellationToken);

            options ??= new RegistrationOptions();

            if (options.CreateOrder && registration.Status != Registration.RegistrationStatus.WaitingList)
            {
                var mandatoryItems = eventInfo.Products
                                     .Where(p => p.IsMandatory)
                                     .Select(p => new OrderItemDto
                {
                    ProductId = p.ProductId,
                    Quantity  = p.MinimumQuantity
                }).ToArray();

                if (mandatoryItems.Any())
                {
                    await _registrationOrderManagementService
                    .CreateOrderForRegistrationAsync(
                        registration.RegistrationId,
                        mandatoryItems,
                        cancellationToken);
                }
            }

            if (eventInfo.MaxParticipants > 0 && eventInfo
                .Registrations.Count + 1 >= eventInfo.MaxParticipants)
            {
                eventInfo.Status = EventInfo.EventInfoStatus.WaitingList;
                await _context.SaveChangesAsync(cancellationToken);
            }

            return(registration);
        }