у меня есть модель
```
    public class Material:IEntity
    {
        [Key]
        public int MaterialId { get; set; }

        [Required]
        [MaxLength(50)]
        public string NumberItem { get; set; }

        [MaxLength(50)]
        public string? NodeCode { get; set; }

        [Required]
        [MaxLength(200)]
        public string? CostName { get; set; }

        public string? ISRComment { get; set; }

        public string? ContractorComment { get; set; }

        [MaxLength(50)]
        public string? UnitOfMeasure { get; set; }

        public decimal? ConsumptionCoefficient { get; set; }

        public decimal? BOCount { get; set; }

        public decimal? TotalCount { get; set; }

        public decimal? MatEquipmPrice { get; set; }

        public decimal? SmpPnpPrice { get; set; }

        public decimal? TotalPrice { get; set; }

        public decimal? MatEquipmCost { get; set; }

        public decimal? SmpPnpCost { get; set; }

        public decimal? TotalCost { get; set; }

        // Внешние ключи
        [ForeignKey("Project")]
        public int ProjectId { get; set; }

        [ForeignKey("ParentWork")]
        public int? ParentWorkId { get; set; }

        [ForeignKey("Unit")]
        public int? UnitId { get; set; }

        public string TypeCost { get; set; }

        public bool IsMigrated { get; set; }

        // Навигационные свойства
        public Project Project { get; set; }

        public Work ParentWork { get; set; }

        public Unit Unit { get; set; }

        public ICollection<WorkMaterial> WorkMaterials { get; set; } = new List<WorkMaterial>();
    }
```
вот пример контроллера
```
// Controllers/MaterialGroupingController.cs

using AutoMapper;
using BuildingFlow.Data.Contract;
using BuildingFlow.Data.Entities;
using BuildingFlow.Services.Models.ViewModels;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;


namespace BuildingFlow.Web.Controllers
{
  public class MaterialGroupingController : Controller
  {
    private readonly IUnitOfWork _unitOfWork;
    //private readonly IMapper _mapper;
    private readonly IRepository<Cost> _costRepository;
    private readonly IRepository<Unit> _unitRepository;
    private readonly IRepository<Material> _materialRepository;

    public MaterialGroupingController(IUnitOfWork unitOfWork, IMapper mapper)
    {
      _unitOfWork = unitOfWork;
      //_mapper = mapper;
      _costRepository = _unitOfWork.GetRepository<Cost>();
      _unitRepository = _unitOfWork.GetRepository<Unit>();
      _materialRepository = _unitOfWork.GetRepository<Material>();
    }

    // GET: MaterialGrouping/Index
    public async Task<IActionResult> Index()
    {
      var projectId = 1; // Замените на нужный ProjectId или передайте как параметр

      // Получаем все CostItems для заданного проекта
      var costItems = await _costRepository.AsReadOnlyQueryable()
          .Where(ci => ci.ProjectId == projectId)
          .ToListAsync();

      // Извлекаем необходимые идентификаторы для оптимизации запросов
      var unitIds = costItems.Where(ci => ci.UnitId.HasValue)
                             .Select(ci => ci.UnitId.Value)
                             .Distinct()
                             .ToList();

      var costIds = costItems.Select(ci => ci.CostId)
                             .Distinct()
                             .ToList();

      // Получаем связанные данные
      var units = await _unitRepository.AsQueryable()
          .Where(u => unitIds.Contains(u.UnitId))
          .ToListAsync();

      var materials = await _materialRepository.AsQueryable()
          .Where(m => costIds.Contains(m.CostId))
          .ToListAsync();

      // Объединяем данные: Материалы -> CostItems -> Units
      var joinedData = from m in materials
                       join ci in costItems on m.CostId equals ci.CostId
                       join u in units on ci.UnitId equals u.UnitId into unitGroup
                       from u in unitGroup.DefaultIfEmpty()
                       select new
                       {
                         CostName = ci.CostName ?? "Без названия",
                         UnitOfMeasure = u != null ? u.UnitName : "Без единицы",
                         ci.ConsumptionCoefficient,
                         ci.TotalCount,
                         ci.MatEquipmPrice,
                         ci.MatEquipmCost
                       };

      // Группируем данные по CostName, UnitOfMeasure и ConsumptionCoefficient
      var groupedData = joinedData
          .GroupBy(x => new { x.CostName, x.UnitOfMeasure, x.ConsumptionCoefficient, x.MatEquipmPrice })
          .Select(g => new GroupedMaterialViewModel
          {
            CostName = g.Key.CostName,
            UnitOfMeasure = g.Key.UnitOfMeasure,
            ConsumptionCoefficient = g.Key.ConsumptionCoefficient,
            TotalCount = g.Sum(x => x.TotalCount),
            //MatEquipmPrice = g.Sum(x => x.MatEquipmPrice)
            MatEquipmPrice = g.Key.MatEquipmPrice,
            MatEquipmCost = g.Sum(x => x.MatEquipmCost)
          })
          .OrderBy(x => x.CostName)
          .ToList();

      return View(groupedData);
    }
  }
}
```
напиши код нового контроллера который сгруппирует данные по полям CostName, UnitOfMeasure, MatEquipmPrice и рассчитает сумму полей TotalCount, MatEquipmCost
так же напиши код представления для отображения полученных данных в виде таблицы, примени bootstrap 5, в таблице должна быть итоговая строка с суммами полей TotalCount, MatEquipmCost