This commit is contained in:
2021-08-25 19:20:25 +00:00
parent 1b8929908d
commit 95c41a297e
10 changed files with 252 additions and 48 deletions

View File

@@ -156,7 +156,7 @@ namespace AyaNova.Api.Controllers
/// <param name="vendorId">optional vendor id will return matches to Part objects manufacturer, wholesaler or alternative wholesaler</param>
/// <returns>PurchaseOrder</returns>
[HttpGet("restock-by-vendor/{vendorId}")]
public async Task<IActionResult> GetPurchaseOrder([FromRoute] long? vendorId)
public async Task<IActionResult> GetRestockByVendor([FromRoute] long? vendorId)
{
if (!serverState.IsOpen)
return StatusCode(503, new ApiErrorResponse(serverState.ApiErrorCode, null, serverState.Reason));

View File

@@ -9,38 +9,14 @@ namespace AyaNova.DataList
{
public PartInventoryDataList()
{
DefaultListAType = AyaType.PartInventory;
DefaultListAType = AyaType.PartInventoryDataList;
SQLFrom = "from vpartinventorylist ";
/*
"CREATE VIEW vpartinventorylist AS select apart.partnumber,apartwarehouse.name as whsname,vpartinventorynow.*,vpartsonorder.quantityonorder,"
+"vpartsonordercommitted.quantityonordercommitted,apart.name as prtname, apart.active, apart.cost, apartstocklevel.minimumquantity,apart.retail, aws.name AS whslrname, aaws.name AS altwhslrname, "
+"GREATEST( COALESCE(apartstocklevel.minimumquantity, 0) - (COALESCE(vpartinventorynow.balance, 0) + COALESCE(vpartsonorder.quantityonorder, 0) - "
+"COALESCE(vpartsonordercommitted.quantityonordercommitted, 0)) ,0) AS reorderquantity FROM vpartinventorynow LEFT JOIN vpartsonordercommitted ON "
+"vpartinventorynow.partid = vpartsonordercommitted.partid AND vpartinventorynow.partwarehouseid = vpartsonordercommitted.partwarehouseid "
+"LEFT JOIN vpartsonorder ON vpartinventorynow.partid = vpartsonorder.partid AND vpartinventorynow.partwarehouseid = vpartsonorder.partwarehouseid "
+"LEFT JOIN apart ON (vpartinventorynow.partid = apart.id) LEFT JOIN apartwarehouse ON (vpartinventorynow.partwarehouseid = apartwarehouse.id) "
+"left join avendor AS aws on (apart.wholesalerid = aws.id) left join avendor AS aaws on (apart.alternativewholesalerid = aaws.id) "
+"left join apartstocklevel on (apartstocklevel.partid = apart.id AND apartstocklevel.partwarehouseid = vpartinventorynow.partwarehouseid);"
await ExecQueryAsync("CREATE VIEW vpartinventorylist AS select vpartinventorynow.*, vpartsonordercommitted.quantityonordercommitted, vpartsonorder.quantityonorder from vpartinventorynow "
+ "left join vpartsonordercommitted on (vpartinventorynow.partid = vpartsonordercommitted.partid and vpartinventorynow.partwarehouseid = vpartsonordercommitted.partwarehouseid)"
+ "left join vpartsonorder on (vpartinventorynow.partid = vpartsonorder.partid and vpartinventorynow.partwarehouseid = vpartsonorder.partwarehouseid)");
*/
//NEEDED COLUMNS
/*
partid, partnumber, partname, partactive, partcost, partretail, partwarehouseid, partwarehousename,wholesalername,wholesalerid,altwholesalername,altwholesalerid,
onhandqty, onorderqty, onordercommittedqty, restocklevel/minimumqty, reorderqty, vpartinventorynow.description, vpartinventorynow.id
*/
var RoleSet = BizRoles.GetRoleSet(DefaultListAType);
AllowedRoles = RoleSet.ReadFullRecord | RoleSet.Change;
DefaultColumns = new List<string>() { "PartPartNumber", "PartWarehouseName", "PartInventoryBalance", "PartByWarehouseInventoryQuantityOnOrder", "PartByWarehouseInventoryQtyOnOrderCommitted" };
DefaultColumns = new List<string>() { "PartPartNumber", "PartWarehouseName", "PartInventoryBalance", "PartByWarehouseInventoryMinStockLevel","PartByWarehouseInventoryReorderQuantity","PartByWarehouseInventoryQuantityOnOrder", "PartByWarehouseInventoryQtyOnOrderCommitted", "Active" };
DefaultSortBy = new Dictionary<string, string>() { { "PartPartNumber", "+" }, { "PartWarehouseName", "+" } };
FieldDefinitions = new List<DataListFieldDefinition>();
@@ -50,8 +26,8 @@ onhandqty, onorderqty, onordercommittedqty, restocklevel/minimumqty, reorderqty,
FieldKey = "PartPartNumber",
AType = (int)AyaType.Part,
UiFieldDataType = (int)UiFieldDataType.Text,
SqlIdColumnName = "apart.id",
SqlValueColumnName = "apart.partnumber"
SqlIdColumnName = "partid",
SqlValueColumnName = "partnumber"
});
FieldDefinitions.Add(new DataListFieldDefinition
@@ -60,8 +36,52 @@ onhandqty, onorderqty, onordercommittedqty, restocklevel/minimumqty, reorderqty,
FieldKey = "PartName",
AType = (int)AyaType.Part,
UiFieldDataType = (int)UiFieldDataType.Text,
SqlIdColumnName = "apart.id",
SqlValueColumnName = "vpartinventorylist.vpartinventorylist"
SqlIdColumnName = "partid",
SqlValueColumnName = "partname"
});
FieldDefinitions.Add(new DataListFieldDefinition
{
TKey = "Active",
FieldKey = "Active",
UiFieldDataType = (int)UiFieldDataType.Bool,
SqlValueColumnName = "partactive"
});
FieldDefinitions.Add(new DataListFieldDefinition
{
TKey = "PartCost",
FieldKey = "PartCost",
UiFieldDataType = (int)UiFieldDataType.Currency,
SqlValueColumnName = "partcost"
});
FieldDefinitions.Add(new DataListFieldDefinition
{
TKey = "PartRetail",
FieldKey = "PartRetail",
UiFieldDataType = (int)UiFieldDataType.Currency,
SqlValueColumnName = "partretail"
});
FieldDefinitions.Add(new DataListFieldDefinition
{
FieldKey = "PartWholesalerID",
TKey = "PartWholesalerID",
UiFieldDataType = (int)UiFieldDataType.Text,
AType = (int)AyaType.Vendor,
SqlIdColumnName = "wholesalerid",
SqlValueColumnName = "wholesalername"
});
FieldDefinitions.Add(new DataListFieldDefinition
{
FieldKey = "PartAlternativeWholesalerID",
TKey = "PartAlternativeWholesalerID",
UiFieldDataType = (int)UiFieldDataType.Text,
AType = (int)AyaType.Vendor,
SqlIdColumnName = "altwholesalerid",
SqlValueColumnName = "altwholesalername"
});
FieldDefinitions.Add(new DataListFieldDefinition
@@ -70,8 +90,8 @@ onhandqty, onorderqty, onordercommittedqty, restocklevel/minimumqty, reorderqty,
FieldKey = "PartWarehouseName",
AType = (int)AyaType.PartWarehouse,
UiFieldDataType = (int)UiFieldDataType.Text,
SqlIdColumnName = "apartwarehouse.id",
SqlValueColumnName = "apartwarehouse.name"
SqlIdColumnName = "partwarehouseid",
SqlValueColumnName = "partwarehousename"
});
FieldDefinitions.Add(new DataListFieldDefinition
@@ -80,8 +100,8 @@ onhandqty, onorderqty, onordercommittedqty, restocklevel/minimumqty, reorderqty,
FieldKey = "PartInventoryTransactionDescription",
AType = (int)AyaType.PartInventory,
UiFieldDataType = (int)UiFieldDataType.Text,
SqlIdColumnName = "vpartinventorylist.id",//NEW: vpartinventorynow.id is actually apartinventory.id required for reporting purposes
SqlValueColumnName = "vpartinventorylist.description",//NEW: vpartinventorynow.description which is actually apartinventory.description
SqlIdColumnName = "partinventoryid",
SqlValueColumnName = "partinventorydescription",
IsMeta = true,//only so it doesn't show in the UI but is required for report
IsRowId = true
});
@@ -91,7 +111,7 @@ onhandqty, onorderqty, onordercommittedqty, restocklevel/minimumqty, reorderqty,
TKey = "PartInventoryBalance",
FieldKey = "PartInventoryBalance",
UiFieldDataType = (int)UiFieldDataType.Decimal,
SqlValueColumnName = "vpartinventorylist.balance"
SqlValueColumnName = "onhandqty"
});
@@ -100,7 +120,7 @@ onhandqty, onorderqty, onordercommittedqty, restocklevel/minimumqty, reorderqty,
TKey = "PartByWarehouseInventoryQuantityOnOrder",
FieldKey = "PartByWarehouseInventoryQuantityOnOrder",
UiFieldDataType = (int)UiFieldDataType.Decimal,
SqlValueColumnName = "vpartinventorylist.quantityonorder"
SqlValueColumnName = "onorderqty"
});
FieldDefinitions.Add(new DataListFieldDefinition
@@ -108,7 +128,25 @@ onhandqty, onorderqty, onordercommittedqty, restocklevel/minimumqty, reorderqty,
TKey = "PartByWarehouseInventoryQtyOnOrderCommitted",
FieldKey = "PartByWarehouseInventoryQtyOnOrderCommitted",
UiFieldDataType = (int)UiFieldDataType.Decimal,
SqlValueColumnName = "vpartinventorylist.quantityonordercommitted"
SqlValueColumnName = "onordercommittedqty"
});
FieldDefinitions.Add(new DataListFieldDefinition
{
TKey = "PartByWarehouseInventoryMinStockLevel",
FieldKey = "PartByWarehouseInventoryMinStockLevel",
UiFieldDataType = (int)UiFieldDataType.Decimal,
SqlValueColumnName = "restockminqty"
});
FieldDefinitions.Add(new DataListFieldDefinition
{
TKey = "PartByWarehouseInventoryReorderQuantity",
FieldKey = "PartByWarehouseInventoryReorderQuantity",
UiFieldDataType = (int)UiFieldDataType.Decimal,
SqlValueColumnName = "reorderqty"
});
@@ -118,8 +156,8 @@ onhandqty, onorderqty, onordercommittedqty, restocklevel/minimumqty, reorderqty,
FieldKey = "metapartnumber",
UiFieldDataType = (int)UiFieldDataType.Text,
SqlIdColumnName = "apart.id",
SqlValueColumnName = "apart.partnumber",
SqlIdColumnName = "partid",
SqlValueColumnName = "partnumber",
IsMeta = true
});
@@ -128,8 +166,8 @@ onhandqty, onorderqty, onordercommittedqty, restocklevel/minimumqty, reorderqty,
{
FieldKey = "metawarehouse",
UiFieldDataType = (int)UiFieldDataType.Text,
SqlIdColumnName = "apartwarehouse.id",
SqlValueColumnName = "apartwarehouse.name",
SqlIdColumnName = "partwarehouseid",
SqlValueColumnName = "partwarehousename",
IsMeta = true
});

View File

@@ -136,7 +136,7 @@ namespace AyaNova.Biz
PartInventory = 67,
DataListColumnView = 68,
PartInventoryRestock = 69,//for list only, synthetic object
PartInventoryRequest = 70,//for list only not, synthetic object
PartInventoryRequest = 70,//for list only, synthetic object
WorkOrderStatus = 71,
TaskGroup = 72,
WorkOrderItemOutsideService = 73,
@@ -166,7 +166,8 @@ namespace AyaNova.Biz
PMItemTravel = 87,
[CoreBizObject]
PMItemUnit = 88,
PMItemOutsideService = 89
PMItemOutsideService = 89,
PartInventoryDataList = 90//for list/reporting only, synthetic object

View File

@@ -61,6 +61,8 @@ namespace AyaNova.Biz
return new PartAssemblyBiz(ct, userId, translationId, roles);
case AyaType.PartInventory:
return new PartInventoryBiz(ct, userId, translationId, roles);
case AyaType.PartInventoryDataList:
return new PartInventoryDataListBiz(ct, userId, translationId, roles);
case AyaType.Project:

View File

@@ -241,6 +241,22 @@ namespace AyaNova.Biz
Select = AuthorizationRoles.All
});
/////////////////////////////////////////////////////////////////
//PartInventoryDataList
// same as PO
//
roles.Add(AyaType.PartInventoryDataList, new BizRoleSet()
{
Change = AuthorizationRoles.Inventory
| AuthorizationRoles.BizAdmin
| AuthorizationRoles.Accounting,
ReadFullRecord = AuthorizationRoles.Service
| AuthorizationRoles.InventoryRestricted
| AuthorizationRoles.BizAdminRestricted
| AuthorizationRoles.ServiceRestricted,
Select = AuthorizationRoles.All
});
////////////////////////////////////////////////////////////

View File

@@ -0,0 +1,106 @@
using System;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using System.Linq;
using AyaNova.Util;
using AyaNova.Api.ControllerHelpers;
using AyaNova.Models;
using Newtonsoft.Json.Linq;
using System.Collections.Generic;
namespace AyaNova.Biz
{
internal class PartInventoryDataListBiz : BizObject, IReportAbleObject, IExportAbleObject
{
internal PartInventoryDataListBiz(AyContext dbcontext, long currentUserId, long userTranslationId, AuthorizationRoles UserRoles)
{
ct = dbcontext;
UserId = currentUserId;
UserTranslationId = userTranslationId;
CurrentUserRoles = UserRoles;
BizType = AyaType.PartInventoryDataList;
}
internal static PartInventoryDataListBiz GetBiz(AyContext ct, Microsoft.AspNetCore.Http.HttpContext httpContext = null)
{
if (httpContext != null)
return new PartInventoryDataListBiz(ct, UserIdFromContext.Id(httpContext.Items), UserTranslationIdFromContext.Id(httpContext.Items), UserRolesFromContext.Roles(httpContext.Items));
else
return new PartInventoryDataListBiz(ct, 1, ServerBootConfig.AYANOVA_DEFAULT_TRANSLATION_ID, AuthorizationRoles.BizAdmin);
}
////////////////////////////////////////////////////////////////////////////////////////////////
//REPORTING
//
public async Task<JArray> GetReportData(DataListSelectedRequest dataListSelectedRequest)
{
var idList = dataListSelectedRequest.SelectedRowIds;
JArray ReportData = new JArray();
while (idList.Any())
{
var batch = idList.Take(IReportAbleObject.REPORT_DATA_BATCH_SIZE);
idList = idList.Skip(IReportAbleObject.REPORT_DATA_BATCH_SIZE).ToArray();
//query for this batch, comes back in db natural order unfortunately
var batchResults = await ct.VPartInventoryList.AsNoTracking().Where(z => batch.Contains(z.Id)).ToArrayAsync();
//order the results back into original
var orderedList = from id in batch join z in batchResults on id equals z.Id select z;
//cache frequent viz data
var AyaTypesEnumList = await AyaNova.Api.Controllers.EnumListController.GetEnumList(
StringUtil.TrimTypeName(typeof(AyaType).ToString()),
UserTranslationId,
CurrentUserRoles);
using (var command = ct.Database.GetDbConnection().CreateCommand())
{
ct.Database.OpenConnection();
foreach (PartInventory w in orderedList)
{
await PopulateVizFields(w, AyaTypesEnumList, command);
var jo = JObject.FromObject(w);
if (!JsonUtil.JTokenIsNullOrEmpty(jo["CustomFields"]))
jo["CustomFields"] = JObject.Parse((string)jo["CustomFields"]);
ReportData.Add(jo);
}
}
}
return ReportData;
}
//populate viz fields from provided object
private async Task PopulateVizFields(PartInventory o, List<NameIdItem> ayaTypesEnumList, System.Data.Common.DbCommand cmd)
{
o.PartViz = await ct.Part.AsNoTracking().Where(x => x.Id == o.PartId).Select(x => x.PartNumber).FirstOrDefaultAsync();
o.PartWarehouseViz = await ct.PartWarehouse.AsNoTracking().Where(x => x.Id == o.PartWarehouseId).Select(x => x.Name).FirstOrDefaultAsync();
if (o.SourceType != null)
o.SourceTypeViz = ayaTypesEnumList.Where(x => x.Id == (long)o.SourceType).Select(x => x.Name).First();
if (o.SourceType != null && o.SourceId != null)
o.SourceViz = BizObjectNameFetcherDirect.Name((AyaType)o.SourceType, (long)o.SourceId, cmd);
}
////////////////////////////////////////////////////////////////////////////////////////////////
// IMPORT EXPORT
//
public async Task<JArray> GetExportData(DataListSelectedRequest dataListSelectedRequest)
{
//for now just re-use the report data code
//this may turn out to be the pattern for most biz object types but keeping it seperate allows for custom usage from time to time
return await GetReportData(dataListSelectedRequest);
}
/////////////////////////////////////////////////////////////////////
}//eoc
}//eons

View File

@@ -122,6 +122,7 @@ namespace AyaNova.Models
// public virtual DbSet<ServiceBank> ServiceBank { get; set; }
public virtual DbSet<ViewRestockRequired> ViewRestockRequired { get; set; }
public virtual DbSet<VPartInventoryList> VPartInventoryList { get; set; }

View File

@@ -0,0 +1,40 @@
namespace AyaNova.Models
{
//Note this is how to define a View backed model with no key (id)
[Microsoft.EntityFrameworkCore.Keyless]
public class VPartInventoryList
{
public long PartId { get; set; }
public string PartNumber { get; set; }
public string PartName { get; set; }
public bool PartActive { get; set; }
public decimal PartCost { get; set; }
public decimal PartRetail { get; set; }
public long PartWarehouseId { get; set; }
public string PartWarehouseName { get; set; }
public long WholesalerId { get; set; }
public string WholesalerName { get; set; }
public long AltWholesalerId { get; set; }
public string AltWholesalerName { get; set; }
public decimal OnHandQty { get; set; }
public decimal OnOrderQty { get; set; }
public decimal OnOrderCommittedQty { get; set; }
public decimal RestockMinQty { get; set; }
public decimal ReOrderQty { get; set; }
public long PartInventoryId { get; set; }
public string PartInventoryDescription { get; set; }
}//eoc
}//eons
/*
vpartinventorylist AS select apart.id as partid, apart.partnumber, apart.name as partname, apart.active as partactive, apart.cost as partcost, apart.retail as partretail,"
+"apartwarehouse.id as partwarehouseid, apartwarehouse.name as partwarehousename, awholesaler.name as wholesalername, awholesaler.id as wholesalerid, "
+"aaltwholesaler.id as altwholesalerid, aaltwholesaler.name as altwholesalername, vpartinventorynow.balance as onhandqty,vpartsonorder.quantityonorder as onorderqty, "
+"vpartsonordercommitted.quantityonordercommitted as onordercommittedqty,apartstocklevel.minimumquantity as restockminqty, "
+"GREATEST( COALESCE(apartstocklevel.minimumquantity, 0) - (COALESCE(vpartinventorynow.balance, 0) + COALESCE(vpartsonorder.quantityonorder, 0) - COALESCE(vpartsonordercommitted.quantityonordercommitted, 0)) ,0) AS reorderqty,"
+"vpartinventorynow.id as partinventoryid, vpartinventorynow.description as partinventorydescription "
*/

View File

@@ -904,8 +904,8 @@ $BODY$ LANGUAGE PLPGSQL STABLE");
await ExecQueryAsync(
"CREATE VIEW vpartinventorylist AS select apart.id as partid, apart.partnumber, apart.name as partname, apart.active as partactive, apart.cost as partcost, apart.retail as partretail,"
+"apartwarehouse.id as partwarehouseid, apartwarehouse.name as partwarehousename, awholesaler.name as wholesalername, awholesaler.id as wholesalerid, "
+"aaltwholesaler.id as altwholesalerid, aaltwholesaler.name as altwholesalername, vpartinventorynow.balance as onhandqty,vpartsonorder.quantityonorder as onorderqty, "
+"vpartsonordercommitted.quantityonordercommitted as onordercommittedqty,apartstocklevel.minimumquantity as restockminqty, "
+"aaltwholesaler.id as altwholesalerid, aaltwholesaler.name as altwholesalername, vpartinventorynow.balance as onhandqty,COALESCE(vpartsonorder.quantityonorder,0) as onorderqty, "
+"COALESCE(vpartsonordercommitted.quantityonordercommitted,0) as onordercommittedqty,COALESCE(apartstocklevel.minimumquantity,0) as restockminqty, "
+"GREATEST( COALESCE(apartstocklevel.minimumquantity, 0) - (COALESCE(vpartinventorynow.balance, 0) + COALESCE(vpartsonorder.quantityonorder, 0) - COALESCE(vpartsonordercommitted.quantityonordercommitted, 0)) ,0) AS reorderqty,"
+"vpartinventorynow.id as partinventoryid, vpartinventorynow.description as partinventorydescription "
+"FROM vpartinventorynow LEFT JOIN vpartsonordercommitted ON "