Help on Register (usertype dilemma)

PHOTO EMBED

Sun Jul 07 2024 10:38:28 GMT+0000 (Coordinated Universal Time)

Saved by @iamkatmakhafola

//Suggested changes
1. Create Separate ViewModels: Define different ViewModels for each user type (Member, Employee, Owner) with the specific fields required for each.

2. Determine User Type First: Create a step in your registration process to first capture the user type.

3. Use Specific ViewModel Based on User Type: Use the captured user type to select and validate the appropriate ViewModel.

//Viewmodels
public class UserViewModel
{
    public string Email { get; set; }
    public string Password { get; set; }
    public int User_Type_ID { get; set; }
    // Common fields...
}

public class MemberViewModel : UserViewModel
{
    public int Contract_ID { get; set; }
    public bool Is_Active { get; set; }
    // Other member-specific fields...
}

public class EmployeeViewModel : UserViewModel
{
    public int Employee_Type_ID { get; set; }
    public int Shift_ID { get; set; }
    public int Hours_Worked { get; set; }
    // Other employee-specific fields...
}

public class OwnerViewModel : UserViewModel
{
    // Owner-specific fields...
}

//UserTypeVM
public class UserTypeVM
{
    public int User_Type_ID { get; set; }
}


//Controller
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Identity;
using System.Text.RegularExpressions;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using Microsoft.AspNetCore.Http;
using Newtonsoft.Json;

[Route("api/[controller]")]
[ApiController]
public class UserController : ControllerBase
{
    private readonly UserManager<User> _userManager;
    private readonly AppDbContext _appDbContext;
    private readonly ILogger<UserController> _logger;

    public UserController(UserManager<User> userManager, AppDbContext appDbContext, ILogger<UserController> logger)
    {
        _userManager = userManager;
        _appDbContext = appDbContext;
        _logger = logger;
    }

    [HttpPost]
    [Route("DetermineUserType")]
    public async Task<IActionResult> DetermineUserType([FromForm] UserTypeViewModel userTypeViewModel)
    {
        if (userTypeViewModel == null || userTypeViewModel.User_Type_ID <= 0)
        {
            return BadRequest("Invalid user type.");
        }

        // Determine user type based on the provided information
        int userTypeID = userTypeViewModel.User_Type_ID;

        // Redirect to the appropriate registration method
        switch (userTypeID)
        {
            case 1:
                return await RegisterMember(userTypeViewModel);
            case 2:
                return await RegisterEmployee(userTypeViewModel);
            case 3:
                return await RegisterOwner(userTypeViewModel);
            default:
                return BadRequest("Invalid user type.");
        }
    }

    private async Task<IActionResult> RegisterMember(UserTypeViewModel userTypeViewModel)
    {
        // Map UserTypeViewModel to MemberViewModel
        var memberViewModel = new MemberViewModel
        {
            Email = userTypeViewModel.Email,
            Password = userTypeViewModel.Password,
            User_Type_ID = userTypeViewModel.User_Type_ID,
            // Initialize other member-specific fields
        };

        return await Register(memberViewModel);
    }

    private async Task<IActionResult> RegisterEmployee(UserTypeViewModel userTypeViewModel)
    {
        // Map UserTypeViewModel to EmployeeViewModel
        var employeeViewModel = new EmployeeViewModel
        {
            Email = userTypeViewModel.Email,
            Password = userTypeViewModel.Password,
            User_Type_ID = userTypeViewModel.User_Type_ID,
            // Initialize other employee-specific fields
        };

        return await Register(employeeViewModel);
    }

    private async Task<IActionResult> RegisterOwner(UserTypeViewModel userTypeViewModel)
    {
        // Map UserTypeViewModel to OwnerViewModel
        var ownerViewModel = new OwnerViewModel
        {
            Email = userTypeViewModel.Email,
            Password = userTypeViewModel.Password,
            User_Type_ID = userTypeViewModel.User_Type_ID,
            // Initialize other owner-specific fields
        };

        return await Register(ownerViewModel);
    }

    private async Task<IActionResult> Register(UserViewModel uvm)
    {
        try
        {
            var formCollection = await Request.ReadFormAsync();
            var photo = formCollection.Files.FirstOrDefault();

            // Validate Phone Number Pattern
            var phoneNumberPattern = @"^\d{10}$";
            bool isValidPhoneNumber = Regex.IsMatch(uvm.PhoneNumber, phoneNumberPattern);

            if (!isValidPhoneNumber) return BadRequest("Enter valid 10-digit phone number.");

            // Validate South African ID number
            if (!IsValidSouthAfricanIDNumber(uvm.Id_Number, uvm.Date_of_Birth))
            {
                return BadRequest("Enter a valid South African ID number.");
            }

            var user = await _userManager.FindByEmailAsync(uvm.Email);
            int lastUserID = _appDbContext.Users
                                .OrderByDescending(u => u.User_ID)
                                .Select(u => u.User_ID)
                                .FirstOrDefault();

            if (user == null)
            {
                if (photo != null && photo.Length > 0)
                {
                    using (var memoryStream = new MemoryStream())
                    {
                        await photo.CopyToAsync(memoryStream);
                        var fileBytes = memoryStream.ToArray();
                        string base64Image = Convert.ToBase64String(fileBytes);

                        user = new User
                        {
                            User_ID = lastUserID + 1,
                            Name = uvm.Name,
                            Surname = uvm.Surname,
                            UserName = uvm.Email,
                            Email = uvm.Email,
                            PasswordHash = _userManager.PasswordHasher.HashPassword(null, uvm.Password),
                            User_Status_ID = uvm.User_Status_ID,
                            User_Type_ID = uvm.User_Type_ID,
                            PhoneNumber = uvm.PhoneNumber,
                            Date_of_Birth = uvm.Date_of_Birth,
                            ID_Number = uvm.Id_Number,
                            Physical_Address = uvm.Physical_Address,
                            Photo = base64Image // Store the base64 string of the photo
                        };

                        IdentityResult result = await _userManager.CreateAsync(user);

                        if (result.Succeeded)
                        {
                            // Assign role based on User_Type_ID
                            string roleName = GetRoleNameByUserType(uvm.User_Type_ID);
                            if (!string.IsNullOrEmpty(roleName))
                            {
                                var roleResult = await _userManager.AddToRoleAsync(user, roleName);
                                if (!roleResult.Succeeded)
                                {
                                    return BadRequest(new { Status = "Error", Errors = roleResult.Errors });
                                }
                            }

                            if (uvm.User_Type_ID == 1) // Member
                            {
                                var memberViewModel = uvm as MemberViewModel;
                                int lastMemberID = _appDbContext.Members
                                    .OrderByDescending(m => m.Member_ID)
                                    .Select(m => m.Member_ID)
                                    .FirstOrDefault();

                                var newMember = new Member
                                {
                                    Member_ID = lastMemberID + 1,
                                    User_ID = user.User_ID,
                                    Contract_ID = memberViewModel.Contract_ID,
                                    Is_Active = memberViewModel.Is_Active // Use the value from the view model
                                };

                                _appDbContext.Members.Add(newMember);
                                _logger.LogInformation("Adding new member with User_ID: {User_ID}, Member_ID: {Member_ID}", user.User_ID, newMember.Member_ID);
                                await _appDbContext.SaveChangesAsync();
                                _logger.LogInformation("Member added successfully with User_ID: {User_ID}, Member_ID: {Member_ID}", user.User_ID, newMember.Member_ID);
                            }
                            else if (uvm.User_Type_ID == 2) // Employee
                            {
                                var employeeViewModel = uvm as EmployeeViewModel;
                                int lastEmployeeID = _appDbContext.Employees
                                    .OrderByDescending(e => e.Employee_ID)
                                    .Select(e => e.Employee_ID)
                                    .FirstOrDefault();

                                var newEmployee = new Employee
                                {
                                    Employee_ID = lastEmployeeID == 0 ? 1 : lastEmployeeID + 1,
                                    User_ID = user.User_ID,
                                    Employment_Date = DateTime.UtcNow,
                                    Hours_Worked = employeeViewModel.Hours_Worked, // Use the value from the view model (initialized to zero)
                                    Employee_Type_ID = employeeViewModel.Employee_Type_ID,
                                    Shift_ID = employeeViewModel.Shift_ID
                                };

                                _appDbContext.Employees.Add(newEmployee);
                                _logger.LogInformation("Adding new employee with User_ID: {User_ID}, Employee_ID: {Employee_ID}", user.User_ID, newEmployee.Employee_ID);
                                await _appDbContext.SaveChangesAsync();
                                _logger.LogInformation("Employee added successfully with User_ID: {User_ID}, Employee_ID: {Employee_ID}", user.User_ID, newEmployee.Employee_ID);
                            }
                            else if (uvm.User_Type_ID == 3) // Owner
                            {
                                var ownerViewModel = uvm as OwnerViewModel;
                                int lastOwnerID = _appDbContext.Owners
                                    .OrderByDescending(o => o.Owner_ID)
                                    .Select(o => o.Owner_ID)
                                    .FirstOrDefault();

                                var newOwner = new Owner
                                {
                                    Owner_ID = lastOwnerID == 0 ? 1 : lastOwnerID + 1,
                                    User_ID = user.User_ID
                                };

                                _appDbContext.Owners.Add(newOwner);
                                _logger.LogInformation("Adding new owner with User_ID: {User_ID}, Owner_ID: {Owner_ID}", user.User_ID, newOwner.Owner_ID);
                                await _appDbContext.SaveChangesAsync();
                                _logger.LogInformation("Owner added successfully with User_ID: {User_ID}, Owner_ID: {Owner_ID}", user.User_ID, newOwner.Owner_ID);
                            }

                            return Ok(new { Status = "Success", Message = "Your profile has been created successfully!" });
                        }
                        else
                        {
                            return StatusCode(StatusCodes.Status500InternalServerError, result.Errors.FirstOrDefault()?.Description);
                        }
                    }
                }
                else
                {
                    return BadRequest("Photo is required.");
                }
            }
            else
            {
                return Forbid("User already exists.");
            }
        }
        catch (DbUpdateException dbEx)
        {
            return StatusCode(StatusCodes.Status500InternalServerError, dbEx.InnerException?.Message ?? "An error occurred while processing your request.");
        }
        catch (Exception ex)
        {
            return StatusCode(StatusCodes.Status500InternalServerError, "An error occurred while processing your request.");
        }
    }

    private bool IsValidSouthAfricanIDNumber(string idNumber, DateTime dateOfBirth)
    {
        // Implement South African ID number validation logic here
        return true;
    }

    private string GetRoleNameByUserType(int userTypeID)
    {
        // Implement logic to get role name by user type ID
        return "RoleName";
    }
}
content_copyCOPY

Explanation 1. DetermineUserType Action: This action receives a basic user type ViewModel. Based on the User_Type_ID, it redirects to the specific registration method (e.g., RegisterMember, RegisterEmployee, RegisterOwner). 2. Specific Registration Methods: Each method maps the basic ViewModel to the specific ViewModel and calls the Register method. 3. Register Method: This method contains the common registration logic. It performs validation, user creation, and specific logic based on the user type. The Register method is called with the specific ViewModel for members, employees, and owners, ensuring that only the relevant fields are used.