Commodities

This commit is contained in:
Andy Howard
2024-12-07 18:09:06 +00:00
parent 30d0352f48
commit d015470f58
39 changed files with 1588 additions and 602 deletions
@@ -520,7 +520,7 @@
<value>Cost price</value>
</data>
<data name="label.retail.price" xml:space="preserve">
<value>Retail price</value>
<value>RRP</value>
</data>
<data name="label.tax.code" xml:space="preserve">
<value>Tax code</value>
@@ -621,4 +621,61 @@
<data name="caption.contact.select" xml:space="preserve">
<value>Select Contact</value>
</data>
<data name="label.dimensions" xml:space="preserve">
<value>Dimensions</value>
</data>
<data name="label.catalog.ref" xml:space="preserve">
<value>Catalog ref</value>
</data>
<data name="label.icn.tariff.code" xml:space="preserve">
<value>ICN tariff code</value>
</data>
<data name="label.place.of.origin" xml:space="preserve">
<value>Place of origin</value>
</data>
<data name="label.material.currency" xml:space="preserve">
<value>Material currency</value>
</data>
<data name="label.material.cost" xml:space="preserve">
<value>Material cost</value>
</data>
<data name="label.ex.works.currency" xml:space="preserve">
<value>Ex-works currency</value>
</data>
<data name="label.ex.works.cost" xml:space="preserve">
<value>Ex-works cost</value>
</data>
<data name="label.specification" xml:space="preserve">
<value>Specification</value>
</data>
<data name="label.material" xml:space="preserve">
<value>Material</value>
</data>
<data name="label.finish" xml:space="preserve">
<value>Finish</value>
</data>
<data name="label.retail.price.planned" xml:space="preserve">
<value>Planned RRP</value>
</data>
<data name="label.carriage.cost.indicative" xml:space="preserve">
<value>Indicative carriage cost</value>
</data>
<data name="label.units" xml:space="preserve">
<value>Units</value>
</data>
<data name="label.weight" xml:space="preserve">
<value>Weight</value>
</data>
<data name="label.length" xml:space="preserve">
<value>Length</value>
</data>
<data name="label.volume" xml:space="preserve">
<value>Volume</value>
</data>
<data name="label.density" xml:space="preserve">
<value>Density</value>
</data>
<data name="label.box.quantity" xml:space="preserve">
<value>Box quantity</value>
</data>
</root>
@@ -1,27 +1,17 @@
using Microsoft.AspNetCore.Mvc;
using Sarand.BusinessMgr.Net.Core.Web.App;
using Sarand.BusinessMgr.Net.Core.Web.Helpers;
using Sarand.BusinessMgr.Web.Portal.Models;
using Sarand.BusinessMgr.Net.Standard.Base.App;
using Sarand.BusinessMgr.Net.Standard.Base.Bus;
using Sarand.BusinessMgr.Net.Standard.Base.Consoles;
using Sarand.BusinessMgr.Net.Standard.Base.Helpers;
using Sarand.BusinessMgr.Net.Standard.Base.Mgr;
using Sarand.BusinessMgr.Web.Portal.Models;
using Sarand.BusinessMgr.Web.Portal.Models.Commodities;
using Sarand.BusinessMgr.Web.Portal.Models.Contacts;
using Sarand.Net.Standard.Base.App;
using Sarand.Net.Standard.Base.Bus;
using Sarand.Net.Standard.Base.Core;
using Sarand.Net.Standard.Base.Dbas;
using Sarand.Net.Standard.Base.Email;
using Sarand.Net.Standard.Base.Helpers;
using Sarand.Net.Standard.Base.Security;
using Sarand.Net.Standard.Base.Utils;
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Linq;
using System.Threading.Tasks;
using System.Web;
using Sarand.BusinessMgr.Web.Portal.Models.Commodities;
using static Sarand.BusinessMgr.Net.Standard.Base.App.Sbm;
namespace Sarand.BusinessMgr.Web.Portal.Controllers.Commodities
@@ -32,16 +22,19 @@ namespace Sarand.BusinessMgr.Web.Portal.Controllers.Commodities
partial class CommodityController
{
//-------------------------------------------------------------------
// Commodity data.
// Item data.
private class CommodityListData : AjaxResponse_Data.ItemData_Base
{
public String TypeCode { get; set; }
public String TypeDesc { get; set; }
// Item properties with specific handling.
public String Code { get; set; }
public String Desc { get; set; }
public String SalesPriceFmt { get; set; }
public String SalesUnit { get; set; }
public String CostPriceFmt { get; set; }
public String Caption { get; set; }
// Fields.
public class FieldData
{
// Item property values keyed to match field name.
public Dictionary<string, string> Value { get; } = new Dictionary<string, string>();
}
public FieldData Field { get; } = new FieldData();
}
private enum CommodityDataGroup
{
@@ -49,48 +42,43 @@ namespace Sarand.BusinessMgr.Web.Portal.Controllers.Commodities
}
private class CommodityItemData : CommodityListData
{
// Commodity properties.
public String DrawingIssue { get; set; }
public String AssocIdCustomer { get; set; }
public String AssocIdSupplier { get; set; }
// Sales.
public String SalesPrice { get; set; }
// Purchasing.
public String CostPrice { get; set; }
// Specification.
// Production.
// Affiliate properties with specific handling.
public String TypeCode { get; set; }
public String TypeDesc { get; set; }
}
private void PopulateCommodityResponseListData(SbmCommodity commodity, CommodityListData data)
{
data.Id = SysId.ToString(commodity.Id);
data.TypeCode = Internals.CommodityTypeCodes.GetCodeForType(commodity.CommodityType);
data.TypeDesc = Internals.CommodityTypeCodes.GetDescForType(commodity.CommodityType);
data.Code = commodity.Code;
data.Desc = commodity.DescBrief;
data.SalesPriceFmt = StringUtil.NullOnBlank(StringUtil.FormatNumeric(commodity.SalesPrice, SbmInternals.CurrencyDecimalsDefault, 0, ','));
data.SalesUnit = StringUtil.NullOnBlank(Internals.GetUnitOfMeasureCaption(commodity.UomIdSale));
data.CostPriceFmt = StringUtil.NullOnBlank(StringUtil.FormatNumeric(commodity.CostPrice, SbmInternals.CurrencyDecimalsDefault, 0, ','));
// Common properties.
data.Notes = commodity.Notes;
data.StatusCode = commodity.StatusCode;
data.StatusDesc = commodity.StatusDesc;
}
private void PopulateCommodityResponseItemData(SbmCommodity commodity, CommodityItemData data, HashSet<CommodityDataGroup> dataGroups = null)
{
PopulateCommodityResponseListData(commodity, data as CommodityListData);
// Prominent properties for selecting and editing.
data.Code = commodity.Code;
data.Caption = commodity.DescBrief;
// Affiliate type - populate for list ('Type' property populated with desc) and form (Type Code & Desc).
data.TypeCode = Internals.CommodityTypeCodes.GetCodeForType(commodity.CommodityType);
data.TypeDesc = Internals.CommodityTypeCodes.GetDescForType(commodity.CommodityType);
data.Field.Value.Add($"{Model_Commodity.ItemField.Type}", Internals.CommodityTypeCodes.GetDescForType(commodity.CommodityType));
// Commodity properties.
data.DrawingIssue = StringUtil.NullOnBlank(commodity.DrawingIssue);
data.AssocIdCustomer = StringUtil.NullOnBlank(SysId.ToString(commodity.AssociationIdCustomer));
data.AssocIdSupplier = StringUtil.NullOnBlank(SysId.ToString(commodity.AssociationIdSupplier));
data.Field.Value.Add($"{Model_Commodity.ItemField.Code}", commodity.Code);
data.Field.Value.Add($"{Model_Commodity.ItemField.DescBrief}", commodity.DescBrief);
data.Field.Value.Add($"{Model_Commodity.ItemField.DrawingIssue}", commodity.DrawingIssue);
data.Field.Value.Add($"{Model_Commodity.ItemField.SalesPriceFmt}", StringUtil.NullOnBlank(StringUtil.FormatNumeric(commodity.SalesPrice, SbmInternals.CurrencyDecimalsDefault, 0, ',')));
data.Field.Value.Add($"{Model_Commodity.ItemField.SalesUnit}", StringUtil.NullOnBlank(Internals.GetUnitOfMeasureCaption(commodity.UomIdSale)));
data.Field.Value.Add($"{Model_Commodity.ItemField.CostPriceFmt}", StringUtil.NullOnBlank(StringUtil.FormatNumeric(commodity.CostPrice, SbmInternals.CurrencyDecimalsDefault, 0, ',')));
data.Field.Value.Add($"{Model_Commodity.ItemField.AssocIdCustomer}", StringUtil.NullOnBlank(SysId.ToString(commodity.AssociationIdCustomer)));
data.Field.Value.Add($"{Model_Commodity.ItemField.AssocIdSupplier}", StringUtil.NullOnBlank(SysId.ToString(commodity.AssociationIdSupplier)));
if (dataGroups != null && dataGroups.Contains(CommodityDataGroup.Sales))
{
// Sales.
data.SalesPrice = StringUtil.NullOnBlank(StringUtil.FormatNumeric(commodity.SalesPrice, SbmInternals.CurrencyDecimalsDefault));
data.Field.Value.Add($"{Model_Commodity.ItemField.SalesPrice}", StringUtil.NullOnBlank(StringUtil.FormatNumeric(commodity.SalesPrice, SbmInternals.CurrencyDecimalsDefault)));
data.Field.Value.Add($"{Model_Commodity.ItemField.UomIdSale}", StringUtil.NullOnBlank(SysId.ToString(commodity.UomIdSale)));
}
if (dataGroups != null && dataGroups.Contains(CommodityDataGroup.Purchasing))
{
// Purchasing.
data.CostPrice = StringUtil.NullOnBlank(StringUtil.FormatNumeric(commodity.CostPrice, SbmInternals.CurrencyDecimalsDefault));
data.Field.Value.Add($"{Model_Commodity.ItemField.CostPrice}", StringUtil.NullOnBlank(StringUtil.FormatNumeric(commodity.CostPrice, SbmInternals.CurrencyDecimalsDefault)));
}
if (dataGroups != null && dataGroups.Contains(CommodityDataGroup.Specification))
{
@@ -100,74 +88,87 @@ namespace Sarand.BusinessMgr.Web.Portal.Controllers.Commodities
{
// Production.
}
// Common properties.
data.StatusCode = commodity.StatusCode;
data.StatusDesc = commodity.StatusDesc;
data.Field.Value.Add($"{Model_Contact.ItemField.Status}", commodity.StatusDesc);
// Cleanse field values.
data.Field.Value.RemoveAll(item => StringUtil.IsBlank(item.Value));
// Populate item list values that might be cleared during update after removing blank values to ensure that blank values are published.
data.Field.Value.Add($"{Model_Commodity.ItemField.Notes}", commodity.Notes);
data.Field.Value.Add($"{Model_Commodity.ItemField.UpdatedOn}", Localiser.FormatDate(commodity.UpdateStamp.On));
}
//-------------------------------------------------------------------
// Commodity configuration.
//-------------------------------------------------------------------
private class AjaxResponse_CommodityConfig : AjaxResponse_Data
{
// Construction.
public AjaxResponse_CommodityConfig(SbmModel_Portal model) : base(model) { }
// Configuration.
public Model_Commodity.ListConfigData Config { get; } = new Model_Commodity.ListConfigData();
public Model_Commodity.ItemConfigData ConfigCmd { get; } = new Model_Commodity.ItemConfigData();
// Reference data.
public List<CodeDesc> CommodityTypes { get; } = new List<CodeDesc>();
public List<CodeDesc> Statuses { get; } = new List<CodeDesc>();
public String DefaultStatusCode { get; set; }
}
// Ajax request.
[HttpPost]
[Route("Commodity/Ajax/Config")]
[Route("Commodity/Ajax/GetConfig")]
public IActionResult Ajax_CommodityConfig(Model_Commodity model)
{
AjaxResponse_CommodityConfig responseData = new AjaxResponse_CommodityConfig(model);
String messageTitle = Localiser["caption.commodities"];
// Validate session and referrer.
if (!ValidUserSession) return GetAjaxResult_InvalidSession(responseData);
if (!ValidReferer) return Forbid();
RefreshModel(model);
// Populate configuration data.
PopulateCommodityConfig(model, responseData);
// Complete response.
responseData.Success = true;
return Json(responseData);
}
private void PopulateCommodityConfig(Model_Commodity model, AjaxResponse_CommodityConfig responseData)
{
// Configuration.
model.PopulateListConfig(responseData.Config);
model.PopulateItemConfig(responseData.ConfigCmd, null, Sbm.CommodityType.Unknown);
// Reference data - commodity types.
foreach (TypeCodeDesc commodityType in GetCodesOfType(Sbm.SystemCode.CommodityType))
responseData.CommodityTypes.Add(commodityType.Code, commodityType.Desc);
// Reference data - statuses.
foreach (SaStatus status in SbmCommodity.ValidStatuses.FindAll(item => item != SaStatus.Deleted))
responseData.Statuses.Add(SacsSystem.GetStatusCode(status), Localiser.GetStatusCaption(status));
responseData.DefaultStatusCode = SacsSystem.GetStatusCode(SbmCommodity.DefaultStatus);
}
//-------------------------------------------------------------------
// Commodity list.
//-------------------------------------------------------------------
private class AjaxResponse_CommodityList : AjaxResponse_Data
private class AjaxResponse_CommodityList : AjaxResponse_CommodityConfig
{
// Construction.
public AjaxResponse_CommodityList(SbmModel_Portal model) : base(model) { }
// View mode.
public class ModeData
{
public bool? Search { get; set; }
public bool? Maintain { get; set; }
public bool? StockControl { get; set; }
public bool? StockTake { get; set; }
}
public ModeData Mode { get; set; }
// Commodity list.
public List<CommodityListData> Commodities { get; } = new List<CommodityListData>();
// Commodity configuration.
public class ConfigData
{
// Optional columns to show.
public class ShowColumnData
{
public bool? CatalogRef { get; set; }
public bool? Weight { get; set; }
public bool? PackQtySale { get; set; }
public bool? StockAllocated { get; set; }
public bool? StockLevelSales { get; set; }
public bool? StockAvailable { get; set; }
}
public ShowColumnData ShowColumn { get; } = new ShowColumnData();
// Optional fields to show.
public class ShowFieldData
{
public bool? DrawingIssue { get; set; }
public bool? DrawingNo { get; set; }
public bool? Department { get; set; }
public bool? CatalogRef { get; set; }
public bool? Volume { get; set; }
public bool? Density { get; set; }
public bool? BoxQuantity { get; set; }
public bool? ICNTariffCode { get; set; }
public bool? PlaceOfOrigin { get; set; }
public bool? MaterialCost { get; set; }
public bool? ExWorksCost { get; set; }
public bool? RetailPricePlanned { get; set; }
public bool? CarriageCostIndicative { get; set; }
}
public ShowFieldData ShowField { get; } = new ShowFieldData();
// Configurable field label.
public class FieldLabelData
{
public String CatalogRef { get; set; }
public String Dimensions { get; set; }
public String ICNTariffCode { get; set; }
public String CostPrice { get; set; }
public String PlaceOfOrigin { get; set; }
public String MaterialCost { get; set; }
public String CurrencyIdMaterial { get; set; }
public String ExWorksCost { get; set; }
public String CurrencyIdExWorks { get; set; }
public String SpecSummary { get; set; }
public String MaterialCode { get; set; }
public String FinishCode { get; set; }
public String DescDetail { get; set; }
public String RetailPricePlanned { get; set; }
}
public FieldLabelData FieldLabel { get; } = new FieldLabelData();
}
public ConfigData Config { get; } = new ConfigData();
// Reference data.
public List<CodeDesc> CommodityTypes { get; } = new List<CodeDesc>();
public List<CodeDesc> Statuses { get; } = new List<CodeDesc>();
public String DefaultStatusCode { get; set; }
}
// Ajax request.
[HttpPost]
@@ -183,17 +184,20 @@ namespace Sarand.BusinessMgr.Web.Portal.Controllers.Commodities
if (!ValidReferer) return Forbid();
RefreshModel(model);
// Configuration.
PopulateConfigShow(responseData.Config.ShowField);
// Populate configuration data.
PopulateCommodityConfig(model, responseData);
// Reference data - commodity types.
foreach (TypeCodeDesc commodityType in GetCodesOfType(Sbm.SystemCode.CommodityType))
responseData.CommodityTypes.Add(commodityType.Code, commodityType.Desc);
// Reference data - statuses.
foreach (SaStatus status in SbmCommodity.ValidStatuses.FindAll(item => item != SaStatus.Deleted))
responseData.Statuses.Add(SacsSystem.GetStatusCode(status), Localiser.GetStatusCaption(status));
responseData.DefaultStatusCode = SacsSystem.GetStatusCode(SbmCommodity.DefaultStatus);
// View mode.
responseData.Mode = new AjaxResponse_CommodityList.ModeData();
Model_Commodity.CommodityViewMode viewMode = model.GetFilterMode();
if (viewMode == Model_Commodity.CommodityViewMode.Maintain)
responseData.Mode.Maintain = true;
else if (viewMode == Model_Commodity.CommodityViewMode.StockControl)
responseData.Mode.StockControl = true;
else if (viewMode == Model_Commodity.CommodityViewMode.StockTake)
responseData.Mode.StockTake = true;
else
responseData.Mode.Search = true;
// Item filter.
SbmCommodity.Params prmCommodity = new SbmCommodity.Params();
@@ -220,9 +224,12 @@ namespace Sarand.BusinessMgr.Web.Portal.Controllers.Commodities
List<ColumnDfn> columns = new List<ColumnDfn>()
{
colId, colCommodityType, colCode, colDescBrief,
colSalesPrice, colSalesUomId,colCostPrice,
colNotes, colStatus, colCreatedOn, colUpdatedOn
};
if (model.UserCanViewCommodityFinancials_Sales())
columns.AddRange(new[] { colSalesPrice, colSalesUomId });
if (model.UserCanViewCommodityFinancials_Supply())
columns.AddRange(new[] { colCostPrice });
// Query items.
using (DbResultSet resultSet = CommodityMgr.ExecuteCommodityQuery(columns, prmCommodity))
@@ -234,21 +241,26 @@ namespace Sarand.BusinessMgr.Web.Portal.Controllers.Commodities
CommodityListData commodityData = new CommodityListData()
{
Id = values.GetString(colId.DataName),
TypeCode = Internals.CommodityTypeCodes.GetCodeForType(commodityType),
TypeDesc = Internals.CommodityTypeCodes.GetDescForType(commodityType),
Code = values.GetString(colCode.DataName),
Desc = values.GetString(colDescBrief.DataName),
SalesPriceFmt = StringUtil.NullOnBlank(StringUtil.FormatNumeric(values.GetValue(colSalesPrice.DataName).ToDecimal(), SbmInternals.CurrencyDecimalsDefault, 0, ',')),
SalesUnit = Internals.GetUnitOfMeasureCaption(new SysId(values.GetLong(colSalesUomId.DataName))),
CostPriceFmt = StringUtil.NullOnBlank(StringUtil.FormatNumeric(values.GetValue(colCostPrice.DataName).ToDecimal(), SbmInternals.CurrencyDecimalsDefault, 0, ',')),
Notes = StringUtil.NullOnBlank(values.GetString(colNotes.DataName)),
Caption = values.GetString(colDescBrief.DataName),
StatusCode = values.GetString(colStatus.DataName),
StatusDesc = SacsSystem.GetStatusDescForCode(values.GetString(colStatus.DataName)),
CreatedOn = DateUtil.Format(values.GetDate(colCreatedOn.DataName), "yyyyMMdd"),
CreatedOnFmt = Localiser.FormatDate(values.GetDate(colCreatedOn.DataName)),
UpdatedOn = DateUtil.Format(values.GetDate(colUpdatedOn.DataName), "yyyyMMdd"),
UpdatedOnFmt = Localiser.FormatDate(values.GetDate(colUpdatedOn.DataName))
};
commodityData.Field.Value.Add($"{Model_Commodity.ItemField.Type}", Internals.CommodityTypeCodes.GetDescForType(commodityType));
commodityData.Field.Value.Add($"{Model_Commodity.ItemField.Code}", values.GetString(colCode.DataName));
commodityData.Field.Value.Add($"{Model_Commodity.ItemField.DescBrief}", values.GetString(colDescBrief.DataName));
if (model.UserCanViewCommodityFinancials_Sales())
{
commodityData.Field.Value.Add($"{Model_Commodity.ItemField.SalesPriceFmt}", StringUtil.FormatNumeric(values.GetValue(colSalesPrice.DataName).ToDecimal(), SbmInternals.CurrencyDecimalsDefault, 0, ','));
commodityData.Field.Value.Add($"{Model_Commodity.ItemField.SalesUnit}", Internals.GetUnitOfMeasureCaption(new SysId(values.GetLong(colSalesUomId.DataName))));
}
if (model.UserCanViewCommodityFinancials_Supply())
commodityData.Field.Value.Add($"{Model_Commodity.ItemField.CostPriceFmt}", StringUtil.FormatNumeric(values.GetValue(colCostPrice.DataName).ToDecimal(), SbmInternals.CurrencyDecimalsDefault, 0, ','));
commodityData.Field.Value.Add($"{Model_Commodity.ItemField.Notes}", CommodityMgr.GetCommodityDataValue(colNotes, values).ToString());
commodityData.Field.Value.Add($"{Model_Commodity.ItemField.Status}", SacsSystem.GetStatusDescForCode(values.GetString(colStatus.DataName)));
commodityData.Field.Value.Add($"{Model_Commodity.ItemField.CreatedOn}", Localiser.FormatDate(values.GetDate(colCreatedOn.DataName)));
commodityData.Field.Value.Add($"{Model_Commodity.ItemField.UpdatedOn}", Localiser.FormatDate(values.GetDate(colUpdatedOn.DataName)));
// Cleanse item values.
commodityData.Field.Value.RemoveAll(item => StringUtil.IsBlank(item.Value));
responseData.Commodities.Add(commodityData);
}
}
@@ -265,27 +277,6 @@ namespace Sarand.BusinessMgr.Web.Portal.Controllers.Commodities
return Json(responseData);
}
//-------------------------------------------------------------------
// Populate configuration.
private void PopulateConfigShow(AjaxResponse_CommodityList.ConfigData.ShowFieldData show)
{
// Ref. Sbm.OrgOption_ShowField.
if (UserContext_Core.GetOwnerOption_ShowField(SbmDbDfn.ColumnIdx.Commodity_DrawingIssue)) show.DrawingIssue = true;
if (UserContext_Core.GetOwnerOption_ShowField(SbmDbDfn.ColumnIdx.Commodity_DrawingNo)) show.DrawingNo = true;
if (UserContext_Core.GetOwnerOption_ShowField(SbmDbDfn.ColumnIdx.Commodity_Department)) show.Department = true;
if (UserContext_Core.GetOwnerOption_ShowField(SbmDbDfn.ColumnIdx.Commodity_CatalogRef)) show.CatalogRef = true;
if (UserContext_Core.GetOwnerOption_ShowField(SbmDbDfn.ColumnIdx.Commodity_Volume)) show.Volume = true;
if (UserContext_Core.GetOwnerOption_ShowField(SbmDbDfn.ColumnIdx.Commodity_Density)) show.Density = true;
if (UserContext_Core.GetOwnerOption_ShowField(SbmDbDfn.ColumnIdx.Commodity_BoxQuantity)) show.BoxQuantity = true;
if (UserContext_Core.GetOwnerOption_ShowField(SbmDbDfn.ColumnIdx.Commodity_ICNTariffCode)) show.ICNTariffCode = true;
if (UserContext_Core.GetOwnerOption_ShowField(SbmDbDfn.ColumnIdx.Commodity_PlaceOfOrigin)) show.PlaceOfOrigin = true;
if (UserContext_Core.GetOwnerOption_ShowField(SbmDbDfn.ColumnIdx.Commodity_MaterialCost)) show.MaterialCost = true;
if (UserContext_Core.GetOwnerOption_ShowField(SbmDbDfn.ColumnIdx.Commodity_ExWorksCost)) show.ExWorksCost = true;
if (UserContext_Core.GetOwnerOption_ShowField(SbmDbDfn.ColumnIdx.Commodity_RetailPricePlanned)) show.RetailPricePlanned = true;
if (UserContext_Core.GetOwnerOption_ShowField(SbmDbDfn.ColumnIdx.Commodity_CarriageCostIndicative)) show.CarriageCostIndicative = true;
}
//-------------------------------------------------------------------
// Get Commodity ajax request.
//-------------------------------------------------------------------
@@ -293,6 +284,8 @@ namespace Sarand.BusinessMgr.Web.Portal.Controllers.Commodities
{
// Construction.
public AjaxResponse_Commodity(SbmModel_Portal model) : base(model) { }
// Configuration.
public Model_Commodity.ItemConfigData Config { get; } = new Model_Commodity.ItemConfigData();
// Commodity details.
public CommodityItemData commodity { get; } = new CommodityItemData();
}
@@ -324,6 +317,7 @@ namespace Sarand.BusinessMgr.Web.Portal.Controllers.Commodities
}
// Construct response.
model.PopulateItemConfig(responseData.Config, commodity);
PopulateCommodityResponseItemData(commodity, responseData.commodity);
// Complete response.
@@ -418,6 +412,7 @@ namespace Sarand.BusinessMgr.Web.Portal.Controllers.Commodities
UpdateAssociatedData(commodity);
// Construct response.
model.PopulateItemConfig(responseData.Config, commodity);
PopulateCommodityResponseItemData(commodity, responseData.commodity);
// Complete response.
@@ -47,6 +47,7 @@ namespace Sarand.BusinessMgr.Web.Portal.Controllers.Commodities
// Commodity page.
RefreshModel(model);
model.PopulateListConfig();
model.Paging.PageNo = SessionData_Portal.Profile.Commodities.Filter.PageNo;
model.Paging.PageLength = SessionData_Portal.Profile.Commodities.Filter.PageLength;
return View(model);
@@ -171,8 +171,8 @@ namespace Sarand.BusinessMgr.Web.Portal.Controllers.Contacts
// View mode.
public class ModeData
{
public bool? Maintain { get; set; }
public bool? Search { get; set; }
public bool? Maintain { get; set; }
public bool? Relationships { get; set; }
public bool? PriceSet { get; set; }
}
@@ -199,21 +199,15 @@ namespace Sarand.BusinessMgr.Web.Portal.Controllers.Contacts
// View mode.
responseData.Mode = new AjaxResponse_AssociationList.ModeData();
switch (model.GetFilterMode())
{
case Model_Association.AssociationViewMode.Search:
responseData.Mode.Search = true;
break;
case Model_Association.AssociationViewMode.Relationships:
responseData.Mode.Relationships = true;
break;
case Model_Association.AssociationViewMode.PriceSet:
responseData.Mode.PriceSet = true;
break;
default:
responseData.Mode.Maintain = true;
break;
}
Model_Association.AssociationViewMode viewMode = model.GetFilterMode();
if (viewMode == Model_Association.AssociationViewMode.Maintain)
responseData.Mode.Maintain = true;
else if (viewMode == Model_Association.AssociationViewMode.Relationships)
responseData.Mode.Relationships = true;
else if (viewMode == Model_Association.AssociationViewMode.PriceSet)
responseData.Mode.PriceSet = true;
else
responseData.Mode.Search = true;
// Item filter.
SbmAssociation.Params prmAssociation = new SbmAssociation.Params();
@@ -24,10 +24,10 @@ namespace Sarand.BusinessMgr.Web.Portal.Controllers.Contacts
partial class ContactController
{
//-------------------------------------------------------------------
// Affiliate data.
// Item data.
private class AffiliateListData : AjaxResponse_Data.ItemData_Base
{
// Affiliate properties with specific handling.
// Item properties with specific handling.
public String Name { get; set; }
// Affiliate properties for list with specific handling.
public long? AssociationCount { get; set; }
@@ -52,7 +52,7 @@ namespace Sarand.BusinessMgr.Web.Portal.Controllers.Contacts
private void PopulateAffiliateResponseItemData(Model_Contact model, SbmAffiliate affiliate, AffiliateItemData data)
{
PopulateAffiliateResponseListData(model, affiliate, data as AffiliateListData);
// Affiliate name - prominent property for selecting and editing.
// Name - prominent property for selecting and editing.
data.Name = affiliate.Name;
// Affiliate type - populate for list ('Type' property populated with desc) and form (Type Code & Desc).
data.TypeCode = Internals.AffiliateTypeCodes.GetCodeForType(affiliate.AffiliateType);
@@ -206,10 +206,10 @@ namespace Sarand.BusinessMgr.Web.Portal.Controllers.Contacts
// View mode.
responseData.Mode = new AjaxResponse_ContactList.ModeData();
Model_Contact.ContactViewMode viewMode = model.GetFilterMode();
if (viewMode == Model_Contact.ContactViewMode.Search)
responseData.Mode.Search = true;
else
if (viewMode == Model_Contact.ContactViewMode.Maintain)
responseData.Mode.Maintain = true;
else
responseData.Mode.Search = true;
// Item filter.
SbmAffiliate.Params prmAffiliate = new SbmAffiliate.Params();
@@ -80,7 +80,7 @@ namespace Sarand.BusinessMgr.Web.Portal.Controllers
/// <para>- Open user session - store details against Sesion Data.</para>
/// <para>- Set 'Keep logged in' cookie if required.</para>
/// </summary>
protected bool SignUserIn(ISbmUserContext_Core userContext, String repositoryContext, SaSecurityItem securityItemUser, SbmAffiliate affiliateUser, List<SysIdString> supervisedOrganisations, SbmAssociation associationOrganisation, SbmAffiliate affiliateOrganisation, bool keepLoggedIn, ref String errorMessage)
protected bool SignUserIn(ISbmUserContext_Core userContext, String repositoryContext, SaSecurityConsole securityConsoleForUser, SbmAccountMgr accountMgrForUser, SaSecurityItem securityItemUser, SbmAffiliate affiliateUser, List<SysIdString> supervisedOrganisations, SbmAssociation associationOrganisation, SbmAffiliate affiliateOrganisation, bool keepLoggedIn, ref String errorMessage)
{
// Validate Security Item and Affiliate, just in case - should have been done before arriving here!
if (securityItemUser == null)
@@ -125,8 +125,7 @@ namespace Sarand.BusinessMgr.Web.Portal.Controllers
// 'Keep logged in' can be switched off by the application configuration.
keepLoggedIn = App.AppConfig.Security.SignIn.KeepLoggedIn.Allowed && keepLoggedIn;
using (SaSecurityConsole securityConsoleForUser = App.CreateSecurityConsole(userContext))
using (SbmAccountMgr accountMgrForUser = App.System.CreateAccountMgr(userContext))
using (DisposableCollection<SacsDisposable> disposables = new DisposableCollection<SacsDisposable>())
{
// Log user in.
securityItemUser.LastLogin = DateTime.Now;
@@ -148,14 +147,14 @@ namespace Sarand.BusinessMgr.Web.Portal.Controllers
return false;
}
SaLogger.Info($"{SysUtil.Fn} User session opened for {securityItemUser.EmailAddress}", true);
// Create session.
OpenUserSession(userContext.SessionContext, repositoryContext, securityItemUser, affiliateUser, supervisedOrganisations, associationOrganisation, affiliateOrganisation);
// Configure security profile.
SessionData_Portal.SecurityProfile_Core.RefreshProfile(SessionConsole, securityConsoleForUser, securityItemUser.Id, securityConsoleForUser.GetRegisteredRights());
}
// Create session.
OpenUserSession(userContext.SessionContext, repositoryContext, securityItemUser, affiliateUser, supervisedOrganisations, associationOrganisation, affiliateOrganisation);
// Configure security profile.
SessionData_Portal.SecurityProfile_Core.RefreshProfile(SessionConsole, SecurityConsole, securityItemUser.Id, SecurityConsole.GetRegisteredRights());
// Send the 'Keep Logged In' cookie if requested.
if (affiliateUser.KeepLoggedIn_Portal)
SetKeepLoggedInCookie();
@@ -264,7 +263,7 @@ namespace Sarand.BusinessMgr.Web.Portal.Controllers
{
List<SysIdString> supervisedOrganisations = accountMgrForUser.GetAffiliatesSupervisedBy(affiliateUser.Id);
String errorMessage = "";
if (SignUserIn(userContext, keepLoggedInParams.RepositoryContext, securityItemUser, affiliateUser, supervisedOrganisations, associationOrganisation, affiliateOrganisation, true, ref errorMessage))
if (SignUserIn(userContext, keepLoggedInParams.RepositoryContext, securityConsoleForUser, accountMgrForUser, securityItemUser, affiliateUser, supervisedOrganisations, associationOrganisation, affiliateOrganisation, true, ref errorMessage))
{
SaLogger.Info(logPrefix + " 'Keep Logged In' cookie found." + logSuffix);
return true;
@@ -175,7 +175,7 @@ namespace Sarand.BusinessMgr.Web.Portal.Controllers.Security
}
// Initialise user session.
if (SignUserIn(userContext, model.RepositoryContext, securityItemUser, affiliateUser, supervisedOrganisations, associationOrganisation, affiliateOrganisation, model.KeepMeSignedIn, ref errorMessage))
if (SignUserIn(userContext, model.RepositoryContext, securityConsoleForUser, accountMgrForUser, securityItemUser, affiliateUser, supervisedOrganisations, associationOrganisation, affiliateOrganisation, model.KeepMeSignedIn, ref errorMessage))
return true;
}
return false;
@@ -0,0 +1,715 @@
using Sarand.BusinessMgr.Net.Standard.Base.App;
using Sarand.BusinessMgr.Net.Standard.Base.Bus;
using Sarand.Net.Standard.Base.Bus;
using System;
using System.Collections.Generic;
using System.Drawing;
namespace Sarand.BusinessMgr.Web.Portal.Models.Commodities
{
//=======================================================================
// Commodity model - Configuration.
//=======================================================================
partial class Model_Commodity
{
//-------------------------------------------------------------------
// Commodity fields.
//-------------------------------------------------------------------
/// <summary>Prefix for field names.</summary>
public const String FieldNamePrefix = "Commodity";
//-------------------------------------------------------------------
// Legacy Commodity dialog tabs and panels.
// - Commodity.
// - Tab 1:
// - Sales.
// - Costs (grid - category cost/labour per unit/job).
// - Orders ('Purchasing').
// - Specification.
// - Asset Category.
// - Defaults.
// - Machines.
// - Notes.
// - Tab 2:
// - Images.
// - Tab 3:
// - Processes
// - Production
// - Special Instructions.
// - Item Docs
// - Tab 4:
// - Stock
// - Stock Events
// - Sage Stock Transfers
// - Sales Budget
// - Tab 5:
// - Portfolio Items
// - Associated Products
// - Tab 6:
// - Update Log
// - Tab 7:
// - Requirements x 6.
// - Other.
// - Stock Projection
//-------------------------------------------------------------------
/// <summary>Item fields.</summary>
public enum ItemField
{
//---------------------------------------------------------------
// Commodity.
Pos,
Id,
Code,
DrawingNo,
DrawingIssue,
Type,
DescBrief,
//---------------------------------------------------------------
// Sales.
SalesPrice,
/// <summary>Formatted sales price - for list only.</summary>
SalesPriceFmt,
RetailPrice,
RetailPricePlanned,
TaxCodeId,
CarriageCostIndicative,
UomIdSale,
/// <summary>Unit of sale caption - for list only.</summary>
SalesUnit,
PackQtySale,
MinOrderQty,
DescOrder,
AssocIdCustomer,
Customer,
Department,
NominalCode,
Promotion,
//---------------------------------------------------------------
// Purchasing.
CostPrice,
/// <summary>Formatted cost price - for list only.</summary>
CostPriceFmt,
PlaceOfOrigin,
MaterialCost,
MaterialCurrency,
ExWorksCost,
ExWorksCurrency,
AssocIdSupplier,
Supplier,
SupplierRef,
NominalCodePurchase,
//---------------------------------------------------------------
// Specification.
Weight,
WeightUnit,
Length,
LengthUnit,
Volume,
VolumeUnit,
Density,
DensityUnit,
BoxQuantity,
BoxUnit,
Dimensions,
SpecSummary,
//---------------------------------------------------------------
// Asset.
AssetCategory,
//---------------------------------------------------------------
// Defaults.
ICNTariffCode,
Category,
Category2,
Category3,
Location,
CatalogRef,
//---------------------------------------------------------------
// Production.
MaterialCode,
FinishCode,
//---------------------------------------------------------------
// Special instructions.
DescDetail,
//---------------------------------------------------------------
// Codes.
RangeCode,
ColourCode,
SourceCode,
SupplyMethodCode,
HandlingCode,
DeliveryCode,
//---------------------------------------------------------------
// Inages.
ImagePath,
Image,
//---------------------------------------------------------------
// Production time.
TimeProd,
//---------------------------------------------------------------
// Stock.
QtyOnOrder,
LastOrderDate,
LastOrderQty,
ReorderLevel,
ReorderQty,
CurrentLevel,
StockAvailable,
StockMonthCurrent,
StockMonth,
StockDueProvisional,
QtyInStock,
QtyAllocated,
FreeStock,
StockTakeDate,
StockTakeQty,
//---------------------------------------------------------------
// Projected sales.
ProjectedSales,
//---------------------------------------------------------------
// Common properties.
Notes,
Status,
CreatedOn,
UpdatedOn,
Actions,
}
/// <summary>
/// Identifier used by form fields to show control specific messages generated by model validation etc.
/// <para>- Both page and model should use this method to consistently generate the field name.</para>
/// </summary>
public static String GetFieldName(ItemField field)
{
return $"{FieldNamePrefix}{field}";
}
//-------------------------------------------------------------------
// List configuration.
public class ListConfigData
{
// List columns.
public class ColumnData
{
// Column name prefix.
public String Prefix { get; } = Model_Commodity.FieldNamePrefix;
// Hide column.
public HashSet<string> Hide { get; } = new HashSet<string>(StringComparer.InvariantCultureIgnoreCase);
// Column labels.
public Dictionary<String, String> Label { get; } = new Dictionary<string, string>(StringComparer.InvariantCultureIgnoreCase);
}
public ColumnData Column { get; } = new ColumnData();
}
public ListConfigData ListConfig { get; private set; }
//-------------------------------------------------------------------
/// <summary>
/// Populate Commodity list configuration data in this model - only required on initial page construction.
/// </summary>
public void PopulateListConfig()
{
ListConfig = new ListConfigData();
PopulateListConfig(ListConfig);
}
/// <summary>
/// Populate Commodity list configuration data.
/// </summary>
public void PopulateListConfig(ListConfigData config)
{
// View properties.
CommodityViewMode viewMode = GetFilterMode();
bool modeIsMaintain = viewMode == CommodityViewMode.Maintain;
bool modeIsSearch = viewMode == CommodityViewMode.Search;
bool modeIsStockControl = viewMode == CommodityViewMode.StockControl;
bool modeIsStockTake = viewMode == CommodityViewMode.StockTake;
Sbm.CommodityType commodityType = GetFilterCommodityType();
//---------------------------------------------------------------
// Commodity list columns.
// Position.
// Id
if (!SbmSystem.DebugMode)
config.Column.Hide.Add($"{ItemField.Id}");
// Code.
// Drawing issue.
if (SessionConsole.DisplayAttribute(SbmDbDfn.ColumnIdx.Commodity_DrawingIssue))
config.Column.Label.Add($"{ItemField.DrawingIssue}", SessionConsole.GetAttributeCaption(SbmDbDfn.ColumnIdx.Commodity_DrawingIssue, Localiser["label.issue"]));
else
config.Column.Hide.Add($"{ItemField.DrawingIssue}");
// Commodity type.
if (commodityType <= 0)
config.Column.Label.Add($"{ItemField.Type}", SessionConsole.GetAttributeCaption(SbmDbDfn.ColumnIdx.Commodity_Type, Localiser["label.type"]));
else
config.Column.Hide.Add($"{ItemField.Type}");
// Description.
//---------------------------------------------------------------
// Sales.
// Sales price.
if (!UserCanViewCommodityFinancials_Sales())
config.Column.Hide.Add($"{ItemField.SalesPrice}");
// Pack qty.
if (modeIsStockControl || SessionData_Portal.GetOwnerOption_ShowColumn(Sbm.OrgOption_ShowColumn.Commodity_PackQtySale))
config.Column.Label.Add($"{ItemField.PackQtySale}", Localiser["label.pack.quantity"]);
else
config.Column.Hide.Add($"{ItemField.PackQtySale}");
// Customer.
if (modeIsStockControl || !SessionConsole.AllowOption(Sbm.ConfigOption.CommodityExclusiveToCustomer))
config.Column.Hide.Add($"{ItemField.Customer}");
// Promotion.
if (!SessionConsole.AllowOption(Sbm.ConfigOption.CommodityPromotion) || !CodeTypeConsole.CodeTypeHasCodes(Internals.GetCodeTypeCode(Sbm.ApplCodeType.CommodityPromotion)) || !CommodityMgr.ColumnExists(SbmDbDfn.ColumnIdx.Commodity_PromotionCode))
config.Column.Hide.Add($"{ItemField.Promotion}");
//---------------------------------------------------------------
// Purchasing.
// Cost price.
if (!UserCanViewCommodityFinancials_Supply())
config.Column.Hide.Add($"{ItemField.CostPrice}");
// Supplier.
if (!modeIsStockControl)
config.Column.Hide.Add($"{ItemField.Supplier}");
//---------------------------------------------------------------
// Specification.
// Weight.
if (modeIsStockControl || SessionData_Portal.GetOwnerOption_ShowColumn(Sbm.OrgOption_ShowColumn.Commodity_Weight))
config.Column.Label.Add($"{ItemField.Weight}", Localiser["label.weight"]);
else
config.Column.Hide.Add($"{ItemField.Weight}");
//---------------------------------------------------------------
// Defaults.
// Catalog Reference.
if (modeIsStockControl || SessionData_Portal.GetOwnerOption_ShowColumn(Sbm.OrgOption_ShowColumn.Commodity_CatalogRef))
config.Column.Label.Add($"{ItemField.CatalogRef}", SessionConsole.GetAttributeCaption(SbmDbDfn.ColumnIdx.Commodity_CatalogRef, Localiser["label.catalog.ref"]));
else
config.Column.Hide.Add($"{ItemField.CatalogRef}");
//---------------------------------------------------------------
// Stock.
// Stock - allocated.
if ((modeIsStockControl || SessionData_Portal.GetOwnerOption_ShowColumn(Sbm.OrgOption_ShowColumn.Commodity_StockAllocated)) && SessionConsole.DisplayAttribute(SbmDbDfn.ColumnIdx.Commodity_QtyAllocated))
config.Column.Label.Add($"{ItemField.QtyAllocated}", SessionConsole.GetAttributeCaption(SbmDbDfn.ColumnIdx.Commodity_QtyAllocated, Localiser["label.allocated"]));
else
config.Column.Hide.Add($"{ItemField.QtyAllocated}");
// Stock - available.
if (!modeIsStockControl && SessionData_Portal.GetOwnerOption_ShowColumn(Sbm.OrgOption_ShowColumn.Commodity_StockAvailable))
config.Column.Label.Add($"{ItemField.StockAvailable}", Localiser["label.available"]);
else
config.Column.Hide.Add($"{ItemField.StockAvailable}");
// Current Level.
if (modeIsStockControl || SessionData_Portal.GetOwnerOption_ShowColumn(Sbm.OrgOption_ShowColumn.Commodity_StockLevelSales))
config.Column.Label.Add($"{ItemField.CurrentLevel}", Localiser["label.current.level"]);
else
config.Column.Hide.Add($"{ItemField.CurrentLevel}");
// Stock - current month.
if (!modeIsStockControl)
config.Column.Hide.Add($"{ItemField.StockMonthCurrent}");
// Stock - by month.
if (!modeIsStockControl)
config.Column.Hide.Add($"{ItemField.StockMonth}");
// Stock - due provisional.
if (!modeIsStockControl)
config.Column.Hide.Add($"{ItemField.StockDueProvisional}");
//---------------------------------------------------------------
// Common.
// Status.
if (modeIsSearch)
config.Column.Hide.Add($"{ItemField.Status}");
// Actions.
if (!modeIsMaintain)
config.Column.Hide.Add($"{ItemField.Actions}");
}
//-------------------------------------------------------------------
// Item configuration.
//-------------------------------------------------------------------
// Contact item configuration.
public class ItemConfigData
{
// Item type.
public bool? IsOrganisation { get; set; }
public bool? IsIndividual { get; set; }
public bool? IsGroup { get; set; }
// Item fields.
public class FieldData
{
// Field name prefix.
public String Prefix { get; } = Model_Commodity.FieldNamePrefix;
// Hide field.
public HashSet<string> Hide { get; } = new HashSet<string>(StringComparer.InvariantCultureIgnoreCase);
// Read-only field.
public HashSet<string> Readonly { get; } = new HashSet<string>(StringComparer.InvariantCultureIgnoreCase);
// Field labels.
public Dictionary<String, String> Label { get; } = new Dictionary<string, string>(StringComparer.InvariantCultureIgnoreCase);
}
public FieldData Field { get; } = new FieldData();
}
//-------------------------------------------------------------------
/// <summary>
/// Populate item configuration for existing association.
/// </summary>
public void PopulateItemConfig(ItemConfigData config, SbmCommodity commodity)
{
PopulateItemConfig(config, commodity.GetItemId(), commodity.CommodityType);
}
/// <summary>
/// Populate item configuration for new or existing association.
/// </summary>
public void PopulateItemConfig(ItemConfigData config, ItemId commodityItemId, Sbm.CommodityType commodityType)
{
// Item type.
bool isProduct = commodityType != Sbm.CommodityType.Service;
bool isService = commodityType == Sbm.CommodityType.Service;
bool importedFromAccounts = Internals.AccountsDfn.ItemIsImportedFromAccounts(commodityItemId);
bool managedByAccounts = Internals.AccountsDfn.IsItemTypeManagedByAccounts(Sbm.ItemType.Commodity);
bool showNotes = true;
//---------------------------------------------------------------
// Commodity.
// Id.
if (SbmSystem.DebugMode)
config.Field.Readonly.Add($"{ItemField.Id}");
else
config.Field.Hide.Add($"{ItemField.Id}");
// Code.
// Read-only if commodity being superceded.
if (managedByAccounts)
config.Field.Readonly.Add($"{ItemField.Code}");
// Commodity type.
if (managedByAccounts)
config.Field.Readonly.Add($"{ItemField.Type}");
// Description.
if (managedByAccounts)
config.Field.Readonly.Add($"{ItemField.DescBrief}");
//---------------------------------------------------------------
// Sales.
// Sales price.
if (!UserCanViewCommodityFinancials_Sales())
config.Field.Hide.Add($"{ItemField.SalesPrice}");
else if (managedByAccounts || !UserCanUpdateFinancials())
config.Field.Readonly.Add($"{ItemField.SalesPrice}");
// Retail price.
if (UserCanViewCommodityFinancials_Sales() && SessionConsole.DisplayAttribute(SbmDbDfn.ColumnIdx.Commodity_RetailPrice))
{
config.Field.Label.Add($"{ItemField.RetailPrice}", SessionConsole.GetAttributeCaption(SbmDbDfn.ColumnIdx.Commodity_RetailPrice, Localiser["label.retail.price"]));
if (!UserCanUpdateFinancials())
config.Field.Readonly.Add($"{ItemField.RetailPrice}");
}
else config.Field.Hide.Add($"{ItemField.RetailPrice}");
// Retail price - planned.
if (UserCanViewCommodityFinancials_Sales() && SessionConsole.DisplayAttribute(SbmDbDfn.ColumnIdx.Commodity_RetailPricePlanned))
{
config.Field.Label.Add($"{ItemField.RetailPricePlanned}", SessionConsole.GetAttributeCaption(SbmDbDfn.ColumnIdx.Commodity_RetailPricePlanned, Localiser["label.retail.price.planned"]));
if (!UserCanUpdateFinancials())
config.Field.Readonly.Add($"{ItemField.RetailPricePlanned}");
}
else config.Field.Hide.Add($"{ItemField.RetailPricePlanned}");
// Tax code
if (managedByAccounts || !UserCanUpdateFinancials())
config.Field.Readonly.Add($"{ItemField.TaxCodeId}");
// Indicative carriage cost.
if (UserCanViewCommodityFinancials_Sales() && SessionConsole.DisplayAttribute(SbmDbDfn.ColumnIdx.Commodity_CarriageCostIndicative) || !CommodityMgr.ColumnExists(SbmDbDfn.ColumnIdx.Commodity_CarriageCostIndicative))
{
config.Field.Label.Add($"{ItemField.CarriageCostIndicative}", SessionConsole.GetAttributeCaption(SbmDbDfn.ColumnIdx.Commodity_CarriageCostIndicative, Localiser["label.carriage.cost.indicative"]));
if (!UserCanUpdateFinancials())
config.Field.Readonly.Add($"{ItemField.CarriageCostIndicative}");
}
else config.Field.Hide.Add($"{ItemField.CarriageCostIndicative}");
// Sales Unit.
if (managedByAccounts || !UserCanUpdateFinancials())
config.Field.Readonly.Add($"{ItemField.UomIdSale}");
// Sales Pack quantity.
// Min order quantity.
// Description - order.
if (managedByAccounts)
config.Field.Readonly.Add($"{ItemField.DescOrder}");
// Customer.
if (!SessionConsole.AllowOption(Sbm.ConfigOption.CommodityExclusiveToCustomer))
config.Field.Hide.Add($"{ItemField.Customer}");
else if (managedByAccounts)
config.Field.Readonly.Add($"{ItemField.Customer}");
// Department.
if (managedByAccounts)
config.Field.Readonly.Add($"{ItemField.Department}");
// Nominal code.
if (!managedByAccounts)
config.Field.Hide.Add($"{ItemField.NominalCode}");
// Promotion.
if (!SessionConsole.AllowOption(Sbm.ConfigOption.CommodityPromotion) || !CodeTypeConsole.CodeTypeHasCodes(Internals.GetCodeTypeCode(Sbm.ApplCodeType.CommodityPromotion)) || !CommodityMgr.ColumnExists(SbmDbDfn.ColumnIdx.Commodity_PromotionCode))
config.Field.Hide.Add($"{ItemField.Promotion}");
//---------------------------------------------------------------
// Purchasing.
// Cost price.
if (UserCanViewCommodityFinancials_Supply())
{
config.Field.Label.Add($"{ItemField.CostPrice}", SessionConsole.GetAttributeCaption(SbmDbDfn.ColumnIdx.Commodity_CostPrice, Localiser["label.cost.price"]));
if (!UserCanUpdateFinancials())
config.Field.Readonly.Add($"{ItemField.CostPrice}");
}
else config.Field.Hide.Add($"{ItemField.CostPrice}");
// Place of origin.
config.Field.Label.Add($"{ItemField.PlaceOfOrigin}", SessionConsole.GetAttributeCaption(SbmDbDfn.ColumnIdx.Commodity_PlaceOfOrigin, Localiser["label.place.of.origin"]));
// Material.
if (UserCanViewCommodityFinancials_Supply())
{
config.Field.Label.Add($"{ItemField.MaterialCost}", SessionConsole.GetAttributeCaption(SbmDbDfn.ColumnIdx.Commodity_MaterialCost, Localiser["label.material.cost"]));
config.Field.Label.Add($"{ItemField.MaterialCurrency}", SessionConsole.GetAttributeCaption(SbmDbDfn.ColumnIdx.Commodity_CurrencyIdMaterial, Localiser["label.material.currency"]));
if (!UserCanUpdateFinancials())
{
config.Field.Readonly.Add($"{ItemField.MaterialCost}");
config.Field.Readonly.Add($"{ItemField.MaterialCurrency}");
}
}
else
{
config.Field.Hide.Add($"{ItemField.MaterialCost}");
config.Field.Hide.Add($"{ItemField.MaterialCurrency}");
}
// Ex-works cost.
if (UserCanViewCommodityFinancials_Supply())
{
config.Field.Label.Add($"{ItemField.ExWorksCost}", SessionConsole.GetAttributeCaption(SbmDbDfn.ColumnIdx.Commodity_ExWorksCost, Localiser["label.ex.works.cost"]));
config.Field.Label.Add($"{ItemField.ExWorksCurrency}", SessionConsole.GetAttributeCaption(SbmDbDfn.ColumnIdx.Commodity_CurrencyIdExWorks, Localiser["label.ex.works.currency"]));
if (!UserCanUpdateFinancials())
{
config.Field.Readonly.Add($"{ItemField.ExWorksCost}");
config.Field.Readonly.Add($"{ItemField.ExWorksCurrency}");
}
}
else
{
config.Field.Hide.Add($"{ItemField.ExWorksCost}");
config.Field.Hide.Add($"{ItemField.ExWorksCurrency}");
}
// Nominal code - purchase.
if (!managedByAccounts)
config.Field.Hide.Add($"{ItemField.NominalCodePurchase}");
// Supplier.
if (!managedByAccounts)
config.Field.Hide.Add($"{ItemField.Supplier}");
// Supplier reference.
//---------------------------------------------------------------
// Specification.
// Weight.
if (isProduct && SessionConsole.DisplayAttribute(SbmDbDfn.ColumnIdx.Commodity_Weight))
{
config.Field.Label.Add($"{ItemField.Weight}", SessionConsole.GetAttributeCaption(SbmDbDfn.ColumnIdx.Commodity_Weight, Localiser["label.weight"]));
}
else
{
config.Field.Hide.Add($"{ItemField.Weight}");
config.Field.Hide.Add($"{ItemField.WeightUnit}");
}
// Lenghth.
if (isProduct && SessionConsole.DisplayAttribute(SbmDbDfn.ColumnIdx.Commodity_Length))
{
config.Field.Label.Add($"{ItemField.Length}", SessionConsole.GetAttributeCaption(SbmDbDfn.ColumnIdx.Commodity_Length, Localiser["label.length"]));
}
else
{
config.Field.Hide.Add($"{ItemField.Length}");
config.Field.Hide.Add($"{ItemField.LengthUnit}");
}
// Volume.
if (isProduct && SessionConsole.DisplayAttribute(SbmDbDfn.ColumnIdx.Commodity_Volume))
{
config.Field.Label.Add($"{ItemField.Volume}", SessionConsole.GetAttributeCaption(SbmDbDfn.ColumnIdx.Commodity_Volume, Localiser["label.volume"]));
}
else
{
config.Field.Hide.Add($"{ItemField.Volume}");
config.Field.Hide.Add($"{ItemField.VolumeUnit}");
}
// Density.
if (isProduct && SessionConsole.DisplayAttribute(SbmDbDfn.ColumnIdx.Commodity_Density))
{
config.Field.Label.Add($"{ItemField.Density}", SessionConsole.GetAttributeCaption(SbmDbDfn.ColumnIdx.Commodity_Density, Localiser["label.density"]));
}
else
{
config.Field.Hide.Add($"{ItemField.Density}");
config.Field.Hide.Add($"{ItemField.DensityUnit}");
}
// Box quantity.
if (isProduct && SessionConsole.DisplayAttribute(SbmDbDfn.ColumnIdx.Commodity_Dimensions))
{
config.Field.Label.Add($"{ItemField.BoxQuantity}", SessionConsole.GetAttributeCaption(SbmDbDfn.ColumnIdx.Commodity_BoxQuantity, Localiser["label.box.quantity"]));
}
else
{
config.Field.Hide.Add($"{ItemField.BoxQuantity}");
config.Field.Hide.Add($"{ItemField.BoxUnit}");
}
// Dimensions.
if (isProduct && SessionConsole.DisplayAttribute(SbmDbDfn.ColumnIdx.Commodity_Dimensions))
config.Field.Label.Add($"{ItemField.Dimensions}", SessionConsole.GetAttributeCaption(SbmDbDfn.ColumnIdx.Commodity_Dimensions, Localiser["label.dimensions"]));
else
config.Field.Hide.Add($"{ItemField.Dimensions}");
// Spec summary.
if (isProduct && SessionConsole.DisplayAttribute(SbmDbDfn.ColumnIdx.Commodity_SpecSummary))
config.Field.Label.Add($"{ItemField.SpecSummary}", SessionConsole.GetAttributeCaption(SbmDbDfn.ColumnIdx.Commodity_SpecSummary, Localiser["label.specification"]));
else
config.Field.Hide.Add($"{ItemField.SpecSummary}");
//---------------------------------------------------------------
// Asset.
// Asset category.
if (!SessionConsole.AllowOption(Sbm.ConfigOption.AllowAssets))
config.Field.Hide.Add($"{ItemField.AssetCategory}");
//---------------------------------------------------------------
// Defaults.
// ICN Tariff code.
if (managedByAccounts)
{
config.Field.Label.Add($"{ItemField.ICNTariffCode}", SessionConsole.GetAttributeCaption(SbmDbDfn.ColumnIdx.Commodity_ICNTariffCode, Localiser["label.icn.tariff.code"]));
config.Field.Readonly.Add($"{ItemField.ICNTariffCode}");
}
else
config.Field.Hide.Add($"{ItemField.ICNTariffCode}");
// Category.
if (managedByAccounts)
{
config.Field.Readonly.Add($"{ItemField.Category}");
config.Field.Readonly.Add($"{ItemField.Category2}");
config.Field.Readonly.Add($"{ItemField.Category3}");
}
// Location.
config.Field.Label.Add($"{ItemField.Location}", SessionConsole.GetAttributeCaption(SbmDbDfn.ColumnIdx.Commodity_Location, Localiser["label.location"]));
if (managedByAccounts)
config.Field.Readonly.Add($"{ItemField.Location}");
// Catalog reference.
config.Field.Label.Add($"{ItemField.CatalogRef}", SessionConsole.GetAttributeCaption(SbmDbDfn.ColumnIdx.Commodity_CatalogRef, Localiser["label.catalog.ref"]));
//---------------------------------------------------------------
// Special Instructions.
// Description - detail.
config.Field.Label.Add($"{ItemField.DescDetail}", SessionConsole.GetAttributeCaption(SbmDbDfn.ColumnIdx.Commodity_DescDetail, Localiser["label.desc.detail"]));
if (managedByAccounts)
config.Field.Readonly.Add($"{ItemField.DescDetail}");
// Image path.
if (managedByAccounts)
config.Field.Readonly.Add($"{ItemField.ImagePath}");
// Weight.
if (managedByAccounts)
config.Field.Readonly.Add($"{ItemField.Weight}");
if (managedByAccounts)
config.Field.Readonly.Add($"{ItemField.WeightUnit}");
//---------------------------------------------------------------
// Production.
// Material.
config.Field.Label.Add($"{ItemField.MaterialCode}", SessionConsole.GetAttributeCaption(SbmDbDfn.ColumnIdx.Commodity_MaterialCode, Localiser["label.material"]));
// Finish.
config.Field.Label.Add($"{ItemField.FinishCode}", SessionConsole.GetAttributeCaption(SbmDbDfn.ColumnIdx.Commodity_FinishCode, Localiser["label.finish"]));
//---------------------------------------------------------------
// Stock.
// Reorder level - not currently in use.
config.Field.Hide.Add($"{ItemField.ReorderLevel}");
// Reorder quantity - not currently in use.
config.Field.Hide.Add($"{ItemField.ReorderQty}");
// Quantity on order.
config.Field.Readonly.Add($"{ItemField.QtyOnOrder}");
// Last order date - not currently in use. Otherwise always read-only.
config.Field.Hide.Add($"{ItemField.LastOrderDate}");
// Last order quantity - not currently in use. Otherwise always read-only.
config.Field.Hide.Add($"{ItemField.LastOrderQty}");
//---------------------------------------------------------------
// Common.
// Notes.
if (!showNotes)
config.Field.Hide.Add($"{ItemField.Notes}");
// Status.
// Read-only if commodity being superceded.
if (managedByAccounts)
config.Field.Readonly.Add($"{ItemField.Status}");
}
//-------------------------------------------------------------------
}
}
@@ -13,12 +13,26 @@ using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using static Sarand.BusinessMgr.Net.Standard.Base.App.Sbm;
using static Sarand.BusinessMgr.Web.Portal.Models.Contacts.Model_Contact;
namespace Sarand.BusinessMgr.Web.Portal.Models.Commodities
{
//=======================================================================
public class Model_Commodity : SbmModel_Portal
// Commodity model.
//=======================================================================
/// <summary>
/// Commodity model - Filter, Form, validation and configuration.
/// </summary>
public partial class Model_Commodity : SbmModel_Portal
{
//-------------------------------------------------------------------
// Definitions.
public enum CommodityViewMode
{
Search, Maintain, StockControl, StockTake
}
//-------------------------------------------------------------------
// Construction.
public Model_Commodity(SbmLocaliser localiser) :
@@ -30,13 +44,21 @@ namespace Sarand.BusinessMgr.Web.Portal.Models.Commodities
// Filter properties.
public class FilterData
{
public string Search { get; set; }
public string CommodityType { get; set; }
public String Mode { get; set; }
public String CommodityType { get; set; }
public String Search { get; set; }
}
public FilterData Filter { get; } = new FilterData();
public CommodityViewMode GetFilterMode()
{
return EnumUtil.ParseEnum(Filter.Mode, CommodityViewMode.Search);
}
public Sbm.CommodityType GetFilterCommodityType()
{
return (Sbm.CommodityType)Internals.CommodityTypeCodes.GetTypeForCode(Filter.CommodityType);
Sbm.CommodityType commodityType = (Sbm.CommodityType)Internals.CommodityTypeCodes.GetTypeForCode(Filter.CommodityType);
if (commodityType == 0 && !StringUtil.IsBlank(Filter.CommodityType) && StringUtil.IsNumeric(Filter.CommodityType, true))
commodityType = (Sbm.CommodityType)StringUtil.ToInt(Filter.CommodityType);
return commodityType;
}
//-------------------------------------------------------------------
@@ -13,9 +13,8 @@ using System.Xml.Serialization;
namespace Sarand.BusinessMgr.Web.Portal.Models.Contacts
{
//=======================================================================
/// <summary>
/// Association model - Configuration.
/// </summary>
// Association model - Configuration.
//=======================================================================
partial class Model_Association
{
//-------------------------------------------------------------------
@@ -143,8 +142,6 @@ namespace Sarand.BusinessMgr.Web.Portal.Models.Contacts
bool typeIsSupplier = associationType == Sbm.AssociationType.Supplier;
bool typeIsMember = associationType == Sbm.AssociationType.Member;
bool userCanViewFinancials = SessionData_Portal.SecurityProfile_Core.UserCanViewFinancials();
// Actions.
if (typeIsCustomer)
@@ -180,23 +177,23 @@ namespace Sarand.BusinessMgr.Web.Portal.Models.Contacts
config.Column.Hide.Add($"{ItemField.Address}");
// Customer financials.
if (!modeIsMaintain || !typeIsCustomer || !userCanViewFinancials || !SessionData_Portal.GetOwnerOption_ShowColumn(Sbm.OrgOption_ShowColumn.Association_Trans_SalesValue_Open))
if (!modeIsMaintain || !typeIsCustomer || !UserCanViewFinancials() || !SessionData_Portal.GetOwnerOption_ShowColumn(Sbm.OrgOption_ShowColumn.Association_Trans_SalesValue_Open))
config.Column.Hide.Add($"{ItemField.TransSalesValueOpen}");
if (!modeIsMaintain || !typeIsCustomer || !SessionData_Portal.GetOwnerOption_ShowColumn(Sbm.OrgOption_ShowColumn.Association_Trans_LastSaleRaised))
config.Column.Hide.Add($"{ItemField.TransLastSaleRaised}");
if (!modeIsMaintain || !typeIsCustomer || !userCanViewFinancials || !SessionData_Portal.GetOwnerOption_ShowColumn(Sbm.OrgOption_ShowColumn.Association_AnnualSalesTarget))
if (!modeIsMaintain || !typeIsCustomer || !UserCanViewFinancials() || !SessionData_Portal.GetOwnerOption_ShowColumn(Sbm.OrgOption_ShowColumn.Association_AnnualSalesTarget))
config.Column.Hide.Add($"{ItemField.AnnualSalesTarget}");
if (!modeIsMaintain || !typeIsCustomer || !userCanViewFinancials || !SessionData_Portal.GetOwnerOption_ShowColumn(Sbm.OrgOption_ShowColumn.Association_Trans_SalesValue_Cytd))
if (!modeIsMaintain || !typeIsCustomer || !UserCanViewFinancials() || !SessionData_Portal.GetOwnerOption_ShowColumn(Sbm.OrgOption_ShowColumn.Association_Trans_SalesValue_Cytd))
config.Column.Hide.Add($"{ItemField.TransSalesValueCytd}");
if (!modeIsMaintain || !typeIsCustomer || !userCanViewFinancials || !SessionData_Portal.GetOwnerOption_ShowColumn(Sbm.OrgOption_ShowColumn.Association_Trans_SalesValue_Lcy))
if (!modeIsMaintain || !typeIsCustomer || !UserCanViewFinancials() || !SessionData_Portal.GetOwnerOption_ShowColumn(Sbm.OrgOption_ShowColumn.Association_Trans_SalesValue_Lcy))
config.Column.Hide.Add($"{ItemField.TransSalesValueLcy}");
// Customer commodities.
if (!modeIsMaintain || !typeIsCustomer || !CommodityMgr.CanManageCommodityCustomers())
config.Column.Hide.Add($"{ItemField.CommodityCount}");
// Customer pricing.
if (!modeIsMaintain || !typeIsCustomer || !userCanViewFinancials || !SessionConsole.AllowOption(Sbm.ConfigOption.CustomerDiscount))
if (!modeIsMaintain || !typeIsCustomer || !UserCanViewFinancials() || !SessionConsole.AllowOption(Sbm.ConfigOption.CustomerDiscount))
config.Column.Hide.Add($"{ItemField.DiscountRate}");
if (!modeIsMaintain || !typeIsCustomer || !userCanViewFinancials || !SessionConsole.AllowOption(Sbm.ConfigOption.CustomerPriceSet) && PriceMgr.PriceDatabaseIsValid)
if (!modeIsMaintain || !typeIsCustomer || !UserCanViewFinancials() || !SessionConsole.AllowOption(Sbm.ConfigOption.CustomerPriceSet) && PriceMgr.PriceDatabaseIsValid)
config.Column.Hide.Add($"{ItemField.PriceSet}");
// Association group.
if (!modeIsMaintain || !typeIsCustomer || !SessionData_Portal.GetOwnerOption_ShowColumn(Sbm.OrgOption_ShowColumn.Association_Group))
@@ -302,8 +299,6 @@ namespace Sarand.BusinessMgr.Web.Portal.Models.Contacts
/// </summary>
public void PopulateItemConfig(ItemConfigData config, ItemId associationItemId, SysId ownerId, Sbm.AssociationType associationType)
{
bool canViewFinancials = SessionData_Portal.SecurityProfile_Core.UserCanViewFinancials();
bool canUpdateFinancials = SessionData_Portal.SecurityProfile_Core.UserCanUpdateFinancials();
bool ownerIsInternal = SessionData_Portal.Organisation.AffiliateId.Equals(ownerId);
bool isCustomer = SbmAssociation.IsCustomer(associationType);
bool isSupplier = SbmAssociation.IsSupplier(associationType);
@@ -384,9 +379,9 @@ namespace Sarand.BusinessMgr.Web.Portal.Models.Contacts
// Financials.
// Annual Sales Target.
if (!canViewFinancials)
if (!UserCanViewFinancials())
config.Field.Hide.Add($"{ItemField.AnnualSalesTarget}");
else if (!canUpdateFinancials)
else if (!UserCanUpdateFinancials())
config.Field.Readonly.Add($"{ItemField.AnnualSalesTarget}");
// Default Nominal Code.
@@ -396,37 +391,37 @@ namespace Sarand.BusinessMgr.Web.Portal.Models.Contacts
config.Field.Readonly.Add($"{ItemField.DefaultNominalCode}");
// Credit limit.
if (!canViewFinancials || !managedByAccounts)
if (!UserCanViewFinancials() || !managedByAccounts)
config.Field.Hide.Add($"{ItemField.CreditLimit}");
else if (managedByAccounts || !canUpdateFinancials)
else if (managedByAccounts || !UserCanUpdateFinancials())
config.Field.Readonly.Add($"{ItemField.CreditLimit}");
// Account balance.
if (!canViewFinancials || !managedByAccounts)
if (!UserCanViewFinancials() || !managedByAccounts)
config.Field.Hide.Add($"{ItemField.AccountBalance}");
else if (managedByAccounts || !canUpdateFinancials)
else if (managedByAccounts || !UserCanUpdateFinancials())
config.Field.Readonly.Add($"{ItemField.AccountBalance}");
// Discount.
if (!canViewFinancials || (!managedByAccounts && !SessionConsole.AllowOption(isSupplier ? Sbm.ConfigOption.SupplierDiscount : Sbm.ConfigOption.CustomerDiscount)))
if (!UserCanViewFinancials() || (!managedByAccounts && !SessionConsole.AllowOption(isSupplier ? Sbm.ConfigOption.SupplierDiscount : Sbm.ConfigOption.CustomerDiscount)))
{
config.Field.Hide.Add($"{ItemField.DiscountType}");
config.Field.Hide.Add($"{ItemField.DiscountRate}");
}
else if (!localPricing || !canUpdateFinancials)
else if (!localPricing || !UserCanUpdateFinancials())
{
config.Field.Readonly.Add($"{ItemField.DiscountType}");
config.Field.Readonly.Add($"{ItemField.DiscountRate}");
}
// Price set.
if (!canViewFinancials || (!managedByAccounts && !SessionConsole.AllowOption(isSupplier ? Sbm.ConfigOption.SupplierPriceSet : Sbm.ConfigOption.CustomerPriceSet)) || !PriceMgr.PriceDatabaseIsValid)
if (!UserCanViewFinancials() || (!managedByAccounts && !SessionConsole.AllowOption(isSupplier ? Sbm.ConfigOption.SupplierPriceSet : Sbm.ConfigOption.CustomerPriceSet)) || !PriceMgr.PriceDatabaseIsValid)
config.Field.Hide.Add($"{ItemField.PriceSet}");
else if (!localPricing || !canUpdateFinancials)
else if (!localPricing || !UserCanUpdateFinancials())
config.Field.Readonly.Add($"{ItemField.PriceSet}");
// Tax code.
if (managedByAccounts || !canUpdateFinancials)
if (managedByAccounts || !UserCanUpdateFinancials())
config.Field.Readonly.Add($"{ItemField.TaxCode}");
// Default sales commodity.
@@ -17,9 +17,11 @@ using System.Threading.Tasks;
namespace Sarand.BusinessMgr.Web.Portal.Models.Contacts
{
//=======================================================================
// Association model.
//=======================================================================
/// <summary>
/// Association model - Filter and Form.
/// Association model - Filter, Form, validation and configuration.
/// </summary>
public partial class Model_Association : SbmModel_Portal
{
@@ -53,7 +55,7 @@ namespace Sarand.BusinessMgr.Web.Portal.Models.Contacts
public FilterData Filter { get; } = new FilterData();
public AssociationViewMode GetFilterMode()
{
return EnumUtil.ParseEnum(Filter.Mode, AssociationViewMode.Maintain);
return EnumUtil.ParseEnum(Filter.Mode, AssociationViewMode.Search);
}
public Sbm.AssociationType GetFilterAssociationType()
{
@@ -8,9 +8,8 @@ using System.Collections.Generic;
namespace Sarand.BusinessMgr.Web.Portal.Models.Contacts
{
//=======================================================================
/// <summary>
/// Contact model - Configuration.
/// </summary>
// Contact model - Configuration.
//=======================================================================
partial class Model_Contact
{
//-------------------------------------------------------------------
@@ -124,29 +123,29 @@ namespace Sarand.BusinessMgr.Web.Portal.Models.Contacts
// Contact type.
if (affiliateType <= 0)
config.Column.Label.Add($"{ItemField.Type}", Localiser["label.type"]);
config.Column.Label.Add($"{ItemField.Type}", SessionConsole.GetAttributeCaption(SbmDbDfn.ColumnIdx.Affiliate_Type, Localiser["label.type"]));
else
config.Column.Hide.Add($"{ItemField.Type}");
// Contact name.
config.Column.Label.Add($"{ItemField.Name}", Localiser["label.name"]);
config.Column.Label.Add($"{ItemField.Name}", SessionConsole.GetAttributeCaption(SbmDbDfn.ColumnIdx.Affiliate_Name, Localiser["label.name"]));
// Nature.
bool showNature = false;
if (!contactGroupsOnly && showNature)
config.Column.Label.Add($"{ItemField.Nature}", Localiser["label.nature"]);
config.Column.Label.Add($"{ItemField.Nature}", SessionConsole.GetAttributeCaption(SbmDbDfn.ColumnIdx.Affiliate_Nature, Localiser["label.nature"]));
else
config.Column.Hide.Add($"{ItemField.Nature}");
// Email.
if (!contactGroupsOnly && (affiliateType == Sbm.AffiliateType.Individual || !StringUtil.IsBlank(Filter.Email)))
config.Column.Label.Add($"{ItemField.Email}", Localiser["label.email"]);
config.Column.Label.Add($"{ItemField.Email}", SessionConsole.GetAttributeCaption(SbmDbDfn.ColumnIdx.Affiliate_Email, Localiser["label.email"]));
else
config.Column.Hide.Add($"{ItemField.Email}");
// Contact.
if (!contactGroupsOnly && (affiliateType != Sbm.AffiliateType.Individual))
config.Column.Label.Add($"{ItemField.Contact}", Localiser["label.contact"]);
config.Column.Label.Add($"{ItemField.Contact}", SessionConsole.GetAttributeCaption(SbmDbDfn.ColumnIdx.Affiliate_Contact, Localiser["label.contact"]));
else
config.Column.Hide.Add($"{ItemField.Contact}");
@@ -17,9 +17,11 @@ using System.Threading.Tasks;
namespace Sarand.BusinessMgr.Web.Portal.Models.Contacts
{
//=======================================================================
// Contact model.
//=======================================================================
/// <summary>
/// Contact (Affiliate) model - Configuration.
/// Contact (Affiliate) model - Filter, Form, validation and configuration.
/// </summary>
public partial class Model_Contact : SbmModel_Portal
{
@@ -42,14 +44,14 @@ namespace Sarand.BusinessMgr.Web.Portal.Models.Contacts
public class FilterData
{
public String Mode { get; set; }
public string ContactType { get; set; }
public string Search { get; set; }
public string Email { get; set; }
public String ContactType { get; set; }
public String Search { get; set; }
public String Email { get; set; }
}
public FilterData Filter { get; } = new FilterData();
public ContactViewMode GetFilterMode()
{
return EnumUtil.ParseEnum(Filter.Mode, ContactViewMode.Maintain);
return EnumUtil.ParseEnum(Filter.Mode, ContactViewMode.Search);
}
public Sbm.AffiliateType GetFilterContactType()
{
@@ -63,31 +65,31 @@ namespace Sarand.BusinessMgr.Web.Portal.Models.Contacts
// Contact properties.
public class ContactData
{
public string Id { get; set; }
public string Exists { get; set; }
public string Type { get; set; }
public string IsIndividual { get; set; }
public string IsGroup { get; set; }
public String Id { get; set; }
public String Exists { get; set; }
public String Type { get; set; }
public String IsIndividual { get; set; }
public String IsGroup { get; set; }
// Organisation.
public string Name { get; set; }
public string Abbreviation { get; set; }
public string Nature { get; set; }
public string Contact { get; set; }
public string PhoneMain { get; set; }
public string PhoneAlt { get; set; }
public string PhoneDirect { get; set; }
public string PhoneFax { get; set; }
public string Email { get; set; }
public string Website { get; set; }
public string CompanyNo { get; set; }
public string VatReg { get; set; }
public String Name { get; set; }
public String Abbreviation { get; set; }
public String Nature { get; set; }
public String Contact { get; set; }
public String PhoneMain { get; set; }
public String PhoneAlt { get; set; }
public String PhoneDirect { get; set; }
public String PhoneFax { get; set; }
public String Email { get; set; }
public String Website { get; set; }
public String CompanyNo { get; set; }
public String VatReg { get; set; }
// Individual.
public string Title { get; set; }
public string Salutation { get; set; }
public string FirstName { get; set; }
public string Initials { get; set; }
public string LastName { get; set; }
public string PhoneMobile { get; set; }
public String Title { get; set; }
public String Salutation { get; set; }
public String FirstName { get; set; }
public String Initials { get; set; }
public String LastName { get; set; }
public String PhoneMobile { get; set; }
// Flags.
// NB Have to use bool with checkbox and then cannot tell whether
// false is unchecked or not submitted (ie. excluded from form, disabled etc).
@@ -95,12 +97,11 @@ namespace Sarand.BusinessMgr.Web.Portal.Models.Contacts
private bool? prospectValue { get; set; }
public bool Prospect { get { return prospectValue ?? false; } set { prospectValue = value; } }
// Common properties.
public string Notes { get; set; }
public string StatusCode { get; set; }
public String Notes { get; set; }
public String StatusCode { get; set; }
}
public SysId GetAffiliateId() { return StringUtil.ToSysId(Contact.Id); }
public SaStatus GetAffiliateStatus() { return SacsSystem.GetStatusForCode(Contact.StatusCode); }
public ContactData Contact { get; } = new ContactData();
public SysId GetAffiliateId() { return StringUtil.ToSysId(Contact.Id); }
public Sbm.AffiliateType GetAffiliateType()
{
if (StringUtil.ToBool(Contact.IsIndividual))
@@ -111,6 +112,7 @@ namespace Sarand.BusinessMgr.Web.Portal.Models.Contacts
return (Sbm.AffiliateType)Internals.AffiliateTypeCodes.GetTypeForCode(Contact.Type);
return Sbm.AffiliateType.Unknown;
}
public SaStatus GetAffiliateStatus() { return SacsSystem.GetStatusForCode(Contact.StatusCode); }
//-------------------------------------------------------------------
// Validation.
@@ -10,6 +10,7 @@ using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using static Sarand.BusinessMgr.Net.Standard.Base.App.Sbm;
namespace Sarand.BusinessMgr.Web.Portal.Models
{
@@ -29,6 +30,16 @@ namespace Sarand.BusinessMgr.Web.Portal.Models
public override ISbmUserContext_Core UserContext_Core { get { return SessionData_Portal; } }
public String OrganisationName { get { return SessionData_Portal?.Organisation?.DisplayName ?? ""; } }
//-------------------------------------------------------------------
// Security profile.
public bool UserCanViewFinancials() { return SessionData_Portal.SecurityProfile_Core.UserCanViewFinancials(); }
public bool UserCanViewCommodityFinancials_Supply() { return SessionData_Portal.SecurityProfile_Core.UserCanViewFinancials(FinancialType.CommoditySupply); }
public bool UserCanViewCommodityFinancials_Sales() { return SessionData_Portal.SecurityProfile_Core.UserCanViewFinancials(FinancialType.CommoditySales); }
public bool UserCanUpdateFinancials() { return SessionData_Portal.SecurityProfile_Core.UserCanUpdateFinancials(); }
public bool UserCanStockTake() { return SessionData_Portal.SecurityProfile_Core.UserHasSecurityRight(SecurityRight.StockTake); }
public bool UserCanCreateItem(Sbm.ItemType itemType) { return SessionData_Portal.SecurityProfile_Core.UserCanCreateItemType(itemType); }
public bool UserCanUpdateItem(Sbm.ItemType itemType) { return SessionData_Portal.SecurityProfile_Core.UserCanUpdateItemType(itemType); }
//-------------------------------------------------------------------
// View reference data.
@@ -44,6 +44,10 @@
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
</Content>
<Content Update="Views\Commodity\Panel-CommodityMaintain.cshtml">
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
</Content>
</ItemGroup>
<ItemGroup>
@@ -3,7 +3,7 @@
@inject SbmLocaliser Localiser
@{
/* Association list panel */
/* NB Can potentially appear more than once on a page? */
/* NB Can potentially appear more than once on a page. */
}
@* Item list *@
@@ -20,6 +20,8 @@
@* Filter form - wrap header to include paging controls. *@
@using (@Html.BeginForm(FormMethod.Post, new { @id = "", @class = "frmAssociationFilter sbm-form", @onSubmit = "return false;" }))
{
@Html.Hidden("Filter.Mode", Model_Association.AssociationViewMode.Maintain, new { @id = "" })
@* Header - Page caption, paging controls, actions. *@
<div class="sbm-panel-header">
<div class="row">
@@ -15,7 +15,7 @@
@using (@Html.BeginForm(FormMethod.Post, new { @id = "", @class = "frmAssociationFilter sbm-form", @onSubmit = "return false;" }))
{
@Html.Hidden("Filter.Mode", "Search", new { @id = "" })
@Html.Hidden("Filter.Mode", Model_Association.AssociationViewMode.Search, new { @id = "" })
@Html.Hidden("Filter.OwnerId", "", new { @id = "", @class = "FilterOwnerId" })
@Html.Hidden("Filter.TargetId", "", new { @id = "", @class = "FilterTargetId" })
@@ -1,121 +1,8 @@
@model Model_Commodity
@inject SbmLocaliser Localiser
@{
/* Commodities - Index */
/* Commodity page. */
ViewData["Title"] = "Commodities";
Model.AdditionalFiles_JS.Add("js/sbm-commodity.js");
}
<div class="sbm-panel Commodities fullheight">
<script type="text/javascript">
</script>
<div class="sbm-panel-data sbm-flex">
@* Filter form - wrap header to include paging controls. *@
@using (@Html.BeginForm(FormMethod.Post, new { @id = "frmCommodityFilter", @class = "sbm-form", @onSubmit = "return false;" }))
{
@* Header - Page caption, paging controls, actions. *@
<div class="sbm-panel-header">
<div class="row">
<div class="col"><partial name="~/Views/Common/ResultsPaging.cshtml" /></div>
<div class="fixed center"><div class="sbm-panel-caption">@Localiser["caption.commodities"]</div></div>
<div class="col right">
@* Burger menu *@
<ul class="nav navbar-nav navbar-dark navbar-right sbm-burger">
<li class="dropdown-toggle caret-off">
<a href="#" class="dropdown" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false"><span class="navbar-toggler-icon"></span></a>
<ul class="dropdown-menu dropdown-menu-right sbm-dropdown-menu">@* Menu items will be inserted here. *@</ul>
</li>
</ul>
</div>
</div>
</div>
@* Filter Panel *@
<div class="sbm-panel-filter">
<div class="row">
<div class="col-sm-4 row pb4">
@* Commodity filter - code, description etc *@
<div class="col-4 col-sm-4 sbm-label text-left text-sm-right">@Localiser["label.search"]</div>
<div class="col-7 col-sm-8">
@Html.TextBoxFor(model => model.Filter.Search, new { @id = "", @class = "FilterCommodity sbm-input", @maxlength = "32" })
</div>
</div>
<div class="col-sm-4 row pb4">
@* Commodity Category *@
<div class="col-4 col-sm-4 sbm-label text-left text-sm-right">@Localiser["label.type"]</div>
<div class="col-7 col-sm-8">
@Html.DropDownListFor(model => model.Filter.CommodityType, Model.GetCommodityTypeCodesForSelect(), Localiser["label.any"], new { @id = "", @class = "FilterCommodityType sbm-select" })
</div>
</div>
<div class="col-sm-4 row pb4">
</div>
</div>
</div>
}
@* Item list *@
<div class="sbm-panel-item-table sbm-flex">
<table class="sbm-item-list">
<thead>
<tr>
<th class="pl-2">@Localiser["label.code"]</th>
<th class="">@Localiser["label.description"]</th>
<th class="">@Localiser["label.type"]</th>
<th class="right">@Localiser["label.sales.price"]</th>
<th class="center">@Localiser["label.unit.of.sale"]</th>
<th class="d-none d-md-table-cell">@Localiser["label.notes"]</th>
<th class="center">@Localiser["label.status"]</th>
<th class="right" style="width:2%;"></th>
</tr>
<tr><td colspan="6"><div class="sbm-panel-messages"></div></td></tr>
</thead>
<tbody></tbody>
</table>
</div>
@* Element templates *@
<div class="sbm-panel-item-template">
@* List burger dropdown template - ul is ignored *@
<ul class="sbm-dropdown-menu CommodityList">
<li class="sbm-dropdown-item sbm-action"><div class="sbm-label">XXX</div></li>
</ul>
@* Item row template - table is ignored. *@
<table>
<tr class="sbm-row-item Commodity">
<td><div class="CommodityCode pl-1"></div></td>
<td><div class="CommodityDesc"></div></td>
<td><div class="CommodityType"></div></td>
<td class="right"><div class="CommoditySalesPrice"></div></td>
<td class="center"><div class="CommoditySalesUnits"></div></td>
<td class="d-none d-md-table-cell"><div class="CommodityNotes"></div></td>
<td><div class="CommodityStatusDesc center"></div></td>
<td>
<div class="right">
@* Burger menu *@
<ul class="nav navbar-nav navbar-light navbar-right sbm-burger">
<li class="dropdown-toggle caret-off">
<a href="#" class="dropdown" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false"><span class="sbm-ellipsis-dot"></span><span class="sbm-ellipsis-dot"></span><span class="sbm-ellipsis-dot"></span></a>
<ul class="dropdown-menu dropdown-menu-right sbm-dropdown-menu">@* Menu items will be inserted here. *@</ul>
</li>
</ul>
</div>
</td>
</tr>
</table>
@* Item burger dropdown template - ul is ignored *@
<ul class="sbm-dropdown-menu Commodity">
<li class="sbm-dropdown-item sbm-action"><div class="sbm-label">XXX</div></li>
</ul>
</div>
</div>
</div>
<partial name="Panel-CommodityDialog.cshtml" />
<partial name="Panel-CommodityMaintain.cshtml" />
@@ -1,7 +1,10 @@
@model Model_Commodity
@* View is decoupled from Commodity model as it may be included in other views, eg. Transactions. *@
@model SbmModel_Portal
@inject SbmLocaliser Localiser
@{
/* Commodities - Commodity dialog panel */
/* Commodity dialog panel */
// Ensure view is only included once in page.
if (!Model.RegisterView("Views/Commodity/Panel-CommodityDialog")) return;
}
<script type="text/javascript">
@@ -11,19 +14,19 @@
@using (@Html.BeginForm(FormMethod.Post, new { @id = "frmCommodityId", @class = "sbm-form" }))
{
@Html.HiddenFor(model => model.Commodity.Id, new { @class = "CommodityId" })
@Html.Hidden("Commodity.Id", "", new { @id = "", @class = "CommodityId" })
}
<div id="dlgCommodity" class="sbm-dialog" title="">
@using (@Html.BeginForm(FormMethod.Post, new { @id = "frmCommodity", @class = "sbm-form", @onSubmit = "return false;" }))
{
@Html.HiddenFor(model => model.Commodity.Id, new { @id = "", @class = "CommodityId sbm-input" })
@Html.HiddenFor(model => model.Commodity.Exists, new { @id = "", @class = "CommodityExists sbm-input" })
@Html.HiddenFor(model => model.Commodity.SupersededStatusConfirmed, new { @id = "", @class = "SupersededStatusConfirmed sbm-input" })
@Html.Hidden("Commodity.Id", "", new { @id = "", @class = "CommodityId sbm-input" })
@Html.Hidden("Commodity.Exists", "", new { @id = "", @class = "CommodityExists sbm-input" })
@Html.Hidden("Commodity.SupersededStatusConfirmed", "", new { @id = "", @class = "SupersededStatusConfirmed sbm-input" })
@* Commodity Type *@
<div class="sbm-form-control CommodityType">
<div class="sbm-form-control @Model_Commodity.GetFieldName(Model_Commodity.ItemField.Type)">
<div class="row">
<div class="col-sm-3">
<div class="sbm-label">
@@ -32,7 +35,7 @@
</div>
<div class="col-sm">
<div class="sbm-control">
@Html.DropDownListFor(model => model.Commodity.Type, Model.GetCommodityTypeCodesForSelect(), Localiser["label.select"], new { @id = "cbCommodityType", @class = "CommodityType sbm-select" })
@Html.DropDownList("Commodity.Type", Model.GetCommodityTypeCodesForSelect(), Localiser["label.select"], new { @id = "cbCommodityType", @class = "CommodityType sbm-select" })
</div>
<div class="sbm-message"></div>
</div>
@@ -40,7 +43,7 @@
</div>
@* Commodity Code *@
<div class="sbm-form-control CommodityCode">
<div class="sbm-form-control @Model_Commodity.GetFieldName(Model_Commodity.ItemField.Code)">
<div class="row">
<div class="col-sm-3">
<div class="sbm-label">
@@ -49,7 +52,7 @@
</div>
<div class="col-sm">
<div class="sbm-control">
@Html.TextBoxFor(model => model.Commodity.Code, new { @id = "ifCommodityCode", @class = "CommodityCode sbm-input", @maxlength = @Model.GetControlMaxLength(SbmDbDfn.ColumnIdx.Commodity_Code) })
@Html.TextBox("Commodity.Code", "", new { @id = "ifCommodityCode", @class = "CommodityCode sbm-input sbm-auto-val", @maxlength = @Model.GetControlMaxLength(SbmDbDfn.ColumnIdx.Commodity_Code) })
</div>
<div class="sbm-message"></div>
</div>
@@ -57,7 +60,7 @@
</div>
@* Commodity Description *@
<div class="sbm-form-control CommodityDesc">
<div class="sbm-form-control @Model_Commodity.GetFieldName(Model_Commodity.ItemField.DescBrief)">
<div class="row">
<div class="col-sm-3">
<div class="sbm-label">
@@ -66,7 +69,7 @@
</div>
<div class="col-sm">
<div class="sbm-control">
@Html.TextBoxFor(model => model.Commodity.DescBrief, new { @id = "ifCommodityDesc", @class = "CommodityDesc sbm-input", @maxlength = @Model.GetControlMaxLength(SbmDbDfn.ColumnIdx.Commodity_DescBrief) })
@Html.TextBox("Commodity.DescBrief", "", new { @id = "ifCommodityDesc", @class = "CommodityDesc sbm-input sbm-auto-val", @maxlength = @Model.GetControlMaxLength(SbmDbDfn.ColumnIdx.Commodity_DescBrief) })
</div>
<div class="sbm-message"></div>
</div>
@@ -74,7 +77,7 @@
</div>
@* Commodity status *@
<div class="sbm-form-control CommodityStatus">
<div class="sbm-form-control @Model_Commodity.GetFieldName(Model_Commodity.ItemField.Status)">
<div class="row">
<div class="col-sm-3">
<div class="sbm-label">
@@ -83,7 +86,7 @@
</div>
<div class="col-sm">
<div class="sbm-control">
<select id="cbCommodityStatus" class="sbm-select CommodityStatus" name="Commodity.StatusCode"></select>
<select id="cbCommodityStatus" class="CommodityStatus sbm-select sbm-auto-val" name="Commodity.StatusCode"></select>
</div>
<div class="sbm-message"></div>
</div>
@@ -91,7 +94,7 @@
</div>
@* Commodity Notes *@
<div class="sbm-form-control CommodityNotes">
<div class="sbm-form-control @Model_Commodity.GetFieldName(Model_Commodity.ItemField.Notes)">
<div class="row">
<div class="col-sm-3">
<div class="sbm-label">
@@ -100,7 +103,7 @@
</div>
<div class="col-sm">
<div class="sbm-control">
@Html.TextAreaFor(model => model.Commodity.Notes, new { @id = "ifCommodityNotes", @class = "CommodityNotes sbm-textarea", @rows = "3", @maxlength = @Model.GetControlMaxLength(SbmDbDfn.ColumnIdx.Commodity_Notes) })
@Html.TextArea("Commodity.Notes", "", new { @id = "ifCommodityNotes", @class = "CommodityNotes sbm-textarea sbm-auto-val", @rows = "3", @maxlength = @Model.GetControlMaxLength(SbmDbDfn.ColumnIdx.Commodity_Notes) })
</div>
<div class="sbm-message"></div>
</div>
@@ -0,0 +1,70 @@
@* View is decoupled from Commodity model as it may be included in other views, eg. Transactions. *@
@model SbmModel_Portal
@inject SbmLocaliser Localiser
@{
/* Commodity list panel */
/* NB Can potentially appear more than once on a page. */
}
@* Item list *@
<div class="sbm-panel-item-table sbm-flex">
<table class="sbm-item-list">
<thead>
<tr>
<th class="@Model_Commodity.GetFieldName(Model_Commodity.ItemField.Code) width20pc pl-2">@Localiser["label.code"]</th>
<th class="@Model_Commodity.GetFieldName(Model_Commodity.ItemField.DescBrief) width25pc">@Localiser["label.description"]</th>
<th class="@Model_Commodity.GetFieldName(Model_Commodity.ItemField.Type) width5pc center">@Localiser["label.type"]</th>
@if (Model.UserCanViewCommodityFinancials_Sales())
{
<th class="@Model_Commodity.GetFieldName(Model_Commodity.ItemField.SalesPriceFmt) width5pc right">@Localiser["label.sales.price"]</th>
<th class="@Model_Commodity.GetFieldName(Model_Commodity.ItemField.SalesUnit) width5pc center">@Localiser["label.unit.of.sale"]</th>
}
<th class="@Model_Commodity.GetFieldName(Model_Commodity.ItemField.Notes) width25pc d-none d-md-table-cell">@Localiser["label.notes"]</th>
<th class="@Model_Commodity.GetFieldName(Model_Commodity.ItemField.Status) width5pc center">@Localiser["label.status"]</th>
<th class="@Model_Commodity.GetFieldName(Model_Commodity.ItemField.Actions) width5pc right" style="width:2%;"></th>
</tr>
<tr><td colspan="6"><div class="sbm-panel-messages"></div></td></tr>
</thead>
<tbody></tbody>
</table>
</div>
@* Element templates *@
<div class="sbm-panel-item-template">
@* List burger dropdown template - ul is ignored *@
<ul class="sbm-dropdown-menu CommodityList">
<li class="sbm-dropdown-item sbm-action"><div class="sbm-label">XXX</div></li>
</ul>
@* Item row template - table is ignored. *@
<table>
<tr class="sbm-row-item Commodity">
<td class="@Model_Commodity.GetFieldName(Model_Commodity.ItemField.Code) pl-1"></td>
<td class="@Model_Commodity.GetFieldName(Model_Commodity.ItemField.DescBrief)"></td>
<td class="@Model_Commodity.GetFieldName(Model_Commodity.ItemField.Type) center nowrap"></td>
@if (Model.UserCanViewCommodityFinancials_Sales())
{
<td class="@Model_Commodity.GetFieldName(Model_Commodity.ItemField.SalesPriceFmt) right nowrap"></td>
<td class="@Model_Commodity.GetFieldName(Model_Commodity.ItemField.SalesUnit) center nowrap"></td>
}
<td class="@Model_Commodity.GetFieldName(Model_Commodity.ItemField.Notes) d-none d-md-table-cell"></td>
<td class="@Model_Commodity.GetFieldName(Model_Commodity.ItemField.Status) center nowrap"></td>
<td class="@Model_Commodity.GetFieldName(Model_Commodity.ItemField.Actions)">
<div class="right">
@* Burger menu *@
<ul class="nav navbar-nav navbar-light navbar-right sbm-burger">
<li class="dropdown-toggle caret-off">
<a href="#" class="dropdown" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false"><span class="sbm-ellipsis-dot"></span><span class="sbm-ellipsis-dot"></span><span class="sbm-ellipsis-dot"></span></a>
<ul class="dropdown-menu dropdown-menu-right sbm-dropdown-menu">@* Menu items will be inserted here. *@</ul>
</li>
</ul>
</div>
</td>
</tr>
</table>
@* Item burger dropdown template - ul is ignored *@
<ul class="sbm-dropdown-menu Commodity">
<li class="sbm-dropdown-item sbm-action"><div class="sbm-label">XXX</div></li>
</ul>
@@ -0,0 +1,70 @@
@* View is decoupled from Commodity model as it may be included in other views, eg. Transactions. *@
@model SbmModel_Portal
@inject SbmLocaliser Localiser
@{
/* Commodity maintain panel */
// Ensure view is only included once in page.
if (!Model.RegisterView("Views/Commodity/Panel-CommodityMaintain")) return;
Model.AdditionalFiles_JS.Add("js/sbm-commodity.js");
}
<div class="sbm-panel Commodities fullheight">
<script type="text/javascript">
</script>
<div class="sbm-panel-data sbm-flex">
@* Filter form - wrap header to include paging controls. *@
@using (@Html.BeginForm(FormMethod.Post, new { @id = "frmCommodityFilter", @class = "sbm-form", @onSubmit = "return false;" }))
{
@Html.Hidden("Filter.Mode", Model_Commodity.CommodityViewMode.Maintain, new { @id = "" })
@* Header - Page caption, paging controls, actions. *@
<div class="sbm-panel-header">
<div class="row">
<div class="col"><partial name="~/Views/Common/ResultsPaging.cshtml" /></div>
<div class="fixed center"><div class="sbm-panel-caption">@Localiser["caption.commodities"]</div></div>
<div class="col right">
@* Burger menu *@
<ul class="nav navbar-nav navbar-dark navbar-right sbm-burger">
<li class="dropdown-toggle caret-off">
<a href="#" class="dropdown" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false"><span class="navbar-toggler-icon"></span></a>
<ul class="dropdown-menu dropdown-menu-right sbm-dropdown-menu">@* Menu items will be inserted here. *@</ul>
</li>
</ul>
</div>
</div>
</div>
@* Filter Panel *@
<div class="sbm-panel-filter">
<div class="row">
<div class="col-sm-4 row pb4">
@* Commodity filter - code, description etc *@
<div class="col-4 col-sm-4 sbm-label text-left text-sm-right">@Localiser["label.search"]</div>
<div class="col-7 col-sm-8">
@Html.TextBox("Filter.Search", "", new { @id = "", @class = "FilterCommodity sbm-input", @maxlength = "32" })
</div>
</div>
<div class="col-sm-4 row pb4">
@* Commodity Category *@
<div class="col-4 col-sm-4 sbm-label text-left text-sm-right">@Localiser["label.type"]</div>
<div class="col-7 col-sm-8">
@Html.DropDownList("Filter.CommodityType", Model.GetCommodityTypeCodesForSelect(), Localiser["label.any"], new { @id = "", @class = "FilterCommodityType sbm-select" })
</div>
</div>
<div class="col-sm-4 row pb4">
</div>
</div>
</div>
}
<partial name="Panel-CommodityList.cshtml" />
</div>
</div>
</div>
<partial name="Panel-CommodityDialog.cshtml" />
@@ -0,0 +1,43 @@
@* View is decoupled from Commodity model as it may be included in other views, eg. Transactions. *@
@model SbmModel_Portal
@inject SbmLocaliser Localiser
@{
/* Commodity select panel */
// Ensure view is only included once in page.
if (!Model.RegisterView("Views/Commodity/Panel-CommoditySelect")) return;
Model.AdditionalFiles_JS.Add("js/sbm-commodity.js");
}
<script type="text/javascript">
</script>
<div id="dlgCommoditySelect" class="sbm-dialog sbm-flex sbm-no-padding" title="@Localiser["caption.contact.select"]">
@using (@Html.BeginForm(FormMethod.Post, new { @id = "", @class = "frmCommodityFilter sbm-form", @onSubmit = "return false;" }))
{
@Html.Hidden("Filter.Mode", Model_Commodity.CommodityViewMode.Search, new { @id = "" })
@* Filter Panel *@
<div class="sbm-panel-filter">
<div class="row">
<div class="col-sm-4 row pb4">
@* Commodity type *@
<div class="col-4 col-sm-4 sbm-label text-left text-sm-right">@Localiser["label.type"]</div>
<div class="col-8 col-sm-8">
@Html.DropDownList("Filter.CommodityType", Model.GetAffiliateTypeCodesForFilterSelect(), Localiser["label.any"], new { @id = "", @class = "FilterCommodityType sbm-select" })
</div>
</div>
<div class="col-sm-4 row pb4">
@* Commodity filter - name etc. *@
<div class="col-4 col-sm-4 sbm-label text-left text-sm-right">@Localiser["label.search"]</div>
<div class="col-8 col-sm-8">
@Html.TextBox("Filter.Search", "", new { @id = "", @class = "FilterSearch sbm-input", @maxlength = "32" })
</div>
</div>
</div>
</div>
}
<partial name="Panel-CommodityList.cshtml" />
</div>
@@ -1,7 +1,7 @@
@model Model_Contact
@inject SbmLocaliser Localiser
@{
/* Contact page */
/* Contact page. */
ViewData["Title"] = "Contacts";
}
@@ -11,9 +11,10 @@
sbm.dlg.title.createContact = '@Localiser.GetJavascriptText("caption.contact.create")';
sbm.dlg.title.updateContact = '@Localiser.GetJavascriptText("caption.contact.update")';
</script>
@using (@Html.BeginForm(FormMethod.Post, new { @id = "frmContactId", @class = "sbm-form" }))
{
<input type="hidden" name="Contact.Id" class="ContactId" />
@Html.Hidden("Contact.Id", "", new { @id = "", @class = "ContactId" })
}
<div id="dlgContact" class="sbm-dialog" title="">
<div class="spacer2"></div>
@@ -59,7 +60,7 @@
</div>
<div class="col-sm">
<div class="sbm-control">
<input type="text" name="Contact.Abbreviation" id="ifContactAbbreviation" class="ContactAbbreviation sbm-input sbm-auto-val upper" maxlength="@Model.GetControlMaxLength(SbmDbDfn.ColumnIdx.Affiliate_Abbrev)" />
@Html.TextBox("Contact.Abbreviation", "", new { @id = "ifContactAbbreviation", @class = "ContactAbbreviation sbm-input sbm-auto-val upper", @maxlength = @Model.GetControlMaxLength(SbmDbDfn.ColumnIdx.Affiliate_Abbrev) })
</div>
</div>
</div>
@@ -79,7 +80,7 @@
</div>
<div class="col-sm">
<div class="sbm-control">
<input type="text" name="Contact.Name" id="ifContactName" class="ContactName sbm-input sbm-auto-val" maxlength="@Model.GetControlMaxLength(SbmDbDfn.ColumnIdx.Affiliate_Name)" />
@Html.TextBox("Contact.Name", "", new { @id = "ifContactName", @class = "ContactName sbm-input sbm-auto-val", @maxlength = @Model.GetControlMaxLength(SbmDbDfn.ColumnIdx.Affiliate_Name) })
</div>
</div>
</div>
@@ -99,7 +100,7 @@
</div>
<div class="col-sm">
<div class="sbm-control">
<input type="text" name="Contact.Nature" id="ifContactNature" class="ContactNature sbm-input sbm-auto-val" maxlength="@Model.GetControlMaxLength(SbmDbDfn.ColumnIdx.Affiliate_Nature)" />
@Html.TextBox("Contact.Nature", "", new { @id = "ifContactNature", @class = "ContactNature sbm-input sbm-auto-val", @maxlength = @Model.GetControlMaxLength(SbmDbDfn.ColumnIdx.Affiliate_Nature) })
</div>
</div>
</div>
@@ -120,7 +121,7 @@
</div>
<div class="col-sm">
<div class="sbm-control">
<input type="text" name="Contact.Contact" id="ifContactContact" class="ContactContact sbm-input sbm-auto-val" maxlength="@Model.GetControlMaxLength(SbmDbDfn.ColumnIdx.Affiliate_Contact)" />
@Html.TextBox("Contact.Contact", "", new { @id = "ifContactContact", @class = "ContactContact sbm-input sbm-auto-val", @maxlength = @Model.GetControlMaxLength(SbmDbDfn.ColumnIdx.Affiliate_Contact) })
</div>
</div>
</div>
@@ -169,7 +170,7 @@
</div>
<div class="col-sm">
<div class="sbm-control">
<input type="text" name="Contact.Salutation" id="ifContactSalutation" class="ContactSalutation sbm-input sbm-auto-val" maxlength="@Model.GetControlMaxLength(SbmDbDfn.ColumnIdx.Affiliate_Salutation)" />
@Html.TextBox("Contact.Salutation", "", new { @id = "ifContactSalutation", @class = "ContactSalutation sbm-input sbm-auto-val", @maxlength = @Model.GetControlMaxLength(SbmDbDfn.ColumnIdx.Affiliate_Salutation) })
</div>
</div>
</div>
@@ -192,7 +193,7 @@
</div>
<div class="col-sm">
<div class="sbm-control">
<input type="text" name="Contact.FirstName" id="ifContactFirstName" class="ContactFirstName sbm-input sbm-auto-val" maxlength="@Model.GetControlMaxLength(SbmDbDfn.ColumnIdx.Affiliate_FirstName)" />
@Html.TextBox("Contact.FirstName", "", new { @id = "ifContactFirstName", @class = "ContactFirstName sbm-input sbm-auto-val", @maxlength = @Model.GetControlMaxLength(SbmDbDfn.ColumnIdx.Affiliate_FirstName) })
</div>
</div>
</div>
@@ -213,7 +214,7 @@
</div>
<div class="col-sm">
<div class="sbm-control">
<input type="text" name="Contact.Initials" id="ifContactInitials" class="ContactInitials sbm-input sbm-auto-val" maxlength="@Model.GetControlMaxLength(SbmDbDfn.ColumnIdx.Affiliate_Initials)" />
@Html.TextBox("Contact.Initials", "", new { @id = "ifContactInitials", @class = "ContactInitials sbm-input sbm-auto-val", @maxlength = @Model.GetControlMaxLength(SbmDbDfn.ColumnIdx.Affiliate_Initials) })
</div>
</div>
</div>
@@ -233,7 +234,7 @@
</div>
<div class="col-sm">
<div class="sbm-control">
<input type="text" name="Contact.LastName" id="ifContactLastName" class="ContactLastName sbm-input sbm-auto-val" maxlength="@Model.GetControlMaxLength(SbmDbDfn.ColumnIdx.Affiliate_LastName)" />
@Html.TextBox("Contact.LastName", "", new { @id = "ifContactLastName", @class = "ContactLastName sbm-input sbm-auto-val", @maxlength = @Model.GetControlMaxLength(SbmDbDfn.ColumnIdx.Affiliate_LastName) })
</div>
</div>
</div>
@@ -253,7 +254,7 @@
</div>
<div class="col-sm">
<div class="sbm-control">
<input type="text" name="Contact.PhoneMain" id="ifContactPhoneMain" class="ContactPhoneMain sbm-input sbm-auto-val" maxlength="@Model.GetControlMaxLength(SbmDbDfn.ColumnIdx.Affiliate_PhoneMain)" />
@Html.TextBox("Contact.PhoneMain", "", new { @id = "ifContactPhoneMain", @class = "ContactPhoneMain sbm-input sbm-auto-val", @maxlength = @Model.GetControlMaxLength(SbmDbDfn.ColumnIdx.Affiliate_PhoneMain) })
</div>
</div>
</div>
@@ -274,7 +275,7 @@
</div>
<div class="col-sm">
<div class="sbm-control">
<input type="text" name="Contact.PhoneAlt" id="ifContactPhoneAlt" class="ContactPhoneAlt sbm-input sbm-auto-val" maxlength="@Model.GetControlMaxLength(SbmDbDfn.ColumnIdx.Affiliate_PhoneAlt)" />
@Html.TextBox("Contact.PhoneAlt", "", new { @id = "ifContactPhoneAlt", @class = "ContactPhoneAlt sbm-input sbm-auto-val", @maxlength = @Model.GetControlMaxLength(SbmDbDfn.ColumnIdx.Affiliate_PhoneAlt) })
</div>
</div>
</div>
@@ -291,7 +292,7 @@
</div>
<div class="col-sm">
<div class="sbm-control">
<input type="text" name="Contact.PhoneMobile" id="ifContactPhoneMobile" class="ContactPhoneMobile sbm-input sbm-auto-val" maxlength="@Model.GetControlMaxLength(SbmDbDfn.ColumnIdx.Affiliate_PhoneMobile)" />
@Html.TextBox("Contact.PhoneMobile", "", new { @id = "ifContactPhoneMobile", @class = "ContactPhoneMobile sbm-input sbm-auto-val", @maxlength = @Model.GetControlMaxLength(SbmDbDfn.ColumnIdx.Affiliate_PhoneMobile) })
</div>
</div>
</div>
@@ -314,7 +315,7 @@
</div>
<div class="col-sm">
<div class="sbm-control">
<input type="text" name="Contact.PhoneDirect" id="ifContactPhoneDirect" class="ContactPhoneDirect sbm-input sbm-auto-val" maxlength="@Model.GetControlMaxLength(SbmDbDfn.ColumnIdx.Affiliate_PhoneDirect)" />
@Html.TextBox("Contact.PhoneDirect", "", new { @id = "ifContactPhoneDirect", @class = "ContactPhoneDirect sbm-input sbm-auto-val", @maxlength = @Model.GetControlMaxLength(SbmDbDfn.ColumnIdx.Affiliate_PhoneDirect) })
</div>
</div>
</div>
@@ -335,7 +336,7 @@
</div>
<div class="col-sm">
<div class="sbm-control">
<input type="text" name="Contact.PhoneFax" id="ifContactPhoneFax" class="ContactPhoneFax sbm-input sbm-auto-val" maxlength="@Model.GetControlMaxLength(SbmDbDfn.ColumnIdx.Affiliate_PhoneFax)" />
@Html.TextBox("Contact.PhoneFax", "", new { @id = "ifContactPhoneFax", @class = "ContactPhoneFax sbm-input sbm-auto-val", @maxlength = @Model.GetControlMaxLength(SbmDbDfn.ColumnIdx.Affiliate_PhoneFax) })
</div>
</div>
</div>
@@ -355,7 +356,7 @@
</div>
<div class="col-sm">
<div class="sbm-control">
<input type="text" name="Contact.Email" id="ifContactEmail" class="ContactEmail sbm-input sbm-auto-val" maxlength="@Model.GetControlMaxLength(SbmDbDfn.ColumnIdx.Affiliate_Email)" />
@Html.TextBox("Contact.Email", "", new { @id = "ifContactEmail", @class = "ContactEmail sbm-input sbm-auto-val", @maxlength = @Model.GetControlMaxLength(SbmDbDfn.ColumnIdx.Affiliate_Email) })
</div>
</div>
</div>
@@ -372,7 +373,7 @@
</div>
<div class="col-sm">
<div class="sbm-control">
<input type="text" name="Contact.Website" id="ifContactWebsite" class="ContactWebsite sbm-input sbm-auto-val" maxlength="@Model.GetControlMaxLength(SbmDbDfn.ColumnIdx.Affiliate_Website)" />
@Html.TextBox("Contact.Website", "", new { @id = "ifContactWebsite", @class = "ContactWebsite sbm-input sbm-auto-val", @maxlength = @Model.GetControlMaxLength(SbmDbDfn.ColumnIdx.Affiliate_Website) })
</div>
</div>
</div>
@@ -392,7 +393,7 @@
</div>
<div class="col-sm">
<div class="sbm-control">
<input type="text" name="Contact.CompanyNo" id="ifContactCompanyNo" class="ContactCompanyNo sbm-input upper sbm-auto-val" maxlength="@Model.GetControlMaxLength(SbmDbDfn.ColumnIdx.Affiliate_CompanyNo)" />
@Html.TextBox("Contact.CompanyNo", "", new { @id = "ifContactCompanyNo", @class = "ContactCompanyNo sbm-input upper sbm-auto-val", @maxlength = @Model.GetControlMaxLength(SbmDbDfn.ColumnIdx.Affiliate_CompanyNo) })
</div>
</div>
</div>
@@ -413,7 +414,7 @@
</div>
<div class="col-sm">
<div class="sbm-control">
<input type="text" name="Contact.VatReg" id="ifContactVatReg" class="ContactVatReg sbm-input upper sbm-auto-val" maxlength="@Model.GetControlMaxLength(SbmDbDfn.ColumnIdx.Affiliate_VatReg)" />
@Html.TextBox("Contact.VatReg", "", new { @id = "ifContactVatReg", @class = "ContactVatReg sbm-input upper sbm-auto-val", @maxlength = @Model.GetControlMaxLength(SbmDbDfn.ColumnIdx.Affiliate_VatReg) })
</div>
</div>
</div>
@@ -3,7 +3,7 @@
@inject SbmLocaliser Localiser
@{
/* Contact list panel */
/* NB Can potentially appear more than once on a page? */
/* NB Can potentially appear more than once on a page. */
}
<script type="text/javascript">
@@ -21,8 +21,8 @@
<th class="@Model_Contact.GetFieldName(Model_Contact.ItemField.Phone) width10pc d-none d-sm-table-cell">@Localiser["label.phone"]</th>
<th class="@Model_Contact.GetFieldName(Model_Contact.ItemField.Notes) width25pc d-none d-md-table-cell">@Localiser["label.notes"]</th>
<th class="@Model_Contact.GetFieldName(Model_Contact.ItemField.Associations) width10pc center">@Localiser["label.associations"]</th>
<th class="@Model_Contact.GetFieldName(Model_Contact.ItemField.Status) width10pc center">@Localiser["label.status"]</th>
<th class="@Model_Contact.GetFieldName(Model_Contact.ItemField.Actions) right" style="width:2%;"></th>
<th class="@Model_Contact.GetFieldName(Model_Contact.ItemField.Status) width5pc center">@Localiser["label.status"]</th>
<th class="@Model_Contact.GetFieldName(Model_Contact.ItemField.Actions) width5pc right" style="width:2%;"></th>
</tr>
<tr><td colspan="6"><div class="sbm-panel-messages"></div></td></tr>
</thead>
@@ -21,6 +21,8 @@
@* Filter form - wrap header to include paging controls. *@
@using (@Html.BeginForm(FormMethod.Post, new { @id = "", @class = "frmContactFilter sbm-form", @onSubmit = "return false;" }))
{
@Html.Hidden("Filter.Mode", Model_Contact.ContactViewMode.Maintain, new { @id = "" })
@* Header - Page caption, paging controls, actions. *@
<div class="sbm-panel-header">
<div class="row">
@@ -45,20 +47,14 @@
@* Contact type *@
<div class="col-4 col-sm-4 sbm-label text-left text-sm-right">@Localiser["label.type"]</div>
<div class="col-7 col-sm-8">
<select name="Filter.ContactType" id="" class="FilterContactType sbm-select">
<option value="">@Localiser["label.any"]</option>
@foreach (var type in Model.GetAffiliateTypeCodesForFilterSelect())
{
<option value="@type.Value">@type.Text</option>
}
</select>
@Html.DropDownList("Filter.ContactType", Model.GetAffiliateTypeCodesForFilterSelect(), Localiser["label.any"], new { @id = "", @class = "FilterContactType sbm-select" })
</div>
</div>
<div class="col-sm-4 row pb4">
@* Contact filter - name etc. *@
<div class="col-4 col-sm-4 sbm-label text-left text-sm-right">@Localiser["label.search"]</div>
<div class="col-7 col-sm-8">
<input type="text" name="Filter.Search" id="" class="FilterSearch sbm-input" maxlength="32" />
@Html.TextBox("Filter.Search", "", new { @id = "", @class = "FilterSearch sbm-input", @maxlength = "32" })
</div>
</div>
</div>
@@ -15,7 +15,7 @@
@using (@Html.BeginForm(FormMethod.Post, new { @id = "", @class = "frmContactFilter sbm-form", @onSubmit = "return false;" }))
{
<input type="hidden" name="Filter.Mode" value="Search" />
@Html.Hidden("Filter.Mode", Model_Contact.ContactViewMode.Search, new { @id = "" })
@* Filter Panel *@
<div class="sbm-panel-filter">
@@ -24,20 +24,14 @@
@* Contact type *@
<div class="col-4 col-sm-4 sbm-label text-left text-sm-right">@Localiser["label.type"]</div>
<div class="col-8 col-sm-8">
<select name="Filter.ContactType" id="" class="FilterContactType sbm-select">
<option value="">@Localiser["label.any"]</option>
@foreach (var type in Model.GetAffiliateTypeCodesForFilterSelect())
{
<option value="@type.Value">@type.Text</option>
}
</select>
@Html.DropDownList("Filter.ContactType", Model.GetAffiliateTypeCodesForFilterSelect(), Localiser["label.any"], new { @id = "", @class = "FilterContactType sbm-select" })
</div>
</div>
<div class="col-sm-4 row pb4">
@* Contact filter - name etc. *@
<div class="col-4 col-sm-4 sbm-label text-left text-sm-right">@Localiser["label.search"]</div>
<div class="col-8 col-sm-8">
<input type="text" name="Filter.Search" id="" class="FilterSearch sbm-input" maxlength="32" />
@Html.TextBox("Filter.Search", "", new { @id = "", @class = "FilterSearch sbm-input", @maxlength = "32" })
</div>
</div>
</div>
@@ -16,6 +16,7 @@
--color-DarkBlue: #00008B;
--color-Indigo: #4b0082;
--color-Iris: #5d3fd3;
--color-Burgundy: #800020;
--color-BrightPurple: #bf40bf;
--color-DarkPink: #aa336a;
}
@@ -19,6 +19,11 @@
--color-panel-data: var(--color-Iris);
}
.Commodities .sbm-panel-data
{
--color-panel-data: var(--color-Burgundy);
}
.sbm-panel-data
{
margin: 6px auto;
@@ -137,7 +142,7 @@
.sbm-panel-data .sbm-panel-header .sbm-results-paging .sbm-action
{
margin: 0px 1px;
padding:0;
padding: 0;
background-color: #e0e0e0;
opacity: 50%;
box-shadow: 0 0 0 1px #40404080 inset;
@@ -101,8 +101,8 @@ body > .container, header > .container, footer > .container
.navbar a.navbar-brand
{
padding-top:0.3rem;
padding-bottom:0.1rem;
padding-top: 0.3rem;
padding-bottom: 0.1rem;
white-space: normal;
text-align: center;
word-break: break-all;
@@ -351,6 +351,11 @@ a:focus
--color-dialog: var(--color-Iris);
}
.ui-dialog.sbm-Commodity
{
--color-dialog: var(--color-Burgundy);
}
.sbm-dialog
{
display: none;
@@ -144,7 +144,7 @@
env.$ctrl.targetActions.filter('.AssocTargetSearch').show();
$ctrls.filter('.AssociationTarget').off('dblclick').on('dblclick', function () { as.selectTarget(env); });
$ctrls.filter('.AssociationStatus').val(env.data.defaultStatusCode);
as.openEditDlg(env, cfg, title);
as.openItemDlg(env, cfg, title);
}
as.clearItem = function (env, cfg)
{
@@ -154,7 +154,7 @@
env.$ctrl.targetActions.hide();
sbm.populateSelectCodeDesc('#cbAssociationStatus', env.data.statuses);
}
as.openEditDlg = function (env, cfg, title)
as.openItemDlg = function (env, cfg, title)
{
sbm.configureItemControls(cfg, env.$frm.item);
let $ctrls = $('.sbm-input,.sbm-textarea,.sbm-select', env.$frm.item);
@@ -222,7 +222,7 @@
env.$ctrl.targetActions.filter('.AssocTargetEdit').show();
$ctrls.filter('.AssociationTarget').off('dblclick').on('dblclick', function () { as.editTarget(env); });
sbm.selectOrAdd($ctrls.filter('.AssociationStatus'), item.statusCode, item.statusDesc)
as.openEditDlg(env, cfg, cfg.title || sbm.dlg.title.updateAssociation);
as.openItemDlg(env, cfg, cfg.title || sbm.dlg.title.updateAssociation);
}
//--------------------------------------------------------------
@@ -237,17 +237,22 @@
sbm.refreshControlValues(response.controlValues);
if (!response.success) return;
env.$dlg.item.dialog('close');
env.$pnl.msgs.hide().empty();
var item = response.association;
var $item = $('#' + as.getItemId(item), env.$pnl.table);
if (!$item.length)
if (env.prmEdit)
{
$item = as.getItemTemplate(env);
$('table tbody', env.$pnl.table).prepend($item).show();
as.onItemEdited(env, item);
}
else if (env.$pnl.table.length)
{
env.$pnl.msgs.hide().empty();
var $item = $('#' + as.getItemId(item), env.$pnl.table);
if (!$item.length)
{
$item = as.getItemTemplate(env);
$('table tbody', env.$pnl.table).prepend($item).show();
}
as.populateItem(env, $item, item);
}
let cfg = response.config || {};
as.populateItem(env, $item, item);
}
//--------------------------------------------------------------
@@ -5,72 +5,94 @@
(function (win, doc, undef)
{
"use strict";
let co = sbm.Commodities = { data: {}, ajax: {} };
let $pnl = co.$pnl = {}, $frm = co.$frm = {}, $dlg = co.$dlg = {};
let co = sbm.mdl.Commodities = { env: {} };
//--------------------------------------------------------------
co.refreshResults = function (delay)
co.refreshConfig = function (env, delay)
{
if (!sbm.awaitingRefreshResponse)
{
$pnl.bgr.invisible();
$pnl.table.find('tbody tr').remove();
$pnl.msgs.hide().empty().append($('<div class="sbm-message">' + sbm.msg.dataQuerying + '</div>')).fadeIn(200);
}
co.ajax.refreshResults = co.ajax.refreshResults || { url: sbm.url.base + 'Commodity/Ajax/List', formId: $frm.filter.prop('id'), callbackFn: co.doRefreshResults };
sbm.doAjaxRequest(co.ajax.refreshResults, delay || 50);
sbm.awaitingRefreshResponse = true;
env.ajax.refreshConfig = env.ajax.refreshConfig || { url: sbm.url.base + 'Commodity/Ajax/Config', formSel: env.$frm.filter, callbackFn: function (response) { co.doRefreshConfig(env, response); } };
sbm.doAjaxRequest(env.ajax.refreshConfig, delay || 50);
}
co.doRefreshResults = function (response)
co.doRefreshConfig = function (env, response)
{
//sbm.debug('doRefreshResults', response);
delete sbm.awaitingRefreshResponse;
$pnl.msgs.hide().empty();
let $table = $('table', $pnl.table).find('tbody tr').remove().end();
sbm.refreshPaging(response, '#frmCommodityFilter', co.refreshResults);
//sbm.debug('doRefreshConfig', env, response);
if (!response.success) return;
// Config.
env.mode = response.mode;
env.config = response.config;
env.configCmd = response.configCmd;
env.data.commodityTypes = response.commodityTypes;
env.data.statuses = response.statuses;
env.data.defaultStatusCode = response.defaultStatusCode;
}
// Reference data.
if (response.defaultStatusCode) sbm.data.defaultStatusCode = response.defaultStatusCode;
if (response.statuses) sbm.data.statuses = response.statuses;
//--------------------------------------------------------------
co.refreshResults = function (env, delay)
{
if (!co.awaitingRefreshResponse)
{
env.$pnl.bgr.invisible();
env.$pnl.table.find('tbody tr').remove();
env.$pnl.msgs.hide().empty().append($('<div class="sbm-message">' + sbm.msg.dataQuerying + '</div>')).fadeIn(200);
}
env.ajax.refreshResults = env.ajax.refreshResults || { url: sbm.url.base + 'Commodity/Ajax/List', formSel: env.$frm.filter, callbackFn: function (response) { co.doRefreshResults(env, response); } };
sbm.doAjaxRequest(env.ajax.refreshResults, delay || 50);
co.awaitingRefreshResponse = true;
}
co.doRefreshResults = function (env, response)
{
//sbm.debug('doRefreshResults', env, response);
delete co.awaitingRefreshResponse;
env.$pnl.msgs.hide().empty();
let $table = $('table', env.$pnl.table).find('tbody tr').remove().end();
sbm.refreshPaging(response, env.$frm.filter, function () { co.refreshResults(env); });
if (!response.success) return;
co.doRefreshConfig(env, response);
// Menu.
$pnl.bgr.invisible();
$pnl.mnu.empty();
$pnl.mnu.append(co.getFilterMenuOption(sbm.lbl.refresh, function () { co.refreshResults(); }, 'sbm-refresh'));
$pnl.mnu.append(co.getFilterMenuOption(sbm.lbl.create, function () { co.createItem(); }, 'sbm-add'));
$pnl.bgr.toggleVisibility(!!$('.sbm-dropdown-item', $pnl.mnu).length);
if (env.$pnl.bgr.length)
{
env.$pnl.bgr.invisible();
env.$pnl.mnu.empty();
env.$pnl.mnu.append(co.getFilterMenuOption(env, sbm.lbl.refresh, function () { co.refreshResults(env); }, 'sbm-refresh'));
env.$pnl.mnu.append(co.getFilterMenuOption(env, sbm.lbl.create, function () { co.createItem(env, env.configCmd); }, 'sbm-add'));
env.$pnl.bgr.toggleVisibility(!!$('.sbm-dropdown-item', env.$pnl.mnu).length);
}
// Items.
var items = response.commodities || [];
if (!items.length)
return $pnl.msgs.append($('<div class="sbm-message">' + sbm.msg.dataNoneFound + '</div>')).fadeIn(500);
return env.$pnl.msgs.append($('<div class="sbm-message">' + sbm.msg.dataNoneFound + '</div>')).fadeIn(500);
for (let itemIdx = 0; itemIdx < items.length; itemIdx++)
$table.append(co.populateItem(co.getItemTemplate(), items[itemIdx]));
$table.append(co.populateItem(env, co.getItemTemplate(env), items[itemIdx]));
}
co.populateItem = function ($item, item)
co.populateItem = function (env, $item, item)
{
if (!item) return;
$pnl.msgs.hide().empty();
$item.prop('id', co.getItemId(item));
$('.CommodityType', $item).text(item.typeDesc);
$('.CommodityCode', $item).text(item.code);
$('.CommodityDesc', $item).text(item.desc);
$('.CommoditySalesPrice', $item).text(item.salesPriceFmt);
$('.CommoditySalesUnits', $item).text(item.salesUnit);
$('.CommodityNotes', $item).text(item.notes);
$('.CommodityStatusDesc', $item).text(item.statusDesc).removeStatusClasses().addClass('sbm-status-' + item.statusCode.toLowerCase());
// Actions.
var $bgr = $('.sbm-burger', $item).hide();
let $mnu = $('ul.sbm-dropdown-menu', $bgr).empty();
if (!item.deleted)
let cfg = env.config;
if (cfg) sbm.populateItemValues(cfg, $item, item.field.value);
if (!env.mode.search)
{
let fnUpd = function () { co.updateItem(item) };
$mnu.append(co.getItemMenuOption(sbm.lbl.edit, fnUpd, 'sbm-edit'));
$('.CommodityCode,.CommodityDesc', $item).off('click').on('click', fnUpd).addClass('sbm-action-text');
$item.off('dblclick').on('dblclick', fnUpd);
let prefix = cfg.column.prefix;
$('.' + prefix + 'Status', $item).text(item.statusDesc).removeStatusClasses().addClass('sbm-status-' + item.statusCode.toLowerCase());
// Actions.
var $bgr = $('.sbm-burger', $item).hide();
let $mnu = $('ul.sbm-dropdown-menu', $bgr).empty();
if (!item.deleted)
{
let fnUpd = function () { co.updateItem(env, item.id) };
$mnu.append(co.getItemMenuOption(env, sbm.lbl.edit, fnUpd, 'sbm-edit'));
$('.CommodityCode,.CommodityDesc', $item).off('click').on('click', fnUpd).addClass('sbm-action-text');
$item.off('dblclick').on('dblclick', fnUpd);
}
$bgr.toggle(!!$('.sbm-dropdown-item', $mnu).length);
}
else
{
$item.off('click').on('click', function () { co.selectItemRow(env, $item, item); });
$item.off('dblclick').on('dblclick', function () { co.selectItem(env); });
}
$bgr.toggle(!!$('.sbm-dropdown-item', $mnu).length);
return $item;
}
co.getItemId = function (item)
@@ -79,27 +101,27 @@
}
//--------------------------------------------------------------
co.getFilterDropdownTemplate = function ()
co.getFilterDropdownTemplate = function (env)
{
return $('.sbm-dropdown-menu.CommodityList li.sbm-dropdown-item', $pnl.tmpls).clone();
return $('.sbm-dropdown-menu.CommodityList li.sbm-dropdown-item', env.$pnl.tmpls).clone();
}
co.getItemTemplate = function ()
co.getItemTemplate = function (env)
{
return $('table tr.sbm-row-item.Commodity', $pnl.tmpls).clone();
return $('table tr.sbm-row-item.Commodity', env.$pnl.tmpls).clone();
}
co.getItemDropdownTemplate = function ()
co.getItemDropdownTemplate = function (env)
{
return $('.sbm-dropdown-menu.Commodity li.sbm-dropdown-item', $pnl.tmpls).clone();
return $('.sbm-dropdown-menu.Commodity li.sbm-dropdown-item', env.$pnl.tmpls).clone();
}
//--------------------------------------------------------------
co.getFilterMenuOption = function (lbl, fn, cls)
co.getFilterMenuOption = function (env, lbl, fn, cls)
{
return co.getMenuOption(co.getFilterDropdownTemplate(), lbl, fn, cls);
return co.getMenuOption(co.getFilterDropdownTemplate(env), lbl, fn, cls);
}
co.getItemMenuOption = function (lbl, fn, cls)
co.getItemMenuOption = function (env, lbl, fn, cls)
{
return co.getMenuOption(co.getItemDropdownTemplate(), lbl, fn, cls);
return co.getMenuOption(co.getItemDropdownTemplate(env), lbl, fn, cls);
}
co.getMenuOption = function ($opt, lbl, fn, cls)
{
@@ -107,98 +129,168 @@
}
//--------------------------------------------------------------
co.createItem = function ()
co.createItem = function (env, cfg)
{
co.clearItem();
let frm = $frm.item;
$('.CommodityStatus', frm).val(sbm.data.defaultStatusCode);
sbm.clearControlErrors();
$dlg.item.dialog('option', 'title', sbm.dlg.title.createCommodity).prop('readonly', false);
co.openItemDlg();
co.clearItem(env, cfg);
let $frm = env.$frm.item;
$('.CommodityStatus', $frm).val(env.data.defaultStatusCode);
co.openItemDlg(env, cfg, sbm.dlg.title.createCommodity);
}
co.clearItem = function ()
co.clearItem = function (env, cfg)
{
sbm.clearControlErrors($frm.item);
$('.sbm-input,.sbm-textarea,.sbm-select', $frm.item).val('');
sbm.populateSelectCodeDesc('#cbCommodityStatus', sbm.data.statuses);
sbm.clearItemForm(env.$frm.item);
sbm.populateSelectCodeDesc('#cbCommodityStatus', env.data.statuses);
}
co.openItemDlg = function ()
co.openItemDlg = function (env, cfg, title)
{
sbm.openDialog($dlg.item, 600, 640);
let $dlg = env.$dlg.item;
let $frm = env.$frm.item;
sbm.configureItemControls(cfg, $frm);
var btns = {};
btns[sbm.lbl.ok] = function () { co.storeItem(env); };
btns[sbm.lbl.cancel] = function () { delete env.prmEdit; $(this).dialog('close'); };
$dlg.dialog('option', 'buttons', btns);
if (title) $dlg.dialog('option', 'title', title);
sbm.openDialog($dlg, 720, 640);
}
//--------------------------------------------------------------
co.updateItem = function (item)
co.updateItem = function (env, id)
{
$('.CommodityId', $frm.itemId).val(item.id);
co.ajax.updateItem = co.ajax.updateItem || { url: sbm.url.base + 'Commodity/Ajax/GetItem', formId: 'frmCommodityId', callbackFn: co.onUpdateItem };
sbm.doAjaxRequest(co.ajax.updateItem, 50);
let $frm = env.$frm.itemId;
$('.CommodityId', $frm).val(id);
env.ajax.updateItem = env.ajax.updateItem || { url: sbm.url.base + 'Commodity/Ajax/GetItem', formSel: $frm, callbackFn: function (response) { co.onUpdateItem(env, response); } };
sbm.doAjaxRequest(env.ajax.updateItem, 50);
}
co.onUpdateItem = function (response)
co.onUpdateItem = function (env, response)
{
//sbm.debug('onUpdateItem', response);
co.clearItem();
sbm.debug('onUpdateItem', env, response);
if (!response.success) return;
let cfg = response.config || {};
co.clearItem(env, cfg);
let item = response.commodity;
let $ctrls = $('.sbm-input,.sbm-textarea,.sbm-select', $frm.item);
let $frm = env.$frm.item;
sbm.populateFormValues(cfg, $frm, item.field.value);
let $ctrls = $('.sbm-input,.sbm-textarea,.sbm-select', $frm);
$ctrls.filter('.CommodityId').val(item.id);
$ctrls.filter('.CommodityExists').val(1);
$ctrls.filter('.CommodityType').val(item.typeCode);
$ctrls.filter('.CommodityCode').val(item.code);
$ctrls.filter('.CommodityDesc').val(item.desc);
$ctrls.filter('.CommodityNotes').val(item.notes);
sbm.selectOrAdd($ctrls.filter('.CommodityStatus'), item.statusCode, item.statusDesc);
$dlg.item.dialog('option', 'title', sbm.dlg.title.updateCommodity);
co.openItemDlg();
sbm.selectOrAdd($ctrls.filter('.CommodityType'), item.typeCode, item.typeDesc);
sbm.selectOrAdd($ctrls.filter('.CommodityStatus'), item.statusCode, item.field.value.Status);
co.openItemDlg(env, cfg, sbm.dlg.title.updateCommodity);
}
//--------------------------------------------------------------
co.storeItem = function ()
co.storeItem = function (env)
{
co.ajax.storeItem = co.ajax.storeItem || { url: sbm.url.base + 'Commodity/Ajax/StoreItem', formId: 'frmCommodity', callbackFn: co.onStoreItem };
sbm.doAjaxRequest(co.ajax.storeItem, 50);
env.ajax.storeItem = env.ajax.storeItem || {
url: sbm.url.base + 'Commodity/Ajax/StoreItem', formSel: env.$frm.item, callbackFn: function (response) { co.onStoreItem(env, response); } };
sbm.doAjaxRequest(env.ajax.storeItem, 50);
}
co.onStoreItem = function (response)
co.onStoreItem = function (env, response)
{
//sbm.debug('onStoreItem', response);
sbm.debug('onStoreItem', env, response);
sbm.refreshControlValues(response.controlValues);
if (!response.success) return;
$dlg.item.dialog('close');
env.$dlg.item.dialog('close');
var item = response.commodity;
var $item = $('#' + co.getItemId(item), $pnl.table);
if (!$item.length)
if (env.prmEdit)
{
$item = co.getItemTemplate();
$('table tbody', $pnl.table).prepend($item).show();
co.onItemEdited(env, item);
}
co.populateItem($item, item);
else if (env.$pnl.table.length)
{
env.$pnl.msgs.hide().empty();
var $item = $('#' + co.getItemId(item), env.$pnl.table);
if (!$item.length)
{
$item = co.getItemTemplate(env);
$('table tbody', env.$pnl.table).prepend($item).show();
}
co.populateItem(env, $item, item);
}
}
//--------------------------------------------------------------
/* Params: type, search, fnSuccess. */
sbm.fn.selectCommodity = function (prm)
{
//sbm.debug('selectCommodity', prm);
let env = co.env.select;
env.prmSelect = prm;
env.$frm.filter.find('.FilterCommodityType').val('');
env.$frm.filter.find('.FilterSearch').val(prm.search || '');
env.$pnl.table.find('tbody tr').remove();
sbm.openDialog(env.$dlg.select, 1000, 800);
if (env.$pnl.items.length) setTimeout(function () { co.refreshResults(env); }, 250);
}
co.selectItemRow = function (env, $item, item)
{
//sbm.debug('selectItemRow', env, $item, item);
env.$pnl.table.find('tr').removeClass('sbm-sel');
$item.addClass('sbm-sel');
env.prmSelect.item = item;
}
co.selectItem = function (env)
{
//sbm.debug('selectItem', env, env.prmSelect.item);
env.$dlg.select.dialog('close');
env.prmSelect.fnSuccess(env.prmSelect.item);
delete env.prmSelect;
}
/* Params: id, fnSuccess. */
sbm.fn.editCommodity = function (prm)
{
//sbm.debug('editCommodity', prm);
let env = co.env.select;
env.prmEdit = prm;
sbm.debug(env, prm);
co.updateItem(env, prm.id);
}
co.onItemEdited = function (env, item)
{
//sbm.debug('co.onItemEdited', env, item);
env.prmEdit.fnSuccess(item);
delete env.prmEdit;
}
//--------------------------------------------------------------
co.initCommodityEnv = function ($pnlItems)
{
let env = { data: {}, ajax: {}, $pnl: {}, $frm: {}, $ctrl: {}, $dlg: {} };
env.$pnl.items = $($pnlItems);
env.$pnl.header = env.$pnl.items.find('.sbm-panel-header');
env.$pnl.bgr = env.$pnl.header.find('.sbm-burger');
env.$pnl.mnu = env.$pnl.bgr.find('ul.sbm-dropdown-menu');
env.$pnl.table = env.$pnl.items.find('.sbm-panel-item-table');
env.$pnl.msgs = env.$pnl.table.find('.sbm-panel-messages');
env.$pnl.tmpls = env.$pnl.items.find('.sbm-panel-item-template');
env.$frm.filter = $('#frmCommodityFilter');
env.$frm.filter.on('input', '.FilterSearch', function () { co.refreshResults(250); }).on('change', '.FilterCommodityType,.FilterStatusCat', function () { co.refreshResults(50); });
var opt = sbm.dlgOpts();
opt.dialogClass += " sbm-Commodity";
env.$dlg.item = $('#dlgCommodity').dialog(opt);
env.$frm.itemId = $('#frmCommodityId');
env.$frm.item = $('#frmCommodity').on('input', '.sbm-input, .sbm-textarea', function () { sbm.clearControlError(this); }).on('change', '.sbm-select', function () { sbm.clearControlError(this); });
var opt = sbm.dlgOpts();
opt.dialogClass += " sbm-Commodity";
opt.buttons[sbm.lbl.ok] = function () { co.selectItem(env); };
opt.buttons[sbm.lbl.cancel] = function () { delete env.prmSelect; $(this).dialog('close'); };
env.$dlg.select = $('#dlgCommoditySelect').dialog(opt);
return env;
}
//--------------------------------------------------------------
$(function ()
{
$pnl.items = $('.sbm-panel.Commodities');
$pnl.header = $('.sbm-panel-header', $pnl.items);
$pnl.bgr = $('.sbm-burger', $pnl.header);
$pnl.mnu = $('ul.sbm-dropdown-menu', $pnl.bgr);
$pnl.table = $('.sbm-panel-item-table', $pnl.items);
$pnl.msgs = $('.sbm-panel-messages', $pnl.table);
$pnl.tmpls = $('.sbm-panel-item-template', $pnl.items);
$frm.filter = $('#frmCommodityFilter');
$frm.filter.on('input', '.FilterSearch', function () { co.refreshResults(250); }).on('change', '.FilterCommodityType,.FilterStatusCat', function () { co.refreshResults(50); });
$frm.itemId = $('#frmCommodityId');
$frm.item = $('#frmCommodity');
$frm.item.on('input', '.sbm-input, .sbm-textarea', function () { sbm.clearControlError(this); }).on('change', '.sbm-select', function () { sbm.clearControlError(this); });
var opt = sbm.dlgOpts();
opt.buttons[sbm.lbl.ok] = function () { co.storeItem(); };
opt.buttons[sbm.lbl.cancel] = function () { $(this).dialog('close'); };
$dlg.item = $('#dlgCommodity').dialog(opt);
setTimeout(co.refreshResults, 250);
co.env.maint = co.initCommodityEnv('.sbm-panel.Commodities');
if (co.env.maint.$pnl.items.length) setTimeout(function () { co.refreshResults(co.env.maint); }, 250);
co.env.select = co.initCommodityEnv('#dlgCommoditySelect');
if (co.env.select.$pnl.items.length) setTimeout(function () { co.refreshConfig(co.env.select); }, 250);
});
}(window, window.document));
@@ -144,11 +144,10 @@
co.clearItem(env, cfg);
let $ctrls = $('.sbm-input,.sbm-textarea,.sbm-select', env.$frm.item);
$ctrls.filter('.ContactStatus').val(env.data.defaultStatusCode);
co.openEditDlg(env, cfg, title);
co.openItemDlg(env, cfg, title);
}
co.clearItem = function (env, cfg)
{
//sbm.debug('clearItem', env, cfg);
let $frm = env.$frm.item;
sbm.clearItemForm($frm);
if (cfg.isIndividual) $('.ContactIsIndividual', $frm).val(1);
@@ -158,16 +157,17 @@
sbm.populateSelectCodeDesc('#cbContactSalutation', env.data.salutations);
sbm.populateSelectCodeDesc('#cbContactStatus', env.data.statuses);
}
co.openEditDlg = function (env, cfg, title)
co.openItemDlg = function (env, cfg, title)
{
let $dlg = env.$dlg.item;
let $frm = env.$frm.item;
sbm.configureItemControls(cfg, $frm);
var btns = {};
btns[sbm.lbl.ok] = function () { co.storeItem(env); };
btns[sbm.lbl.cancel] = function () { delete env.prmEdit; $(this).dialog('close'); };
env.$dlg.item.dialog('option', 'buttons', btns);
if (title) env.$dlg.item.dialog('option', 'title', title);
sbm.openDialog(env.$dlg.item, 640, 600);
$dlg.dialog('option', 'buttons', btns);
if (title) $dlg.dialog('option', 'title', title);
sbm.openDialog($dlg, 640, 600);
}
//--------------------------------------------------------------
@@ -193,7 +193,7 @@
$ctrls.filter('.ContactType').val(item.typeCode);
$ctrls.filter('.ContactProspect').prop('checked', !!item.prospect);
$ctrls.filter('.ContactStatus').val(item.statusCode);
co.openEditDlg(env, cfg, sbm.dlg.title.updateContact);
co.openItemDlg(env, cfg, sbm.dlg.title.updateContact);
}
//--------------------------------------------------------------
@@ -211,7 +211,7 @@
var item = response.contact;
if (env.prmEdit)
{
co.onContactEdited(env, item);
co.onItemEdited(env, item);
}
else if (env.$pnl.table.length)
{
@@ -271,9 +271,9 @@
sbm.debug(env, prm);
co.updateItem(env, prm.id);
}
co.onContactEdited = function (env, item)
co.onItemEdited = function (env, item)
{
//sbm.debug('onContactEdited', env, item);
//sbm.debug('co.onItemEdited', env, item);
env.prmEdit.fnSuccess(item);
delete env.prmEdit;
}