Example #1
0
        public async Task SeedAllAsync(CancellationToken cancellationToken)
        {
            if (context.PaidTimeOffPolicies.Any())
            {
                logger.LogInformation("Database has already been initialized with basic data. Nothing to do.");
                return;
            }

            await SeedPtoPoliciesAsync();
            await SeedCurrenciesAsync();

            await context.SaveChangesAsync(cancellationToken);
        }
            public async Task <RegisterOrUpdateEmployeeCommand> Handle(RegisterOrUpdateEmployeeCommand request, CancellationToken cancellationToken)
            {
                // Map the view model to a domain entity. We are now in the realm of business entities and logic.
                var employee = employeeVmToDomainEntityMapper.MapToDomainEntity(request);

                var isNewEmployee = employee.Id == null;

                // Look up manager from DB.
                EmployeeEntity managerEntity = null;

                if (request.ManagerId != null)
                {
                    managerEntity = await context.Employees.FindAsync(request.ManagerId);

                    if (managerEntity == null)
                    {
                        throw new EmployeeException($"Manager with ID {request.ManagerId} not found.");
                    }
                    // Convert to domain entity as well.
                    employee = employee.WithManager(employeeDomainToDbEntityMapper.MapToDomainEntity(managerEntity));
                }

                // Look up subordinates and map those to domain entities.
                var subordinateIds      = request.SubordinateIds.ToArray();
                var subordinateEntities = await(from e in context.Employees.AsNoTracking() where subordinateIds.Contains(e.Id) select e).ToArrayAsync();

                employee = employee.WithSubordinates(from e in subordinateEntities select employeeDomainToDbEntityMapper.MapToDomainEntity(e));

                // Get PTO policy for this employee and map to domain entity.
                var policyEntity = await context.PaidTimeOffPolicies.AsNoTracking().FirstOrDefaultAsync(p => p.Id == request.PaidTimeOffPolicyId);

                if (policyEntity == null)
                {
                    throw new EmployeeException($"PTO policy not found.");
                }
                var policy = ptoPolicyDomainToDbEntityMapper.MapToDomainEntity(policyEntity);

                employee = employee.WithPaidTimeOffPolicy(policy);

                // Check the validity of the employee's PTO hours and other business logic. All business rule validation is still happening within the Domain layer...
                employee.AssertAggregates();
                employee.VerifyEmployeeManagerAndSubordinates();
                if (isNewEmployee)
                {
                    employee.VerifyStartingPtoHoursAreValid();
                }
                else
                {
                    employee.VerifyPtoHoursAreValid();
                }
                // End business logic.

                // Convert back to persistence entity.
                var employeeEntity = employeeDomainToDbEntityMapper.MapToDbEntity(employee);

                employeeEntity.TenantId = TenantId;
                var entry = await context.Employees.AddAsync(employeeEntity);

                if (!isNewEmployee)
                {
                    entry.State = EntityState.Modified;
                }

                // Delete previous entity relationships.
                context.EmployeeManagers.RemoveRange(context.EmployeeManagers.Where(em => em.EmployeeId == employee.Id));
                context.EmployeeManagers.RemoveRange(context.EmployeeManagers.Where(em => em.ManagerId == employee.Id));

                // Commit transaction to DB.
                await context.SaveChangesAsync(cancellationToken);

                // Create new relationships.
                if (employee.Manager != null)
                {
                    await context.EmployeeManagers.AddAsync(new EmployeeManagerEntity { TenantId = TenantId, EmployeeId = employeeEntity.Id, ManagerId = managerEntity.Id });
                }
                await context.EmployeeManagers.AddRangeAsync(from s in subordinateEntities select new EmployeeManagerEntity {
                    TenantId = TenantId, EmployeeId = s.Id, ManagerId = employeeEntity.Id
                });

                // Commit transaction to DB.
                if (context.HasChanges)
                {
                    await context.SaveChangesAsync(cancellationToken);
                }

                // Set ID of domain entity.
                employee.Id = employeeEntity.Id;

                // Kick off domain events.
                employee.CreateEmployeeRegisteredEvent(dateTimeService);
                await employee.DispatchDomainEventsAsync();

                // Map from domain entity back to VM (command) and return that.
                return(employeeVmToDomainEntityMapper.MapToViewModel(employee));
            }