Sobes.tech
Junior — Senior

Code review and improvement of the organization service structure

livecode

Task condition

It is necessary to review the code and refactor the presented service, improving readability, eliminating unnecessary database calls, and fixing logical errors. The provided class implements methods for getting and setting the organization's logo, as well as calculating total expenses for projects.

public class OrganizationService
{
    private readonly IStorageService _storage;
    private readonly IAlertService _alert;
    private readonly IProjectApi _projectApi;
    private readonly ApplicationDbContext _db;

    public OrganizationService(
        IStorageService storage,
        IAlertService alert,
        IProjectApi projectApi,
        ApplicationDbContext db)
    {
        _storage = storage;
        _alert = alert;
        _projectApi = projectApi;
        _db = db;
    }

    public byte[] GetOrganizationLogo(Guid organizationId)
    {
        var orgList = _db.Organizations.ToList();
        var org = orgList.First(entity => entity.Id == organizationId);

        var logoId = org.LogoId;

        var memoryStream = new MemoryStream();
        Stream image = _storage.GetByObjectId(logoId);
        image.CopyTo(memoryStream);

        return memoryStream.ToArray();
    }

    public void SetOrganizationLogo(Guid organizationId, Stream logo)
    {
        var logoId = _storage.UploadLogo(logo);

        var orgList = _db.Organizations.ToList();
        var org = orgList.First(entity => entity.Id == organizationId);

        org.LogoId = logoId;

        _db.SaveChangesAsync(default);

        _alert.NotifyLogoChanged(org.Id);
    }

    public async Task<long> Calculate(Guid organizationId, DateTime? start, DateTime? finished, CancellationToken ct)
    {
        var orgList = _db.Organizations.ToList();
        var org = orgList.First(entity => entity.Id == organizationId);

        var projects = await _projectApi.GetProjectsAsync(org.Id, default);

        var result = 0L;

        foreach (var project in projects)
        {
            if (project.CompleteDate > start || project.CompleteDate < finished)
            {
                result += project.Cost;
            }
        }

        return result;
    }
}