Files
InventoryTraker-Box/InventoryTraker.Web/Controllers/ReportController.cs
T
2016-09-21 11:55:06 -04:00

211 lines
5.9 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web.Mvc;
using AutoMapper;
using AutoMapper.QueryableExtensions;
using InventoryTraker.Web.Core;
using InventoryTraker.Web.Data;
using InventoryTraker.Web.Models;
using InventoryTraker.Web.Utilities;
namespace InventoryTraker.Web.Controllers
{
public class ReportController : ControllerBase
{
private readonly AppDbContext _context;
public ReportController(AppDbContext context)
{
_context = context;
}
[HttpGet]
public ActionResult Distribution()
{
return View();
}
public ActionResult Distribution(DateTime startDate, DateTime endDate)
{
var query =
from t in _context.Transactions
where
t.TransactionType == TransactionType.Distributed
&& t.TransactionDate >= startDate
&& t.TransactionDate < endDate
group t by new { t.TransactionDate, t.Destination }
into g
select new
{
Date = g.Key.TransactionDate,
Destination = g.Key.Destination,
Transactions = g.ToList()
};
var report =
from item in query.ToArray()
select new DistributionReport
{
Date = item.Date,
Destination = item.Destination,
Transactions =
Mapper.Map<IList<Transaction>, IList<TransactionViewModel>>
(item.Transactions).ToArray()
};
return BetterJson(report.ToArray());
}
[HttpGet]
public ActionResult Movement()
{
return View();
}
public ActionResult Movement(DateTime month)
{
var report = GetMovementReport(month);
return BetterJson(report);
}
public ActionResult MovementExcel(DateTime month)
{
var report = GetMovementReport(month);
var writer = new MovementReportWriter();
var excel = writer.Write(report);
var filename = $"MonthlyInventoryReport{report.Month:MMMMyyyy}.xlsx";
return
new FileContentResult(excel, "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")
{
FileDownloadName = filename
};
}
private MovementReport GetMovementReport(DateTime month)
{
var startDate = month;
var endDate = startDate.AddMonths(1);
return
new MovementReport
{
Items = GetMovementReportItems(startDate, endDate),
Month = month
};
}
private IEnumerable<MovementReportItem> GetMovementReportItems(DateTime startDate, DateTime endDate)
{
var transactionsMostRecentBefore =
(from transaction in _context.Transactions
where
transaction.TransactionDate < startDate
group transaction by transaction.Inventory
into g
let mostRecent =
g.OrderByDescending(t => t.TransactionDate)
.ThenBy(t => t.CurrentQuantity) // for days with multiple, assume it's the smallest
.FirstOrDefault()
where mostRecent.CurrentQuantity > 0
select mostRecent).ToList();
var transactionSums =
(from transaction in _context.Transactions
where
transaction.TransactionDate >= startDate
&& transaction.TransactionDate < endDate
group transaction by transaction.Inventory
into g
let addedQty = g.Sum(t => t.AddedQuantity)
let distributed = g.Where(t => t.TransactionType == TransactionType.Distributed)
let distributedQty = distributed.Any() ? distributed.Sum(t => t.RemovedQuantity) : 0
let adjustment = g.Where(t =>
t.TransactionType == TransactionType.Expired
|| t.TransactionType == TransactionType.Loss)
let adjustmentQty = adjustment.Any() ? adjustment.Sum(t => t.RemovedQuantity) : 0
let endingQty =
g
.OrderByDescending(t => t.TransactionDate)
.ThenBy(t => t.CurrentQuantity)
.FirstOrDefault().CurrentQuantity
select new
{
Inventory = g.Key,
addedQty,
adjustmentQty,
distributedQty,
endingQty
}).ToList();
var inventoryReportItems =
transactionsMostRecentBefore.FullOuterJoin( // source
transactionSums, // inner
before => before.Inventory.Id, // fk
sums => sums.Inventory.Id, // pk
(before, sums, r) =>
{
var item = new MovementReportInventoryItem();
if (before != null)
{
item.Inventory = before.Inventory;
item.BeginningQuantity = before.CurrentQuantity;
if (sums != null)
{
item.AddedQuantity = sums.addedQty;
item.DistributedQuantity = sums.distributedQty;
item.AdjustmentQuantity = sums.adjustmentQty;
item.EndingQuantity = sums.endingQty;
}
else // no change
{
item.EndingQuantity = item.BeginningQuantity;
}
}
else if (sums != null) // item was added in this time period
{
item.Inventory = sums.Inventory;
item.AddedQuantity = sums.addedQty;
item.DistributedQuantity = sums.distributedQty;
item.AdjustmentQuantity = sums.adjustmentQty;
item.EndingQuantity = sums.endingQty;
}
item.TotalAvailableQuantity = item.BeginningQuantity + item.AddedQuantity;
return item;
}).ToArray();
// group by inventory type
var inventoryTypeReportItems =
from item in inventoryReportItems
group item by item.Inventory.InventoryType
into grp
select new MovementReportItem
{
InventoryType = Mapper.Map<InventoryTypeViewModel>(grp.Key),
BeginningQuantity = grp.Sum(g => g.BeginningQuantity),
AddedQuantity = grp.Sum(g => g.AddedQuantity),
TotalAvailableQuantity = grp.Sum(g => g.TotalAvailableQuantity),
DistributedQuantity = grp.Sum(g => g.DistributedQuantity),
AdjustmentQuantity = grp.Sum(g => g.AdjustmentQuantity),
EndingQuantity = grp.Sum(g => g.EndingQuantity)
};
return inventoryTypeReportItems;
}
}
internal class MovementReportInventoryItem
{
public Inventory Inventory { get; set; }
public int BeginningQuantity { get; set; }
public int AddedQuantity { get; set; }
public int TotalAvailableQuantity { get; set; }
public int DistributedQuantity { get; set; }
public int AdjustmentQuantity { get; set; }
public int EndingQuantity { get; set; }
}
}