Загрузка данных


return dataContext.Projects
    .Where(x => x.GetParentHierarchy<Project>(true)
        .Any(p => p is Proekt_AP && p.Name == "НАЗВАНИЕ ПРОЕКТА"))
    .Where(x => x is Zadacha)

    .Select(x => new
    {
        Id = x.Id,
        Задача = x.Name,
        Календарь = x.CalendarId,
        ПланНачало = x.SystemStartDate,
        ПланЗавершение = x.SystemEndDate,

        Лимит = x.Fields.Limit_n_ch == null
            ? 0.0
            : x.Fields.Limit_n_ch.Value,

        Факт = x.GetChildrenHierarchy<Uchet_vremeni>(true)
            .Select(p => p.Fakt_ch_ch == null ? 0.0 : p.Fakt_ch_ch.Value)
            .DefaultIfEmpty(0.0)
            .Sum(),

        Статус = x.Status.ToString(),

        Факты = x.GetChildrenHierarchy<Uchet_vremeni>(true)
            .Select(p => new
            {
                Дата = p.Date,
                Факт = p.Fakt_ch_ch
            })
    })

    .ToList()

    .Select(x =>
    {
        var calendar = workCalendars.GetWorkCalendar(x.Календарь);

        var остаток =
            x.Статус == "Complete"
                ? 0.0
                : x.Лимит > x.Факт
                    ? x.Лимит - x.Факт
                    : 0.0;


        Func<DateTime, DateTime, double?> calcFactMonth =
            (monthStart, monthEnd) =>
        {
            var monthFacts = x.Факты
                .Where(p =>
                    p.Дата >= monthStart &&
                    p.Дата <= monthEnd);

            if (monthFacts.Any())
                return monthFacts
                    .Select(p => p.Факт == null ? 0.0 : p.Факт.Value)
                    .Sum();

            return null;
        };


        Func<DateTime, DateTime, double> calcNoFactMonthHours =
            (monthStart, monthEnd) =>
        {
            if (x.ПланНачало == null ||
                x.ПланЗавершение == null)
                return 0.0;

            if (calcFactMonth(monthStart, monthEnd) != null)
                return 0.0;

            if (x.ПланНачало.Value.Date > monthEnd ||
                x.ПланЗавершение.Value.Date < monthStart)
                return 0.0;

            var monthPartStart =
                x.ПланНачало.Value.Date > monthStart
                    ? x.ПланНачало.Value.Date
                    : monthStart;

            var monthPartEnd =
                x.ПланЗавершение.Value.Date < monthEnd
                    ? x.ПланЗавершение.Value.Date
                    : monthEnd;

            return calendar.GetWorktimeHours(
                monthPartStart,
                calendar.GetDayEnd(monthPartEnd));
        };


        double totalHoursOld = 0.0;
        double totalHoursNew = 0.0;

        if (x.ПланНачало != null &&
            x.ПланЗавершение != null)
        {
            totalHoursOld =
                calcNoFactMonthHours(new DateTime(2025, 6, 1),  new DateTime(2025, 6, 30)) +
                calcNoFactMonthHours(new DateTime(2025, 7, 1),  new DateTime(2025, 7, 31)) +
                calcNoFactMonthHours(new DateTime(2025, 8, 1),  new DateTime(2025, 8, 31)) +
                calcNoFactMonthHours(new DateTime(2025, 9, 1),  new DateTime(2025, 9, 30)) +
                calcNoFactMonthHours(new DateTime(2025, 10, 1), new DateTime(2025, 10, 31)) +
                calcNoFactMonthHours(new DateTime(2025, 11, 1), new DateTime(2025, 11, 30)) +
                calcNoFactMonthHours(new DateTime(2025, 12, 1), new DateTime(2025, 12, 31)) +

                calcNoFactMonthHours(new DateTime(2026, 1, 1),  new DateTime(2026, 1, 31)) +
                calcNoFactMonthHours(new DateTime(2026, 2, 1),  new DateTime(2026, 2, 28)) +
                calcNoFactMonthHours(new DateTime(2026, 3, 1),  new DateTime(2026, 3, 31)) +
                calcNoFactMonthHours(new DateTime(2026, 4, 1),  new DateTime(2026, 4, 30)) +
                calcNoFactMonthHours(new DateTime(2026, 5, 1),  new DateTime(2026, 5, 31)) +
                calcNoFactMonthHours(new DateTime(2026, 6, 1),  new DateTime(2026, 6, 30)) +
                calcNoFactMonthHours(new DateTime(2026, 7, 1),  new DateTime(2026, 7, 31)) +
                calcNoFactMonthHours(new DateTime(2026, 8, 1),  new DateTime(2026, 8, 31)) +
                calcNoFactMonthHours(new DateTime(2026, 9, 1),  new DateTime(2026, 9, 30)) +
                calcNoFactMonthHours(new DateTime(2026, 10, 1), new DateTime(2026, 10, 31)) +
                calcNoFactMonthHours(new DateTime(2026, 11, 1), new DateTime(2026, 11, 30)) +
                calcNoFactMonthHours(new DateTime(2026, 12, 1), new DateTime(2026, 12, 31)) +

                calcNoFactMonthHours(new DateTime(2027, 1, 1),  new DateTime(2027, 1, 31)) +
                calcNoFactMonthHours(new DateTime(2027, 2, 1),  new DateTime(2027, 2, 28)) +
                calcNoFactMonthHours(new DateTime(2027, 3, 1),  new DateTime(2027, 3, 31)) +
                calcNoFactMonthHours(new DateTime(2027, 4, 1),  new DateTime(2027, 4, 30)) +
                calcNoFactMonthHours(new DateTime(2027, 5, 1),  new DateTime(2027, 5, 31)) +
                calcNoFactMonthHours(new DateTime(2027, 6, 1),  new DateTime(2027, 6, 30)) +
                calcNoFactMonthHours(new DateTime(2027, 7, 1),  new DateTime(2027, 7, 31)) +
                calcNoFactMonthHours(new DateTime(2027, 8, 1),  new DateTime(2027, 8, 31)) +
                calcNoFactMonthHours(new DateTime(2027, 9, 1),  new DateTime(2027, 9, 30)) +
                calcNoFactMonthHours(new DateTime(2027, 10, 1), new DateTime(2027, 10, 31)) +
                calcNoFactMonthHours(new DateTime(2027, 11, 1), new DateTime(2027, 11, 30)) +
                calcNoFactMonthHours(new DateTime(2027, 12, 1), new DateTime(2027, 12, 31));


            var firstMonth = new DateTime(
                x.ПланНачало.Value.Year,
                x.ПланНачало.Value.Month,
                1);

            var lastMonth = new DateTime(
                x.ПланЗавершение.Value.Year,
                x.ПланЗавершение.Value.Month,
                1);

            var monthsCount =
                (lastMonth.Year - firstMonth.Year) * 12 +
                lastMonth.Month - firstMonth.Month + 1;

            totalHoursNew = Enumerable.Range(0, monthsCount)
                .Select(i =>
                {
                    var mStart = firstMonth.AddMonths(i);
                    var mEnd = mStart.AddMonths(1).AddDays(-1);

                    return calcNoFactMonthHours(mStart, mEnd);
                })
                .Sum();
        }


        Func<DateTime, DateTime, double, double?> calcPlan =
            (monthStart, monthEnd, totalHours) =>
        {
            if (x.ПланНачало == null ||
                x.ПланЗавершение == null)
                return 0.0;

            if (x.ПланНачало.Value.Date > monthEnd ||
                x.ПланЗавершение.Value.Date < monthStart)
                return null;

            var factMonth = calcFactMonth(monthStart, monthEnd);

            if (factMonth != null)
                return factMonth;

            var monthPartStart =
                x.ПланНачало.Value.Date > monthStart
                    ? x.ПланНачало.Value.Date
                    : monthStart;

            var monthPartEnd =
                x.ПланЗавершение.Value.Date < monthEnd
                    ? x.ПланЗавершение.Value.Date
                    : monthEnd;

            var monthHours = calendar.GetWorktimeHours(
                monthPartStart,
                calendar.GetDayEnd(monthPartEnd));

            return totalHours <= 0.0
                ? 0.0
                : Math.Round(
                    остаток * monthHours / totalHours,
                    2);
        };


        var oldJan = calcPlan(new DateTime(2026, 1, 1), new DateTime(2026, 1, 31), totalHoursOld) ?? 0.0;
        var oldFeb = calcPlan(new DateTime(2026, 2, 1), new DateTime(2026, 2, 28), totalHoursOld) ?? 0.0;
        var oldMar = calcPlan(new DateTime(2026, 3, 1), new DateTime(2026, 3, 31), totalHoursOld) ?? 0.0;
        var oldApr = calcPlan(new DateTime(2026, 4, 1), new DateTime(2026, 4, 30), totalHoursOld) ?? 0.0;
        var oldMay = calcPlan(new DateTime(2026, 5, 1), new DateTime(2026, 5, 31), totalHoursOld) ?? 0.0;
        var oldJun = calcPlan(new DateTime(2026, 6, 1), new DateTime(2026, 6, 30), totalHoursOld) ?? 0.0;
        var oldJul = calcPlan(new DateTime(2026, 7, 1), new DateTime(2026, 7, 31), totalHoursOld) ?? 0.0;
        var oldAug = calcPlan(new DateTime(2026, 8, 1), new DateTime(2026, 8, 31), totalHoursOld) ?? 0.0;
        var oldSep = calcPlan(new DateTime(2026, 9, 1), new DateTime(2026, 9, 30), totalHoursOld) ?? 0.0;
        var oldOct = calcPlan(new DateTime(2026, 10, 1), new DateTime(2026, 10, 31), totalHoursOld) ?? 0.0;
        var oldNov = calcPlan(new DateTime(2026, 11, 1), new DateTime(2026, 11, 30), totalHoursOld) ?? 0.0;
        var oldDec = calcPlan(new DateTime(2026, 12, 1), new DateTime(2026, 12, 31), totalHoursOld) ?? 0.0;


        var newJan = calcPlan(new DateTime(2026, 1, 1), new DateTime(2026, 1, 31), totalHoursNew) ?? 0.0;
        var newFeb = calcPlan(new DateTime(2026, 2, 1), new DateTime(2026, 2, 28), totalHoursNew) ?? 0.0;
        var newMar = calcPlan(new DateTime(2026, 3, 1), new DateTime(2026, 3, 31), totalHoursNew) ?? 0.0;
        var newApr = calcPlan(new DateTime(2026, 4, 1), new DateTime(2026, 4, 30), totalHoursNew) ?? 0.0;
        var newMay = calcPlan(new DateTime(2026, 5, 1), new DateTime(2026, 5, 31), totalHoursNew) ?? 0.0;
        var newJun = calcPlan(new DateTime(2026, 6, 1), new DateTime(2026, 6, 30), totalHoursNew) ?? 0.0;
        var newJul = calcPlan(new DateTime(2026, 7, 1), new DateTime(2026, 7, 31), totalHoursNew) ?? 0.0;
        var newAug = calcPlan(new DateTime(2026, 8, 1), new DateTime(2026, 8, 31), totalHoursNew) ?? 0.0;
        var newSep = calcPlan(new DateTime(2026, 9, 1), new DateTime(2026, 9, 30), totalHoursNew) ?? 0.0;
        var newOct = calcPlan(new DateTime(2026, 10, 1), new DateTime(2026, 10, 31), totalHoursNew) ?? 0.0;
        var newNov = calcPlan(new DateTime(2026, 11, 1), new DateTime(2026, 11, 30), totalHoursNew) ?? 0.0;
        var newDec = calcPlan(new DateTime(2026, 12, 1), new DateTime(2026, 12, 31), totalHoursNew) ?? 0.0;


        return new
        {
            x.Id,
            x.Задача,
            x.Статус,
            x.ПланНачало,
            x.ПланЗавершение,

            x.Лимит,
            x.Факт,
            Остаток = остаток,

            TotalHoursСтарый = totalHoursOld,
            TotalHoursНовый = totalHoursNew,

            ЯнварьСтарый = oldJan,
            ЯнварьНовый = newJan,

            ФевральСтарый = oldFeb,
            ФевральНовый = newFeb,

            МартСтарый = oldMar,
            МартНовый = newMar,

            АпрельСтарый = oldApr,
            АпрельНовый = newApr,

            МайСтарый = oldMay,
            МайНовый = newMay,

            ИюньСтарый = oldJun,
            ИюньНовый = newJun,

            ИюльСтарый = oldJul,
            ИюльНовый = newJul,

            АвгустСтарый = oldAug,
            АвгустНовый = newAug,

            СентябрьСтарый = oldSep,
            СентябрьНовый = newSep,

            ОктябрьСтарый = oldOct,
            ОктябрьНовый = newOct,

            НоябрьСтарый = oldNov,
            НоябрьНовый = newNov,

            ДекабрьСтарый = oldDec,
            ДекабрьНовый = newDec,

            План2026Старый =
                oldJan + oldFeb + oldMar + oldApr +
                oldMay + oldJun + oldJul + oldAug +
                oldSep + oldOct + oldNov + oldDec,

            План2026Новый =
                newJan + newFeb + newMar + newApr +
                newMay + newJun + newJul + newAug +
                newSep + newOct + newNov + newDec
        };
    })

    .OrderBy(x => x.Задача);