How to add, delete, check and modify gracefully (3): Add, delete, check and modify for business users

Create business users

Different from the authentication user IdentityUser of the identity management module (Identity module), the business user (BusinessUser) is a domain model around the definition of "user" in the business system. For example: in a hospital system, business users can be doctors, nurses, and patients; in an OA system, business users can be employees, administrators, customers, etc.

Business users and authentication users are associated by a synchronization mechanism, and business users are associated and synchronized with authentication users through the Synchronizer of DistributedEvent.

In the Health business module, two types of business users are defined:

Client: client;

Employee: Employee.

These business users inherit from HealthUser, which is the base class of business users and contains basic information of business users, such as name, gender, date of birth, ID number, etc. And it is necessary to implement the IUpdateUserData interface, so as to update the basic information of the business user when synchronizing the authentication user information.

Employee contains job number, job title, profile and other information. Its domain model is defined as follows:

public class Employee : HealthUser<Guid>, IUser, IUpdateUserData
{
    [StringLength(12)]
    public string EmployeeNumber { get; set; }

    [StringLength(64)]
    public string EmployeeTitle { get; set; }

    public string Introduction { get; set; }

    ...
}

Client contains customer number, height, weight, marital status and other information. Its domain model is defined as follows:

public class Client : HealthUser<Guid>, IUser, IUpdateUserData
{

    //unique

    [StringLength(12)]
    public string ClientNumber { get; set; }

    public string ClientNumberType { get; set; }

    [Range(0.0, 250.0)]
    public double? Height { get; set; }


    [Range(0.0, 1000.0)]
    public double? Weight { get; set; }

    public string Marriage { get; set; }

    public string Status { get; set; }
}

Create a business user synchronizer

Taking Client as an example, ClientLookupService is a query service for business users. Its base class UserLookupService defines the query interface for associated users, including query by ID, query by user name, query by organizational structure, and query by user relationship.

Create ClientLookupService, the code is as follows

public class ClientLookupService : UserLookupService<Client, IClientRepository>, IClientLookupService
{
    public ClientLookupService(
        IClientRepository userRepository,
        IUnitOfWorkManager unitOfWorkManager)
        : base(
            userRepository,
            unitOfWorkManager)
    {

    }

    protected override Client CreateUser(IUserData externalUser)
    {
        return new Client(externalUser);
    }
}

The synchronizer subscribes to the distributed event EntityUpdatedEto. When the authenticated user is updated, the synchronizer will update the basic information of the business user.

Create ClientSynchronizer, the code is as follows

public class ClientSynchronizer :
        IDistributedEventHandler<EntityUpdatedEto<UserEto>>,
    ITransientDependency
{
    protected IClientRepository UserRepository { get; }
    protected IClientLookupService UserLookupService { get; }

    public ClientSynchronizer(
        IClientRepository userRepository,
        IClientLookupService userLookupService)
    {
        UserRepository = userRepository;
        UserLookupService = userLookupService;
    }

    public async Task HandleEventAsync(EntityUpdatedEto<UserEto> eventData)
    {
        var user = await UserRepository.FindAsync(eventData.Entity.Id);
        if (user != null)
        {
            if (user.Update(eventData.Entity))
            {
                await UserRepository.UpdateAsync(user);
            }
        }
    }
}

Create a business user application service

Take Employee as an example

Create EmployeeAppService in the application layer, where we implement the operation of adding, deleting, modifying and checking business users.

EmployeeAppService inherits from CrudAppService, which is the base class for CRUD provided by the ABP framework. Its base class defines the interfaces for CRUD, including GetAsync, GetListAsync, CreateAsync, UpdateAsync, DeleteAsync, etc.

OrganizationUnit provides the query basis for the query interface of business users to query by organizational structure. OrganizationUnitAppService is injected into EmployeeAppService.

public class EmployeeAppService : CrudAppService<Employee, EmployeeDto, Guid, GetAllEmployeeInput, CreateEmployeeInput>, IEmployeeAppService
{
    private readonly IOrganizationUnitAppService organizationUnitAppService;

}

increase

Create the CreateWithUserAsync method for creating business users.

public async Task<EmployeeDto> CreateWithUserAsync(CreateEmployeeWithUserInput input)
{

    var createdUser = await identityUserAppService.CreateAsync(input);
    await CurrentUnitOfWork.SaveChangesAsync();
    var currentEmployee = await userLookupService.FindByIdAsync(createdUser.Id);
    ObjectMapper.Map(input, currentEmployee);
    var updatedEmployee = await Repository.UpdateAsync(currentEmployee);
    var result = ObjectMapper.Map<Employee, EmployeeDto>(updatedEmployee);

    if (input.OrganizationUnitId.HasValue)
    {
        await organizationUnitAppService.AddToOrganizationUnitAsync(
            new UserToOrganizationUnitInput()
            { UserId = createdUser.Id, OrganizationUnitId = input.OrganizationUnitId.Value });
    }
    return result;
}

delete

The default implementation of the delete interface is provided by CrudAppService without rewriting.

change

Create an UpdateWithUserAsync method for updating business users.

public async Task<EmployeeDto> UpdateWithUserAsync(CreateEmployeeInput input)
{

    var currentEmployee = await userLookupService.FindByIdAsync(input.Id);
    if (currentEmployee == null)
    {
        throw new UserFriendlyException("没有找到对应的用户");
    }
    ObjectMapper.Map(input, currentEmployee);
    var updatedEmployee = await Repository.UpdateAsync(currentEmployee);
    var result = ObjectMapper.Map<Employee, EmployeeDto>(updatedEmployee);

    return result;
}

check

The interface for querying a single entity is provided by CrudAppService by default and does not need to be rewritten.

Query collection:

Taking Employee as an example, the input parameters required by the query interface are:

OrganizationUnitId: Query users by organizational structure
IsWithoutOrganization: Query users who do not belong to any organizational structure
EmployeeTitle: Query users by professional title

Create GetAllEmployeeInput, the code is as follows

public class GetAllEmployeeInput : PagedAndSortedResultRequestDto
{
    public string EmployeeTitle { get; set; }

    public Guid? OrganizationUnitId { get; set; }
    public bool IsWithoutOrganization { get; set; }

}

Override CreateFilteredQueryAsync


protected override async Task<IQueryable<Employee>> CreateFilteredQueryAsync(GetAllEmployeeInput input)
{
    var query = await ReadOnlyRepository.GetQueryableAsync().ConfigureAwait(continueOnCapturedContext: false);

    if (input.OrganizationUnitId.HasValue && !input.IsWithoutOrganization)
    {
        var organizationUnitUsers = await organizationUnitAppService.GetOrganizationUnitUsersAsync(new GetOrganizationUnitUsersInput()
        {
            Id = input.OrganizationUnitId.Value
        });
        if (organizationUnitUsers.Count() > 0)
        {
            var ids = organizationUnitUsers.Select(c => c.Id);
            query = query.Where(t => ids.Contains(t.Id));
        }
        else
        {
            query = query.Where(c => false);
        }
    }
    else if (input.IsWithoutOrganization)
    {
        var organizationUnitUsers = await organizationUnitAppService.GetUsersWithoutOrganizationAsync(new GetUserWithoutOrganizationInput());
        if (organizationUnitUsers.Count() > 0)
        {
            var ids = organizationUnitUsers.Select(c => c.Id);
            query = query.Where(t => ids.Contains(t.Id));
        }
        else
        {
            query = query.Where(c => false);
        }
    }
    query = query.WhereIf(!string.IsNullOrEmpty(input.EmployeeTitle), c => c.EmployeeTitle == input.EmployeeTitle);
    return query;
}

So far, we have completed the implementation of adding, deleting, modifying and checking functions for business users.

create controller

Create EmployeeController in the HttpApi project, the code is as follows:

[Area(HealthRemoteServiceConsts.ModuleName)]
[RemoteService(Name = HealthRemoteServiceConsts.RemoteServiceName)]
[Route("api/Health/employee")]
public class EmployeeController : AbpControllerBase, IEmployeeAppService
{
    private readonly IEmployeeAppService _employeeAppService;

    public EmployeeController(IEmployeeAppService employeeAppService)
    {
        _employeeAppService = employeeAppService;
    }

    [HttpPost]
    [Route("CreateWithUser")]

    public Task<EmployeeDto> CreateWithUserAsync(CreateEmployeeWithUserInput input)
    {
        return _employeeAppService.CreateWithUserAsync(input);
    }

    [HttpDelete]
    [Route("Delete")]
    public Task DeleteAsync(Guid id)
    {
        return _employeeAppService.DeleteAsync(id);
    }

    [HttpPut]
    [Route("UpdateWithUser")]

    public Task<EmployeeDto> UpdateWithUserAsync(CreateEmployeeInput input)
    {
        return _employeeAppService.UpdateWithUserAsync(input);
    }

    [HttpGet]
    [Route("Get")]
    public Task<EmployeeDto> GetAsync(Guid id)
    {
        return _employeeAppService.GetAsync(id);
    }

    [HttpGet]
    [Route("GetAll")]
    public Task<PagedResultDto<EmployeeDto>> GetAllAsync(GetAllEmployeeInput input)
    {
        return _employeeAppService.GetAllAsync(input);
    }
}

test

run project

insert image description here

On the web side, enter the organization

We create several departments at will, as shown in the following figure:

insert image description here

Create several employee users and assign them to "R&D Group A" and "R&D Group B",

Query by organizational structure

By clicking on different organizational structures, you can view different users:

Users in "R&D Group A":

insert image description here

Users in "R&D Group B":

insert image description here

Users in "unassigned":

insert image description here

Query by job title

Click "Filter" in a certain group, select job title-intermediate, and click Query

All employees whose job title is mid-level will be queried

insert image description here

insert image description here

The message Payload of the combined query is as follows:

insert image description here

In the next chapter, we will implement the general query application layer base class, so that query by organization can be applied to all business entities.

Guess you like

Origin blog.csdn.net/jevonsflash/article/details/131634633