[ Web Proxy ]
URL:
Viewing: https://raw.githubusercontent.com/pythonclound/abp-samples/master/OrganizationUnitSample/README.md [Back]  [Original]

# Organization Unit Sample Projects

This is the sample project for Organization Unit Management to demonstrate common use cases. 

Also see [Organization Unit Management docs](https://github.com/abpframework/abp/blob/dev/docs/en/Modules/Organization-Units.md).


#### Creating An Entity That Belongs To An Organization Unit

The most obvious usage of OUs is to assign an entity to an OU. [Sample Product entity](https://github.com/abpframework/abp-samples/blob/master/OrganizationUnitSample/src/OrganizationUnitSample.Domain/Products/Product.cs):

```csharp
public class Product : AuditedAggregateRoot, IMultiTenant
{
    public virtual Guid OrganizationUnitId { get; private set; }
    public virtual Guid? TenantId { get; private set;}
    public virtual string Name { get; private set; }
    public virtual float Price { get; private set; }
}
```

You need to create **OrganizationUnitId** property to assign this entity to an OU. Depending on requirement, this property can be nullable. You can now relate a Product to an OU and query the products of a specific OU.

You can use **IMultiTenant** interface if you want to distinguish products of different tenants in a multi-tenant application (see the [Multi-Tenancy document](https://github.com/abpframework/abp/blob/dev/docs/en/Multi-Tenancy.md) for more info). If your application is not multi-tenant, you don't need this interface and property.

#### Getting Entities In An Organization Unit

To get the Products of an OU, you can implement a simple domain service; [Product Manager](https://github.com/abpframework/abp-samples/blob/master/OrganizationUnitSample/src/OrganizationUnitSample.Domain/Products/ProductManager.cs) in this case to get the filtered data:

```csharp
public class ProductManager : IDomainService
{
    private readonly IProductRepository _productRepository;

    public ProductManager(IProductRepository productRepository)
    {
        _productRepository = productRepository;
    }

    public virtual Task GetProductsInOuAsync(OrganizationUnit organizationUnit)
    {
        return await AsyncExecuter.ToListAsync(_productRepository.Where(p =>
                p.OrganizationUnitId == organizationUnit.Id));
    }               
}
```

**For better practice**, you should consider querying it on domain layer for performance and scalability. To do so, add a method to your [IProductRepository](https://github.com/abpframework/abp-samples/blob/master/OrganizationUnitSample/src/OrganizationUnitSample.Domain/Products/IProductRepository.cs) interface:

```csharp
public interface IProductRepository : IRepository
{
    public Task GetProductsInOrganizationUnitAsync(Guid organizationUnitId);
}
```

Then implement it on your ORM layer (which is EntityFrameworkCore in this sample), [ProductRepository](https://github.com/abpframework/abp-samples/blob/master/OrganizationUnitSample/src/OrganizationUnitSample.EntityFrameworkCore/Products/ProductRepository.cs):

```csharp
public async Task GetProductsInOrganizationUnitAsync(Guid organizationUnitId)
{
    return await DbSet.Where(p => p.OrganizationUnitId == organizationUnitId).ToListAsync();
}
```

Afterwards, you can modify your domain service [Product Manager](https://github.com/abpframework/abp-samples/blob/master/OrganizationUnitSample/src/OrganizationUnitSample.Domain/Products/ProductManager.cs) like below:

```csharp
public async Task GetProductsInOuAsync(OrganizationUnit organizationUnit)
{
	return await _productRepository.GetProductsInOrganizationUnitAsync(organizationUnit.Id);
}
```

#### Get Entities In An Organization Unit Including It's Child Organization Units

You may want to get the Products of an organization unit including child organization units. In this case, the OU **Code** can be helpful.

You can introduce an other method for your domain service [Product Manager](https://github.com/abpframework/abp-samples/blob/master/OrganizationUnitSample/src/OrganizationUnitSample.Domain/Products/ProductManager.cs) like below:

```csharp
public class ProductManager : DomainService
{
    private readonly IProductRepository _productRepository;
    private readonly IOrganizationUnitRepository _organizationUnitRepository;

    public ProductManager(IProductRepository productRepository,
                          IOrganizationUnitRepository organizationUnitRepository)
    {
        _productRepository = productRepository;
        _organizationUnitRepository = organizationUnitRepository;
    }

    public virtual async Task GetProductsInOuIncludingChildrenAsync(
        OrganizationUnit organizationUnit)
    {
        var ouIds = (await _organizationUnitRepository.GetAllChildrenWithParentCodeAsync(
                organizationUnit.Code, organizationUnit.ParentId))
				.Select(ou => ou.Id).ToList();
            return await AsyncExecuter.ToListAsync(_productRepository.Where(p => ouIds.Contains(p.OrganizationUnitId)));
    }
}
```

This way, you can get the **organizationUnitIds** of all the children of the given OU. Then look for the products with these organizationUnitIds. This way you can hierarchically get the products of an OU.

#### Filter Entities For A User

You may want to get all products that are in the OUs of a specific user. To do so, you need to find the Ids of the OUs of the user. Then use a **Contains** condition while getting the products. **For better practice**, you should start introducing a new method to your [IProductRepository](https://github.com/abpframework/abp-samples/blob/master/OrganizationUnitSample/src/OrganizationUnitSample.Domain/Products/IProductRepository.cs) interface:

```csharp
public interface IProductRepository : IRepository
{
    public Task GetProductsOfOrganizationUnitListAsync(List organizationUnitIds);
}
```

Afterwards, implement it on your [ProductRepository](https://github.com/abpframework/abp-samples/blob/master/OrganizationUnitSample/src/OrganizationUnitSample.EntityFrameworkCore/Products/ProductRepository.cs)

```csharp
public Task GetProductsOfOrganizationUnitListAsync(List organizationUnitIds)
{
    return DbSet.Where(p => organizationUnitIds.Contains(p.OrganizationUnitId))
        .ToListAsync();
}
```

As last, you need to pass the OuIds of user to the repository on your [ProductManager](https://github.com/abpframework/abp-samples/blob/master/OrganizationUnitSample/src/OrganizationUnitSample.Domain/Products/ProductManager.cs) domain service:

```csharp
public class ProductManager : DomainService
{
    private readonly IProductRepository _productRepository;
    private readonly IdentityUserManager _userManager;

    public ProductManager(IProductRepository productRepository,
                          IdentityUserManager userManager)
    {
        _productRepository = productRepository;
        _organizationUnitRepository = organizationUnitRepository;
        _userManager = userManager;
    }

    public virtual async Task GetProductForUserAsync(Guid userId)
    {
        var user = await _userManager.GetByIdAsync(userId);
        var userOuIds = user.OrganizationUnits.Select(ou => ou.OrganizationUnitId);

        return await _productRepository.GetProductsOfOrganizationUnitListAsync(userOuIds.ToList());
    }
}
```

**See also** [ProductManagerTest](https://github.com/abpframework/abp-samples/blob/master/OrganizationUnitSample/test/OrganizationUnitSample.Domain.Tests/ProductManagerTest.cs) domain service tests and [TestOrganizationUnitDataBuilder](https://github.com/abpframework/abp-samples/blob/master/OrganizationUnitSample/test/OrganizationUnitSample.Domain.Tests/TestOrganizationUnitDataBuilder.cs) for the test data creation for this sample.

Web Proxy Viewer  |  New URL  |  Original Page