You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
470 lines
20 KiB
470 lines
20 KiB
using Kean.Application.Command.ViewModels;
|
|
using Microsoft.AspNetCore.Mvc;
|
|
using Newtonsoft.Json;
|
|
using Newtonsoft.Json.Linq;
|
|
using OfficeOpenXml;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Threading.Tasks;
|
|
|
|
namespace Kean.Presentation.Rest.Controllers
|
|
{
|
|
/// <summary>
|
|
/// 库存服务
|
|
/// </summary>
|
|
[ApiController, Route("api/stocks")]
|
|
public class StocksController : ControllerBase
|
|
{
|
|
private readonly Application.Command.Interfaces.IStockService _stockCommandService; // 库存命令服务
|
|
private readonly Application.Query.Interfaces.IStockService _stockQueryService; // 库存查询服务
|
|
private readonly Application.Query.Interfaces.IWarehouseService _warehouseQueryService; // 库房查询服务
|
|
private readonly Application.Query.Interfaces.IIdentityService _identityQueryService; // 身份查询服务
|
|
|
|
/// <summary>
|
|
/// 依赖注入
|
|
/// </summary>
|
|
public StocksController(
|
|
Application.Command.Interfaces.IStockService stockCommandService,
|
|
Application.Query.Interfaces.IStockService stockQueryService,
|
|
Application.Query.Interfaces.IIdentityService identityQueryService,
|
|
Application.Query.Interfaces.IWarehouseService warehouseQueryService)
|
|
{
|
|
_stockCommandService = stockCommandService;
|
|
_stockQueryService = stockQueryService;
|
|
_identityQueryService = identityQueryService;
|
|
_warehouseQueryService = warehouseQueryService;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 获取库存列表
|
|
/// </summary>
|
|
/// <response code="200">成功</response>
|
|
[HttpGet]
|
|
[ProducesResponseType(200)]
|
|
public async Task<IActionResult> GetList(
|
|
[FromQuery] int[] area,
|
|
[FromQuery] bool? pallet,
|
|
[FromQuery] bool? palletized,
|
|
[FromQuery] int[] category,
|
|
[FromQuery] string code,
|
|
[FromQuery] string name,
|
|
[FromQuery] string batch,
|
|
[FromQuery] string barcode,
|
|
[FromQuery] string cell,
|
|
[FromQuery] string qc,
|
|
[FromQuery] string qualityState,
|
|
[FromQuery] string materialAgeStatus,
|
|
[FromQuery] DateTime? inboundTimeFrom,
|
|
[FromQuery] DateTime? inboundTimeTo,
|
|
[FromQuery] DateTime? manufacturingDateFrom,
|
|
[FromQuery] DateTime? manufacturingDateTo,
|
|
[FromQuery] DateTime? inventoryTimeFrom,
|
|
[FromQuery] DateTime? inventoryTimeTo,
|
|
[FromQuery] bool? overdue,
|
|
[FromQuery] bool? enabled,
|
|
[FromQuery] bool? excludeTask,
|
|
[FromQuery] string sort,
|
|
[FromQuery] int? offset,
|
|
[FromQuery] int? limit,
|
|
[FromQuery] string remark,
|
|
[FromQuery] string supplier,
|
|
[FromQuery] string laneway,
|
|
[FromQuery] string workorderNo,
|
|
[FromQuery] bool bQty,
|
|
[FromQuery] string bill)
|
|
{
|
|
if (area.Length == 0)
|
|
{
|
|
area = null;
|
|
}
|
|
if (category.Length == 0)
|
|
{
|
|
category = null;
|
|
}
|
|
var items = await _stockQueryService.GetStockList(area, pallet, palletized, category, code, name, batch, barcode, cell, qc, inboundTimeFrom, inboundTimeTo, inventoryTimeFrom, inventoryTimeTo, overdue, enabled, excludeTask, sort, offset, limit, qualityState, materialAgeStatus, manufacturingDateFrom, manufacturingDateTo, remark, supplier, laneway, workorderNo, bill);
|
|
|
|
decimal qtyCurrent = 0;
|
|
decimal qtySum = 0;
|
|
decimal transQtyCurrent = 0;
|
|
decimal transQtySum = 0;
|
|
|
|
if (bQty)
|
|
{
|
|
qtyCurrent = await _stockQueryService.GetStockQtySum(area, pallet, palletized, category, code, name, batch, barcode, cell, qc, inboundTimeFrom, inboundTimeTo, inventoryTimeFrom, inventoryTimeTo, overdue, enabled, excludeTask, sort, offset, limit, qualityState, materialAgeStatus, manufacturingDateFrom, manufacturingDateTo, remark, supplier, laneway, workorderNo, bill);
|
|
transQtyCurrent = qtyCurrent;
|
|
}
|
|
|
|
if (offset.HasValue || limit.HasValue)
|
|
{
|
|
var total = await _stockQueryService.GetStockCount(area, pallet, palletized, category, code, name, batch, barcode, cell, qc, inboundTimeFrom, inboundTimeTo, inventoryTimeFrom, inventoryTimeTo, overdue, enabled, excludeTask, qualityState, materialAgeStatus, manufacturingDateFrom, manufacturingDateTo, remark, supplier, laneway, workorderNo, bill);
|
|
|
|
if (bQty)
|
|
{
|
|
qtySum = await _stockQueryService.GetStockQtySum(area, pallet, palletized, category, code, name, batch, barcode, cell, qc, inboundTimeFrom, inboundTimeTo, inventoryTimeFrom, inventoryTimeTo, overdue, enabled, excludeTask, null, null, null, qualityState, materialAgeStatus, manufacturingDateFrom, manufacturingDateTo, remark, supplier, laneway, workorderNo, bill);
|
|
transQtySum = qtySum;
|
|
|
|
Application.Query.ViewModels.Stock statistics = new Application.Query.ViewModels.Stock();
|
|
statistics.QualifiedNum = $"{qtyCurrent} / {qtySum}";
|
|
statistics.TransQty = $"{transQtyCurrent} / {transQtySum}";
|
|
statistics.Barcode = "";
|
|
|
|
|
|
items = items.Concat(new[]{ statistics});
|
|
}
|
|
|
|
|
|
return StatusCode(200, new {
|
|
items,
|
|
total
|
|
});
|
|
}
|
|
else
|
|
{
|
|
if (bQty)
|
|
{
|
|
var statistics = new Application.Query.ViewModels.Stock();
|
|
statistics.QualifiedNum = $"{qtyCurrent} / {qtyCurrent}";
|
|
statistics.TransQty = $"{transQtyCurrent} / {transQtyCurrent}";
|
|
statistics.Barcode = "";
|
|
|
|
items = items.Concat(new[] { statistics });
|
|
}
|
|
|
|
|
|
return StatusCode(200, new {
|
|
items,
|
|
total = items.Count()
|
|
});
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 导出库存列表
|
|
/// </summary>
|
|
/// <response code="200">成功</response>
|
|
[HttpGet("excel")]
|
|
[ProducesResponseType(200)]
|
|
public async Task<IActionResult> Export(
|
|
[FromQuery] int[] area,
|
|
[FromQuery] bool? pallet,
|
|
[FromQuery] bool? palletized,
|
|
[FromQuery] int[] category,
|
|
[FromQuery] string code,
|
|
[FromQuery] string name,
|
|
[FromQuery] string batch,
|
|
[FromQuery] string barcode,
|
|
[FromQuery] string cell,
|
|
[FromQuery] string qc,
|
|
[FromQuery] string qualityState,
|
|
[FromQuery] string materialAgeStatus,
|
|
[FromQuery] DateTime? inboundTimeFrom,
|
|
[FromQuery] DateTime? inboundTimeTo,
|
|
[FromQuery] DateTime? inventoryTimeFrom,
|
|
[FromQuery] DateTime? inventoryTimeTo,
|
|
[FromQuery] bool? overdue,
|
|
[FromQuery] bool? enabled,
|
|
[FromQuery] bool? excludeTask,
|
|
[FromQuery] DateTime? manufacturingDateFrom,
|
|
[FromQuery] DateTime? manufacturingDateTo,
|
|
[FromQuery] string remark,
|
|
[FromQuery] string supplier,
|
|
[FromQuery] string laneway,
|
|
[FromQuery] string workorderNo,
|
|
[FromQuery] string bill)
|
|
{
|
|
if (area.Length == 0)
|
|
{
|
|
area = null;
|
|
}
|
|
if (category.Length == 0)
|
|
{
|
|
category = null;
|
|
}
|
|
using var package = new ExcelPackage();
|
|
var worksheet = package.Workbook.Worksheets.Add("Sheet1");
|
|
var column = 0;
|
|
worksheet.Cells[1, ++column].Value = "托盘";
|
|
worksheet.Cells[1, ++column].Value = "物料编码";
|
|
worksheet.Cells[1, ++column].Value = "物料名称";
|
|
worksheet.Cells[1, ++column].Value = "仓库";
|
|
worksheet.Cells[1, ++column].Value = "货位";
|
|
worksheet.Cells[1, ++column].Value = "膜卷码";
|
|
worksheet.Cells[1, ++column].Value = "质量状态";
|
|
worksheet.Cells[1, ++column].Value = "库存状态";
|
|
worksheet.Cells[1, ++column].Value = "过账状态";
|
|
worksheet.Cells[1, ++column].Value = "生产日期";
|
|
worksheet.Cells[1, ++column].Value = "货龄(天)";
|
|
worksheet.Cells[1, ++column].Value = "创建时间";
|
|
worksheet.Cells[1, ++column].Value = "工单号";
|
|
worksheet.Cells[1, ++column].Value = "数量";
|
|
worksheet.Cells[1, ++column].Value = "单位";
|
|
worksheet.Cells[1, ++column].Value = "备注";
|
|
var index = 1;
|
|
|
|
foreach (var item in await _stockQueryService.GetStockList(area, pallet, palletized, category, code, name, batch, barcode, cell, qc, inboundTimeFrom, inboundTimeTo, inventoryTimeFrom, inventoryTimeTo, overdue, enabled, excludeTask, null, null, null, qualityState, materialAgeStatus, manufacturingDateFrom, manufacturingDateTo, remark, supplier, laneway, workorderNo, bill))
|
|
{
|
|
index++;
|
|
column = 0;
|
|
worksheet.Cells[index, ++column].Value = item.Barcode;
|
|
worksheet.Cells[index, ++column].Value = item.Code;
|
|
worksheet.Cells[index, ++column].Value = item.Name;
|
|
worksheet.Cells[index, ++column].Value = item.Warehouse;
|
|
worksheet.Cells[index, ++column].Value = item.Cell;
|
|
worksheet.Cells[index, ++column].Value = item.Bill;
|
|
string qs = "";
|
|
if (item.QualityState == "ok")
|
|
{
|
|
qs = "合格";
|
|
} else if (item.QualityState == "ng")
|
|
{
|
|
qs = "NG";
|
|
}
|
|
else if (item.QualityState == "check")
|
|
{
|
|
qs = "验证品";
|
|
}
|
|
worksheet.Cells[index, ++column].Value = qs;
|
|
worksheet.Cells[index, ++column].Value = item.Enabled == true? "可用": "冻结";
|
|
worksheet.Cells[index, ++column].Value = "";
|
|
worksheet.Cells[index, ++column].Value = item.ManufacturingDate;
|
|
worksheet.Cells[index, column].Style.Numberformat.Format = "yyyy-MM-dd HH:mm:ss";
|
|
worksheet.Cells[index, ++column].Value = item.MaterialAge;
|
|
worksheet.Cells[index, ++column].Value = item.InboundTime;
|
|
worksheet.Cells[index, column].Style.Numberformat.Format = "yyyy-MM-dd HH:mm:ss";
|
|
worksheet.Cells[index, ++column].Value = item.WorkorderNo;
|
|
worksheet.Cells[index, ++column].Value = item.TransQty;
|
|
worksheet.Cells[index, ++column].Value = item.TransUnit;
|
|
worksheet.Cells[index, ++column].Value = item.Remark;
|
|
}
|
|
return File(package.GetAsByteArray(), "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
|
|
}
|
|
|
|
/// <summary>
|
|
/// 创建库动
|
|
/// </summary>
|
|
/// <response code="201">成功</response>
|
|
/// <response code="405">非法操作</response>
|
|
/// <response code="422">请求内容错误</response>
|
|
[HttpPost]
|
|
[ProducesResponseType(201)]
|
|
[ProducesResponseType(405)]
|
|
[ProducesResponseType(422)]
|
|
public async Task<IActionResult> Operate(
|
|
[FromMember] string operation,
|
|
[FromMember] Stock stock,
|
|
[FromMember] bool? full,
|
|
[FromMember] int? destination,
|
|
[FromMiddleware] int session)
|
|
{
|
|
stock.Operator = session;
|
|
|
|
var user = await _identityQueryService.GetUser(session);
|
|
try
|
|
{
|
|
JObject jObj = JObject.Parse(stock.Tag);
|
|
JToken jPostUser = jObj.SelectToken("postUser");
|
|
if (jPostUser == null)
|
|
{
|
|
jObj.Add("postUser", user.Name);
|
|
}
|
|
else
|
|
{
|
|
jObj["postUser"] = user.Name;
|
|
}
|
|
|
|
stock.Tag = JsonConvert.SerializeObject(jObj);
|
|
}
|
|
catch { }
|
|
|
|
Failure failure;
|
|
(string Device, Failure Failure) commandResult;
|
|
commandResult.Device = "";
|
|
switch (operation)
|
|
{
|
|
case "palletIn":
|
|
failure = await _stockCommandService.PalletIn(stock, full, destination);
|
|
break;
|
|
case "scanInbound":
|
|
commandResult = await _stockCommandService.ScanInbound(stock, full, destination);
|
|
failure = commandResult.Failure;
|
|
break;
|
|
case "inbound":
|
|
failure = await _stockCommandService.Inbound(stock, full, destination);
|
|
break;
|
|
case "outbound":
|
|
failure = await _stockCommandService.Outbound(stock);
|
|
break;
|
|
case "update":
|
|
failure = await _stockCommandService.Update(stock);
|
|
break;
|
|
case "combine":
|
|
failure = await _stockCommandService.Combine(stock, full, destination);
|
|
break;
|
|
case "inventory":
|
|
failure = await _stockCommandService.Inventory(stock);
|
|
break;
|
|
case "applyin":
|
|
|
|
//var user = await _identityQueryService.GetUser(session);
|
|
foreach (var r in stock.Lines)
|
|
{
|
|
r.Postuser = user.Name;
|
|
}
|
|
|
|
|
|
commandResult = await _stockCommandService.ApplyIn(stock, full, destination);
|
|
failure = commandResult.Failure;
|
|
break;
|
|
default:
|
|
return StatusCode(405);
|
|
}
|
|
if (failure == null)
|
|
{
|
|
return StatusCode(201, commandResult.Device);
|
|
}
|
|
else
|
|
{
|
|
return StatusCode(422, failure);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 获取安全库存列表
|
|
/// </summary>
|
|
/// <response code="200">成功</response>
|
|
[HttpGet("safeties")]
|
|
[ProducesResponseType(200)]
|
|
public async Task<IActionResult> GetSafetyList(
|
|
[FromQuery] string type,
|
|
[FromQuery] int[] warehouse,
|
|
[FromQuery] int[] category,
|
|
[FromQuery] string code,
|
|
[FromQuery] string name,
|
|
[FromQuery] string sort,
|
|
[FromQuery] int? offset,
|
|
[FromQuery] int? limit)
|
|
{
|
|
if (warehouse.Length == 0)
|
|
{
|
|
warehouse = null;
|
|
}
|
|
if (category.Length == 0)
|
|
{
|
|
category = null;
|
|
}
|
|
var items = await _stockQueryService.GetSafetyList(type, warehouse, category, code, name, sort, offset, limit);
|
|
if (offset.HasValue || limit.HasValue)
|
|
{
|
|
var total = await _stockQueryService.GetSafetyCount(type, warehouse, category, code, name);
|
|
return StatusCode(200, new { items, total });
|
|
}
|
|
else
|
|
{
|
|
return StatusCode(200, new { items, total = items.Count() });
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 导出安全库存列表
|
|
/// </summary>
|
|
/// <response code="200">成功</response>
|
|
[HttpGet("safeties/excel")]
|
|
[ProducesResponseType(200)]
|
|
public async Task<IActionResult> ExportSafety(
|
|
[FromQuery] string type,
|
|
[FromQuery] int[] warehouse,
|
|
[FromQuery] int[] category,
|
|
[FromQuery] string code,
|
|
[FromQuery] string name)
|
|
{
|
|
if (warehouse.Length == 0)
|
|
{
|
|
warehouse = null;
|
|
}
|
|
if (category.Length == 0)
|
|
{
|
|
category = null;
|
|
}
|
|
using var package = new ExcelPackage();
|
|
var worksheet = package.Workbook.Worksheets.Add("Sheet1");
|
|
var column = 0;
|
|
worksheet.Cells[1, ++column].Value = "物料号";
|
|
worksheet.Cells[1, ++column].Value = "物料名";
|
|
worksheet.Cells[1, ++column].Value = "规格型号";
|
|
worksheet.Cells[1, ++column].Value = "数量";
|
|
worksheet.Cells[1, ++column].Value = "单位";
|
|
worksheet.Cells[1, ++column].Value = "安全库存";
|
|
var warehouseName = (await _warehouseQueryService.GetWarehouseList(null, null, null)).ToDictionary(w => w.Id.ToString(), w => w.Name);
|
|
var index = 1;
|
|
foreach (var item in await _stockQueryService.GetSafetyList(type, warehouse, category, code, name, null, null, null))
|
|
{
|
|
index++;
|
|
column = 0;
|
|
worksheet.Cells[index, ++column].Value = item.Code;
|
|
worksheet.Cells[index, ++column].Value = item.Name;
|
|
worksheet.Cells[index, ++column].Value = item.Model;
|
|
worksheet.Cells[index, ++column].Value = item.Quantity;
|
|
worksheet.Cells[index, ++column].Value = item.Unit;
|
|
worksheet.Cells[index, ++column].Value = $"{item.LowerLimit} ~ {item.UpperLimit} ( {string.Join(" + ", item.Warehouse.Split(',').Select(i => warehouseName.ContainsKey(i) ? warehouseName[i] : "?"))} )";
|
|
}
|
|
return File(package.GetAsByteArray(), "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
|
|
}
|
|
|
|
///////////////////////////////////////////////////////
|
|
/// <summary>
|
|
/// 获取批次码列表
|
|
/// </summary>
|
|
/// <response code="200">成功</response>
|
|
[HttpGet("batch")]
|
|
[ProducesResponseType(200)]
|
|
public async Task<IActionResult> GetBatchList([FromQuery] int? material)
|
|
{
|
|
var items = await _stockQueryService.GetBatchList(material);
|
|
return StatusCode(200, new
|
|
{
|
|
items
|
|
});
|
|
}
|
|
|
|
/// <summary>
|
|
/// 冻结
|
|
/// </summary>
|
|
/// <response code="201">成功</response>
|
|
/// <response code="405">非法操作</response>
|
|
/// <response code="422">请求内容错误</response>
|
|
[HttpPost("setQcStatus")]
|
|
[ProducesResponseType(201)]
|
|
[ProducesResponseType(405)]
|
|
[ProducesResponseType(422)]
|
|
public async Task<IActionResult> SetQcStatus(
|
|
[FromMember] string operation,
|
|
[FromMember] int? code,
|
|
[FromMember] string batch,
|
|
[FromMember] DateTime? mfgFrom,
|
|
[FromMember] DateTime? mfgTo,
|
|
[FromMember] DateTime? inboundTimeFrom,
|
|
[FromMember] DateTime? inboundTimeTo,
|
|
[FromMember] string barcode,
|
|
[FromMember] string supplier,
|
|
[FromMember] string[] barcodes,
|
|
[FromMiddleware] int session)
|
|
{
|
|
Failure failure;
|
|
(int barcodeCount, Failure Failure) commandResult;
|
|
commandResult.barcodeCount = 0;
|
|
|
|
commandResult = await _stockCommandService.SetQcStatus(session, operation, code, batch, mfgFrom, mfgTo, inboundTimeFrom, inboundTimeTo, barcode, supplier, barcodes);
|
|
failure = commandResult.Failure;
|
|
|
|
if (failure == null)
|
|
{
|
|
return StatusCode(201, commandResult.barcodeCount);
|
|
}
|
|
else
|
|
{
|
|
return StatusCode(422, failure);
|
|
}
|
|
}
|
|
}
|
|
}
|