public async Task <AchievementAdminViewModel> Handle(CreateAchievementCommand request, CancellationToken cancellationToken)
            {
                var existingAchievements = await _context.Achievements.ToListAsync(cancellationToken);

                var achievement = existingAchievements
                                  .FirstOrDefault(a => a.Name.Equals(request.Name, StringComparison.InvariantCulture))
                                  ?? new Domain.Entities.Achievement();

                achievement.Name = request.Name;
                var codeData = Encoding.ASCII.GetBytes(request.Name);

                achievement.Code  = Convert.ToBase64String(codeData);
                achievement.Value = request.Value;

                if (achievement.Id == 0)
                {
                    _context.Achievements.Add(achievement);
                    await _context.SaveChangesAsync(cancellationToken);

                    return(new AchievementAdminViewModel()
                    {
                        Code = achievement.Code,
                        Name = achievement.Name,
                        Value = achievement.Value
                    });
                }

                return(null);
            }
예제 #2
0
            public async Task <Unit> Handle(UpsertUserCommand request, CancellationToken cancellationToken)
            {
                var user = new Domain.Entities.User();

                if (request.Id == 0)
                {
                    _context.Users.Add(user);
                }
                else
                {
                    user = await _context
                           .Users
                           .FirstOrDefaultAsync(u => u.Id == request.Id, cancellationToken);

                    if (user == null)
                    {
                        throw new NotFoundException(nameof(User), request.Id);
                    }
                }

                _mapper.Map(request, user);

                await _context.SaveChangesAsync(cancellationToken);

                return(Unit.Value);
            }
예제 #3
0
            public async Task <ClaimRewardResult> Handle(ClaimRewardCommand request, CancellationToken cancellationToken)
            {
                var reward = await _context
                             .Rewards
                             .Where(r => r.Code == request.Code)
                             .FirstOrDefaultAsync(cancellationToken);

                if (reward == null)
                {
                    return(new ClaimRewardResult
                    {
                        status = RewardStatus.NotFound
                    });
                }

                var user = await _currentUserService.GetCurrentUserAsync(cancellationToken);

                if (user.Points < reward.Cost)
                {
                    return(new ClaimRewardResult
                    {
                        status = RewardStatus.NotEnoughPoints
                    });
                }

                var userHasReward = await _context
                                    .UserRewards
                                    .Where(ur => ur.UserId == user.Id)
                                    .Where(ur => ur.RewardId == reward.Id)
                                    .FirstOrDefaultAsync(cancellationToken);

                if (userHasReward != null && userHasReward.AwardedAt >= DateTime.Now.AddMinutes(-5))
                {
                    return(new ClaimRewardResult
                    {
                        status = RewardStatus.Duplicate
                    });
                }

                await _context
                .UserRewards
                .AddAsync(new Domain.Entities.UserReward
                {
                    UserId   = user.Id,
                    RewardId = reward.Id
                }, cancellationToken);

                await _context.SaveChangesAsync(cancellationToken);

                var rewardModel = _mapper.Map <RewardViewModel>(reward);

                return(new ClaimRewardResult
                {
                    viewModel = rewardModel,
                    status = RewardStatus.Claimed
                });
            }
예제 #4
0
            public async Task <StaffDto> Handle(UpsertStaffMemberProfileCommand request, CancellationToken cancellationToken)
            {
                var staffMember       = _mapper.Map <StaffMember>(request);
                var staffMemberEntity = await _context.StaffMembers
                                        .Include(s => s.StaffMemberSkills)
                                        .ThenInclude(sms => sms.Skill)
                                        .FirstOrDefaultAsync(u => u.Name == request.Name, cancellationToken);

                // Add if doesn't exist
                if (staffMemberEntity == null)
                {
                    _context.StaffMembers.Add(staffMember);
                }
                else // Update existing entity
                {
                    staffMemberEntity.Email           = request.Email;
                    staffMemberEntity.Name            = request.Name;
                    staffMemberEntity.Profile         = request.Profile;
                    staffMemberEntity.TwitterUsername = request.TwitterUsername;
                    staffMemberEntity.Title           = request.Title;

                    // check for skills
                    var skills = request.Skills;

                    // changes have been made to members' skills
                    if (staffMemberEntity.StaffMemberSkills.Count() != skills.Count())
                    {
                        var newSkills = request.Skills.Where(x => !staffMemberEntity.StaffMemberSkills.Select(x => x.Skill.Name).Contains(x)).ToList();

                        if (staffMemberEntity.StaffMemberSkills.Count() < request.Skills.Count())
                        {
                            // assign the new skills to a member
                            foreach (var skill in newSkills)
                            {
                                var skillEntity = await _context.Skills.FirstOrDefaultAsync(x => x.Name == skill);

                                staffMemberEntity.StaffMemberSkills.Add(new StaffMemberSkill {
                                    Skill = skillEntity
                                });
                            }
                        }
                        else
                        {
                            var deletedSkills = staffMemberEntity.StaffMemberSkills.Where(x => !request.Skills.Contains(x.Skill.Name)).ToList();
                            foreach (var deletedSkill in deletedSkills)
                            {
                                staffMemberEntity.StaffMemberSkills.Remove(deletedSkill);
                            }
                        }
                    }
                }

                await _context.SaveChangesAsync(cancellationToken);

                return(_mapper.Map <StaffDto>(request));
            }
예제 #5
0
            public async Task <PostAchievementResult> Handle(PostAchievementCommand request, CancellationToken cancellationToken)
            {
                var achievement = await _context
                                  .Achievements
                                  .Where(a => a.Code == request.Code)
                                  .FirstOrDefaultAsync(cancellationToken);

                if (achievement == null)
                {
                    return(new PostAchievementResult
                    {
                        status = AchievementStatus.NotFound
                    });
                }

                var user = await _currentUserService.GetCurrentUserAsync(cancellationToken);

                var userHasAchievement = await _context
                                         .UserAchievements
                                         .Where(ua => ua.UserId == user.Id)
                                         .Where(ua => ua.AchievementId == achievement.Id)
                                         .AnyAsync(cancellationToken);

                if (userHasAchievement)
                {
                    return(new PostAchievementResult
                    {
                        status = AchievementStatus.Duplicate
                    });
                }

                await _context
                .UserAchievements
                .AddAsync(new Domain.Entities.UserAchievement
                {
                    UserId        = user.Id,
                    AchievementId = achievement.Id
                }, cancellationToken);

                await _context.SaveChangesAsync(cancellationToken);

                var achievementModel = _mapper.Map <AchievementViewModel>(achievement);

                return(new PostAchievementResult
                {
                    viewModel = achievementModel,
                    status = AchievementStatus.Added
                });
            }
            public async Task <Unit> Handle(DeleteStaffMemberProfileCommand request, CancellationToken cancellationToken)
            {
                var staffMember = await _context.StaffMembers
                                  .FirstOrDefaultAsync(u => u.Name == request.Name, cancellationToken);

                if (staffMember == null)
                {
                    throw new NotFoundException(nameof(StaffMember), request.Name);
                }

                _context.StaffMembers.Remove(staffMember);
                await _context.SaveChangesAsync(cancellationToken);

                return(Unit.Value);
            }
예제 #7
0
            public async Task <AchievementViewModel> Handle(AddAchievementCommand request, CancellationToken cancellationToken)
            {
                var achievement = await _context
                                  .Achievements
                                  .Where(a => a.Code == request.Code)
                                  .FirstOrDefaultAsync(cancellationToken);

                if (achievement == null)
                {
                    throw new NotFoundException(request.Code, nameof(Domain.Entities.Achievement));
                }

                var user = await _currentUserService.GetCurrentUserAsync(cancellationToken);

                var userHasAchievement = await _context
                                         .UserAchievements
                                         .Where(ua => ua.UserId == user.Id)
                                         .Where(ua => ua.AchievementId == achievement.Id)
                                         .AnyAsync(cancellationToken);

                if (userHasAchievement)
                {
                    throw new AlreadyAwardedException(user.Id, achievement.Name);
                }

                await _context
                .UserAchievements
                .AddAsync(new Domain.Entities.UserAchievement
                {
                    UserId        = user.Id,
                    AchievementId = achievement.Id
                }, cancellationToken);

                try
                {
                    await _context.SaveChangesAsync(cancellationToken);
                }
                catch (Exception)
                {
                    throw new AlreadyAwardedException(user.Id, achievement.Name);
                }

                return(_mapper.Map <AchievementViewModel>(achievement));
            }
            public async Task <Unit> Handle(UpsertCurrentUserCommand request, CancellationToken cancellationToken)
            {
                var user = await _context
                           .Users
                           .Where(u => u.Email == _currentUserService.GetUserEmail())
                           .FirstOrDefaultAsync(cancellationToken);

                if (user == null)
                {
                    user = new Domain.Entities.User();
                    await _context.Users.AddAsync(user, cancellationToken);
                }

                _mapper.Map(_currentUserService, user);

                await _context.SaveChangesAsync(cancellationToken);

                return(Unit.Value);
            }
예제 #9
0
            public async Task <string> Handle(UploadProfilePicCommand request, CancellationToken cancellationToken)
            {
                await using var ms = new MemoryStream();
                IFormFile file = request.File;
                await file.CopyToAsync(ms, cancellationToken);

                byte[] bytes = ms.ToArray();

                string filename = file.FileName;

                string url = await _storage.UploadProfilePic(bytes, filename);

                Domain.Entities.User user = await _context.Users.FirstOrDefaultAsync(u => u.Email.ToLower() == _currentUserService.GetUserEmail(), cancellationToken);

                user.Avatar = url;
                await _context.SaveChangesAsync(cancellationToken);

                return(url);
            }
예제 #10
0
        public async Task <int> Handle(AddRewardCommand request, CancellationToken cancellationToken)
        {
            var imageBytes = Convert.FromBase64String(request.ImageBytesInBase64);
            var imageUri   = await _picStorageProvider.UploadRewardPic(imageBytes, request.ImageFileName);

            var    codeData = Encoding.ASCII.GetBytes(request.Name);
            string code     = Convert.ToBase64String(codeData);

            var entity = new SSW.Rewards.Domain.Entities.Reward
            {
                Name       = request.Name,
                Cost       = request.Cost,
                RewardType = request.RewardType,
                ImageUri   = imageUri.AbsoluteUri,
                Code       = code
            };

            _context.Rewards.Add(entity);

            await _context.SaveChangesAsync(cancellationToken);

            return(entity.Id);
        }
        public async Task <ClaimAchievementResult> Handle(ClaimAchievementForUserCommand request, CancellationToken cancellationToken)
        {
            var achievement = await _context
                              .Achievements
                              .Where(a => a.Code == request.Code)
                              .FirstOrDefaultAsync(cancellationToken);

            if (achievement == null)
            {
                _logger.LogError("Achievement was not found for code: {0}", request.Code);
                return(new ClaimAchievementResult
                {
                    status = ClaimAchievementStatus.NotFound
                });
            }

            var user = await _context.Users
                       .Where(u => u.Id == request.UserId)
                       .Include(u => u.UserAchievements).ThenInclude(ua => ua.Achievement)
                       .FirstOrDefaultAsync(cancellationToken);

            if (user == null)
            {
                _logger.LogError("User was not found for id: {0}", request.UserId);
                return(new ClaimAchievementResult
                {
                    status = ClaimAchievementStatus.Error
                });
            }

            var achievementCheck = user
                                   .UserAchievements
                                   .Where(ua => ua.Achievement.Code == request.Code)
                                   .FirstOrDefault();

            if (achievementCheck != null)
            {
                _logger.LogError("User already has achievement: {0}", request.Code);
                return(new ClaimAchievementResult
                {
                    status = ClaimAchievementStatus.Duplicate
                });
            }

            try
            {
                await _context
                .UserAchievements
                .AddAsync(new UserAchievement
                {
                    UserId        = user.Id,
                    AchievementId = achievement.Id
                }, cancellationToken);

                await _context.SaveChangesAsync(cancellationToken);
            }
            catch (Exception e)
            {
                _logger.LogError(e.Message, e);
                return(new ClaimAchievementResult
                {
                    status = ClaimAchievementStatus.Error
                });
            }

            return(new ClaimAchievementResult
            {
                status = ClaimAchievementStatus.Claimed
            });
        }
예제 #12
0
            public async Task <ClaimRewardResult> Handle(ClaimRewardCommand request, CancellationToken cancellationToken)
            {
                var reward = await _context
                             .Rewards
                             .Where(r => r.Code == request.Code)
                             .FirstOrDefaultAsync(cancellationToken);

                if (reward == null)
                {
                    return(new ClaimRewardResult
                    {
                        status = RewardStatus.NotFound
                    });
                }

                var user = await _currentUserService.GetCurrentUserAsync(cancellationToken);

                var userRewards = await _context
                                  .UserRewards
                                  .Where(ur => ur.UserId == user.Id)
                                  .ToListAsync(cancellationToken);

                int pointsUsed = userRewards.Sum(ur => ur.Reward.Cost);

                int balance = user.Points - pointsUsed;

                if (balance < reward.Cost)
                {
                    return(new ClaimRewardResult
                    {
                        status = RewardStatus.NotEnoughPoints
                    });
                }

                // TECH DEBT: the following logic is intended to 'debounce' reward
                // claiming, to prevent users claiming the same reward twice
                // within a 5 minute window. This workaround is only required on
                // the current 'milestone' model for points. Once we move to the
                // 'currency' model, this will not be required anymore.
                // see: https://github.com/SSWConsulting/SSW.Rewards/issues/100
                var userHasReward = userRewards
                                    .Where(ur => ur.RewardId == reward.Id)
                                    .FirstOrDefault();

                if (userHasReward != null && userHasReward.AwardedAt >= _dateTimeProvider.Now.AddMinutes(-5))
                {
                    return(new ClaimRewardResult
                    {
                        status = RewardStatus.Duplicate
                    });
                }

                await _context
                .UserRewards
                .AddAsync(new Domain.Entities.UserReward
                {
                    UserId   = user.Id,
                    RewardId = reward.Id
                }, cancellationToken);

                await _context.SaveChangesAsync(cancellationToken);

                var dbUser = await _context.Users
                             .Where(u => u.Id == user.Id)
                             .FirstAsync(cancellationToken);

                await _rewardSender.SendRewardAsync(dbUser, reward, cancellationToken);

                var rewardModel = _mapper.Map <RewardViewModel>(reward);

                return(new ClaimRewardResult
                {
                    viewModel = rewardModel,
                    status = RewardStatus.Claimed
                });
            }
        public async Task <ClaimRewardResult> Handle(ClaimRewardForUserCommand request, CancellationToken cancellationToken)
        {
            var reward = await _context
                         .Rewards
                         .Where(r => r.Code == request.Code)
                         .FirstOrDefaultAsync(cancellationToken);

            if (reward == null)
            {
                _logger.LogError("Reward not found with code: {0}", request.Code);
                return(new ClaimRewardResult
                {
                    status = RewardStatus.NotFound
                });
            }

            var user = await _context.Users
                       .Where(u => u.Id == request.UserId)
                       .Include(u => u.UserAchievements).ThenInclude(ua => ua.Achievement)
                       .FirstOrDefaultAsync(cancellationToken);

            var userRewards = await _context
                              .UserRewards
                              .Include(ur => ur.Reward)
                              .Where(ur => ur.UserId == user.Id)
                              .ToListAsync(cancellationToken);

            int pointsUsed = userRewards.Sum(ur => ur.Reward.Cost);

            int balance = user.UserAchievements.Sum(ua => ua.Achievement.Value) - pointsUsed;

            if (balance < reward.Cost)
            {
                _logger.LogInformation("User does not have enough points to claim reward");
                return(new ClaimRewardResult
                {
                    status = RewardStatus.NotEnoughPoints
                });
            }

            try
            {
                await _context
                .UserRewards
                .AddAsync(new UserReward
                {
                    UserId   = user.Id,
                    RewardId = reward.Id
                }, cancellationToken);

                await _context.SaveChangesAsync(cancellationToken);
            }
            catch (Exception e)
            {
                _logger.LogError(e.Message, e);
                return(new ClaimRewardResult
                {
                    status = RewardStatus.Error
                });
            }

            return(new ClaimRewardResult
            {
                status = RewardStatus.Claimed
            });
        }