Files
BusinessMgr-2019/SaBusMgrStandardDbas/Dbas/Bus/SbmTransaction_Dbas.cs
T
2021-07-08 20:50:46 +01:00

475 lines
19 KiB
C#

using Sarand.BusinessMgr.Net.Standard.Base.App;
using Sarand.BusinessMgr.Net.Standard.Base.Bus;
using Sarand.BusinessMgr.Net.Standard.Base.Mgr;
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.Interfaces;
using Sarand.Net.Standard.Base.Utils;
using Sarand.Net.Standard.Dbas.Base;
using System;
using System.Collections.Generic;
namespace Sarand.BusinessMgr.Net.Standard.Dbas.Bus
{
//=======================================================================
class SbmTransaction_Dbas : SbmTransaction
{
//-------------------------------------------------------------------
// Data members.
private readonly SbmInternals internals;
private List<SbmTransactionPayment> transactionPayments = new List<SbmTransactionPayment>();
private readonly List<TypeCodeDesc> transactionTypes;
private readonly List<TypeCodeDesc> transactionStatusCats;
private readonly List<TypeCodeDesc> requirementStatusCats;
private readonly List<TypeCodeDesc> constituentStatusCats;
private readonly String statusCancelled = SacsSystem.GetStatusCode(SaStatus.Cancelled);
//-------------------------------------------------------------------
// Construction.
public SbmTransaction_Dbas(SbmInternals internals, SysId id, SysId affIdOwner, SysId assocId, Sbm.TransactionType transactionType, ushort flags) :
base(internals.UserContext, id, affIdOwner, assocId, transactionType)
{
this.internals = internals;
transactionTypes = internals.GetCodesOfType(Sbm.SystemCode.TransactionType);
transactionStatusCats = internals.GetCodesOfType(Sbm.SystemCode.TransactionStatusCat);
requirementStatusCats = internals.GetCodesOfType(Sbm.SystemCode.RequirementStatusCat);
constituentStatusCats = internals.GetCodesOfType(Sbm.SystemCode.ConstituentStatusCat);
Flags = flags;
}
protected override void Dispose(bool disposing)
{
if (disposing)
{
// NB Do not dispose the Internals - owned by manager.
}
base.Dispose(disposing);
}
//-------------------------------------------------------------------
// Properties.
//-------------------------------------------------------------------
// Utilities.
public override bool IsReadOnly()
{
if (!SysId.IsValid(Id)) return false;
bool bReadOnly = false;
// Transaction can't be updated after it has been exporetd to an accounts system.
if (!bReadOnly)
{
if (internals.AccountsDfn.IsTransactionTypeManagedByAccounts(TransactionType))
bReadOnly = true;
}
return bReadOnly;
}
public override bool DetailsAreReadOnly()
{
if (!SysId.IsValid(Id)) return false;
if (IsReadOnly()) return true; // If transaction is read only then details must be.
bool detailsAreReadOnly = false;
// User must be allowed to update transactions:
if (!detailsAreReadOnly)
{
// ToDo UserCanUpdateItemType
/*if (!pSys->UserCanUpdateItemType(eSapItemTypeTransaction))
bDetailsAreReadOnly = true;*/
}
// Closed transactions.
if (!detailsAreReadOnly)
{
if (TransactionStatusCat == SbmTransaction.StatusCat.Closed)
{
// Once the 'grace' period has passed, only the status can be modified.
int graceDaysUpdateClosedTrans = Math.Max(0, internals.UserContext.GetOwnerOption_UpdateLimit(Sbm.OrgOption_PeriodDays.UpdateClosedTransaction, 0));
DateTime closed = Closed;
detailsAreReadOnly = (DateUtil.IsValid(closed) && closed <= DateTime.Today.AddDays(-graceDaysUpdateClosedTrans));
}
}
return detailsAreReadOnly;
}
//-------------------------------------------------------------------
// Associated data.
public override bool IsReferencedByOtherTransactions()
{
ClearErrorState();
return internals.TransactionMgr.TransactionIsReferencedByOtherTransactions(Id);
}
public override bool HasRequirements(SbmRequirement.StatusCat requirementStatusCat = SbmRequirement.StatusCat.NotDeleted)
{
return (GetRequirementCount(requirementStatusCat) > 0);
}
public override bool HasConstituents(SbmConstituent.StatusCat constituentStatusCat = SbmConstituent.StatusCat.NotDeleted)
{
ClearErrorState();
return internals.TransactionMgr.TransactionHasConstituents(Id, constituentStatusCat);
}
public override bool HasContainerItems()
{
ClearErrorState();
return internals.TransactionMgr.TransactionHasContainerItems(Id);
}
public override bool HasStockMovements()
{
ClearErrorState();
return internals.TransactionMgr.TransactionHasStockMovements(Id);
}
public override bool HasPendingStockMovements()
{
ClearErrorState();
return internals.TransactionMgr.TransactionHasPendingStockMovements(Id);
}
public override bool HasDiaryLinks()
{
if (!SysId.IsValid(Id)) return false;
/*SbmDiaryConsole diaryConsole = SbmGlobals.Application.GetDiaryConsole(SessionContext);
if (diaryConsole != null)
diaryConsole.DataItemHasLinks((short)Sbm.ItemType.Transaction, Id);*/
return false;
}
//public override void SetDefaults(class SbmRequirement *) const;
public override long GetRequirementCount(SbmRequirement.StatusCat requirementStatusCat = SbmRequirement.StatusCat.Any)
{
ClearErrorState();
if (!SysId.IsValid(Id)) return 0;
ISacsDatabase db = internals.BusMgrDatabase;
if (db != null)
{
List<String> filter = new List<String>();
filter.Add(SbmDbDfn.GetColumnNameQual(SbmDbDfn.ColumnIdx.Requirement_TransId) + "=" + Id.ToString());
if (requirementStatusCat == SbmRequirement.StatusCat.NotCancelled)
filter.Add(SbmDbDfn.GetColumnNameQual(SbmDbDfn.ColumnIdx.Requirement_Status) + "<>'" + statusCancelled + "'");
else if (requirementStatusCat > 0)
filter.Add(SbmDbDfn.GetColumnNameQual(SbmDbDfn.ColumnIdx.Requirement_StatusCat) + "='" + requirementStatusCats.GetCodeForType(requirementStatusCat) + "'");
return db.GetRowCount(SbmDbDfn.GetTableName(SbmDbDfn.TableIdx.Requirement), filter.Concat(" AND ", "(", ")"));
}
else SetErrorState("database is not available");
return 0;
}
public override List<SbmRequirement> GetRequirements(SbmRequirement.StatusCat requirementStatusCat = SbmRequirement.StatusCat.Any)
{
if (SysId.IsValid(Id))
{
// Retrieve the current set of requirements for this transaction.
SbmRequirement.Params prmRequirement = new SbmRequirement.Params();
//prmRequirement.RequirementStatusCat = requirementStatusCat;
prmRequirement.TransIncludedIds.Add(Id);
return internals.TransactionMgr.GetRequirementList(prmRequirement);
}
return new List<SbmRequirement>();
}
public override bool ItemsRequireJobNumber()
{
// Check whether Job Number should be allocated:
SbmConfigConsole configConsole = internals.ConfigConsole;
if (configConsole != null && configConsole.AllowOption(UserContext, Sbm.ConfigOption.SalesOrderItemJobNumber) && SbmGlobals.Application.BusMgrColumnExists(internals.SessionContext, SbmDbDfn.ColumnIdx.Requirement_JobNumber))
return TransactionType == Sbm.TransactionType.SalesOrder;
return false;
}
public override bool UpdateRequirements(List<SbmRequirement> requirements)
{
if (this == null) return false;
ClearErrorState();
SacsDatabase db = internals.BusMgrDatabase as SacsDatabase;
if (db == null) return SetErrorState("Database not available");
if (!SysId.IsValid(Id)) return SetErrorState("transaction does not exist");
// Verify requirements list.
if (!HasErrorState())
{
// Validate the identity of each each requirement in the list.
foreach (SbmRequirement requirement in requirements)
{
if (requirement == null) continue;
if (SysId.IsValid(requirement.AssociationId) && requirement.AssociationId != AssociationId)
{
SetErrorState("Invalid requirement in list: doesn't belong to association.");
}
else if (SysId.IsValid(requirement.TransactionId) && requirement.TransactionId != Id)
{
SetErrorState("Invalid requirement in list: doesn't belong to transaction.");
}
}
}
// Set identity for each requirements in the list.
if (!HasErrorState())
{
// Set the sequence and identity against each requirement in the list.
for (int requirementIdx = 0; requirementIdx < requirements.Count; requirementIdx++)
{
SbmRequirement requirement = requirements[requirementIdx];
requirement.Seq = (short)(requirementIdx + 1);
requirement.AssociationId = AssociationId;
requirement.TransactionId = Id;
if (ItemsRequireJobNumber() && StringUtil.IsEmpty(requirement.JobNumber))
{
String jobNumberNextIdObject = "JobNumber:" + SysId.ToString(internals.UserContext.Organisation.AffiliateId);
/*
// Check for original Job Number 'NextId' key and convert to organisation specific.
String filter = SbmDbDfn.GetColumnName(SbmDbDfn.ColumnIdx.NextId_Object) + "='JobNumber'";
if (db.GetRowCount(SbmDbDfn.GetTableName(SbmDbDfn.TableIdx.NextId), filter) > 0)
{
String query =
"Begin Transaction;\n" + "Update dbo.NextId Set Object='" + jobNumberNextIdObject + "' Where " + filter + ";\n" + "Commit Transaction;\n";
db.ExecuteQuery(query);
}
*/
String jobNumber = SysId.ToString(db.GetNextId(jobNumberNextIdObject, internals.UserContext.DbUpdateInfo, false));
requirement.JobNumber = "";
}
SetDefaults(requirement);
}
}
// Make a copy of the list (pointers only) to keep track of those requirements in the list that have not been updated against the database.
List<SbmRequirement> requirementsNotUpdated = new List<SbmRequirement>(requirements);
// Retrieve each of the requirements currently specified for this transaction in turn.
List<SysId> requirementIdsUpdated = new List<SysId>();
if (!HasErrorState())
{
List<ColumnDfn> columnsQuery = new List<ColumnDfn>();
String colRequirement_Id = SbmDbDfn.GetColumnName(SbmDbDfn.ColumnIdx.Requirement_Id);
SbmRequirement.Params prmRequirement = new SbmRequirement.Params();
prmRequirement.TransIncludedIds.Add(Id);
using (DbResultSet dbResultSet = internals.TransactionMgr.ExecuteRequirementQuery(columnsQuery, prmRequirement))
{
while (!HasErrorState() && dbResultSet != null && dbResultSet.NextRecord())
{
NamedValue.Map values = dbResultSet.GetRecordValues();
SysId requirementId = new SysId((int)values.GetValue(colRequirement_Id).AsLong());
// Does this requirement exist in the list.
if (requirementsNotUpdated.ExistsById(requirementId))
{
// Requirement still in list - update the details.
SbmRequirement requirement = requirementsNotUpdated[0];
if (internals.TransactionMgr.UpdateRequirement(requirement, internals.DbUpdateInfo))
{
if (!requirement.CommitAssociatedData())
SetErrorState("Failed to update requirement's data: " + requirement.ErrorState);
}
else SetErrorState("Failed to update requirement: " + internals.TransactionMgr.ErrorState);
requirementsNotUpdated.Remove(requirement);
}
else
{
// Requirement not in list - remove it.
SbmRequirement requirement = internals.TransactionMgr.GetRequirement(prmRequirement);
if (requirement != null)
{
if (!internals.TransactionMgr.DeleteRequirement(requirement, TransactionType, internals.DbUpdateInfo))
SetErrorState("Failed to remove requirement: " + internals.TransactionMgr.ErrorState);
}
else SetErrorState("Failed to retrieve requirement for deletion: " + internals.TransactionMgr.ErrorState);
}
}
}
}
// Any requirements left in the 'Not Updated' list must be new.
foreach (SbmRequirement requirementNotUpdate in requirementsNotUpdated)
{
if (requirementNotUpdate != null)
{
if (!SysId.IsValid(requirementNotUpdate.Id))
{
// Requirement does not yet exist - create it:
if (internals.TransactionMgr.InsertRequirement(requirementNotUpdate, internals.DbUpdateInfo))
{
if (!requirementNotUpdate.CommitAssociatedData())
SetErrorState("Failed to update requirement's data: " + requirementNotUpdate.ErrorState);
}
else SetErrorState("Failed to create requirement: " + internals.TransactionMgr.ErrorState);
}
}
else SetErrorState("null item in list");
requirementsNotUpdated = null;
}
// Clean-up:
requirementsNotUpdated.Clear();
return !HasErrorState();
}
public override bool CommitAssociatedData()
{
ClearErrorState();
if (this == null || !SysId.IsValid(Id)) return false;
if (!HasErrorState()) CommitPayments();
return !HasErrorState();
}
public override bool ClearDependentData()
{
ClearErrorState();
if (!SysId.IsValid(Id)) return false;
ISacsDatabase db = internals.BusMgrDatabase;
if (db != null)
{
if (!HasErrorState())
{
// Delete interface data items.
SaInterfaceConsole interfaceConsole = internals.InterfaceConsole;
if (interfaceConsole != null)
{
if (!interfaceConsole.ClearInterfaceDataItems(new ItemId((short)Sbm.ItemType.Transaction, Id), internals.DbUpdateInfo))
SetErrorState("Failed to clear interface data items - " + interfaceConsole.ErrorState);
}
else SetErrorState("Failed to retrieve interface console");
interfaceConsole = null; // Do not delete this global object.
}
if (!HasErrorState())
{
/* ToDo itemDocConsole > Remove document references.
SaItemDocConsole itemDocConsole = SbmGlobals.Application.GetItemDocConsole(SessionContext);
if (itemDocConsole != null)
{
if (!itemDocConsole.ClearItemDocs(Sbm.ItemType.Transaction, Id))
SetErrorState(itemDocConsole.ErrorState());
}
else SetErrorState("Failed to retrieve item document console");
itemDocConsole = null; // Do not delete this global object.*/
}
// Delete any associated items links.
if (!HasErrorState())
{
if (!internals.DataItemMgr.ClearDataItem(Sbm.ItemType.Transaction, Id))
SetErrorState("failed to clear transaction item links");
}
// Delete any constituents that belong to this Transaction.
if (!HasErrorState())
{
String filter = SbmDbDfn.GetColumnName(SbmDbDfn.ColumnIdx.Constituent_TransId) + "=" + Id.ToString();
if (db.ExecuteDelete(SbmDbDfn.GetTableName(SbmDbDfn.TableIdx.Constituent), filter) > 0)
SetErrorState("failed to clear Transaction constituents");
}
// Clear requirements.
if (!HasErrorState())
{
List<SbmRequirement> requirements = GetRequirements();
if (requirements != null && requirements.Count > 0)
{
foreach (SbmRequirement requirement in requirements)
{
if (!internals.TransactionMgr.DeleteRequirement(requirement, TransactionType, internals.DbUpdateInfo))
SetErrorState(internals.TransactionMgr.ErrorState.ToString());
requirements = null;
}
}
if (requirements != null) requirements.Clear();
}
// Clear addresses.
if (!HasErrorState())
{
if (!internals.AccountMgr.ClearAddressesFor(Sbm.ItemType.Transaction, new ItemId()))
SetErrorState("failed to clear addresses - " + internals.AccountMgr.ErrorState);
}
// Clear any references to this transaction from other transactions:
if (!HasErrorState())
{
String filter = SbmDbDfn.GetColumnName(SbmDbDfn.ColumnIdx.Transaction_TransIdSource) + "=" + Id.ToString();
List<StringPair> values = new List<StringPair>();
SacsDatabase.AddValuePair(values, SbmDbDfn.GetColumnName(SbmDbDfn.ColumnIdx.Transaction_TransIdSource), "0", false);
db.ExecuteUpdate(SbmDbDfn.GetTableName(SbmDbDfn.TableIdx.Transaction), values, filter);
SetErrorState("failed to clear Transaction references");
}
}
else SetErrorState("database is unavailable");
return !HasErrorState();
}
public override bool HasPayments()
{
if (transactionPayments != null) return true;
else if (SysId.IsValid(Id))
{
SbmItemLink.Params prmItemLink = new SbmItemLink.Params
{
ItemLinkType = Sbm.ItemLinkType.Transaction_Payment,
ItemTypeFrom = Sbm.ItemType.Transaction,
ItemIdFrom = Id
};
foreach (SbmItemLink itemLink in internals.DataItemMgr.GetItemLinkList(prmItemLink))
if (itemLink != null) return true;
}
return false;
}
public override List<SbmTransactionPayment> GetPayments()
{
List<SbmTransactionPayment> transactionPaymentsCopy = new List<SbmTransactionPayment>();
if (transactionPayments == null && SysId.IsValid(Id))
{
SbmItemLink.Params prm = new SbmItemLink.Params();
prm.ItemLinkType = Sbm.ItemLinkType.Transaction_Payment;
prm.ItemTypeFrom = Sbm.ItemType.Transaction;
prm.ItemIdFrom = Id;
List<SbmItemLink> itemLinks = internals.DataItemMgr.GetItemLinkList(prm);
if (itemLinks != null)
{
foreach (SbmItemLink itemLink in itemLinks)
{
if (itemLink == null) continue;
SbmTransactionPayment transactionPayment = new SbmTransactionPayment(UserContext, itemLink.DataContent);
transactionPayment.Notes = itemLink.Notes;
transactionPayment.Changed = false;
if (transactionPayments == null) transactionPayments = new List<SbmTransactionPayment>();
transactionPayments.Add(transactionPayment);
}
// Clean-up.
itemLinks.Clear();
}
}
// Clone the list.
transactionPaymentsCopy = transactionPayments.Clone();
transactionPaymentsCopy.Sort();
return transactionPaymentsCopy;
}
public override bool SetPayments(List<SbmTransactionPayment> transactionPaymentsNew)
{
// Clear the existing list:
if (transactionPayments != null) transactionPayments.Clear();
// Copy all items from the specified list:
transactionPayments = transactionPaymentsNew.Clone();
return true;
}
public override bool CommitPayments()
{
ClearErrorState();
// Do not attempt any updates unless the list has been populated.
if (transactionPayments != null && SysId.IsValid(Id))
{
// Build an item link list corresponding to the list of payment:
List<SbmItemLink> itemLinks = new List<SbmItemLink>();
foreach (SbmTransactionPayment transactionPayment in transactionPayments)
{
if (transactionPayment == null) continue;
SbmItemLink itemLink = internals.DataItemMgr.CreateItemLink(Sbm.ItemLinkType.Transaction_Payment, Sbm.ItemType.Transaction, Id, Sbm.ItemType.Unknown, new SysId(0));
if (itemLink != null)
{
itemLink.Seq = (short)transactionPayment.CodeSeq;
itemLink.DataContent = transactionPayment.ToString();
itemLink.Notes = transactionPayment.Notes;
itemLinks.Add(itemLink);
itemLink = null; // Now owned by the list.
}
}
// Store these details:
if (internals.DataItemMgr.StoreFromItemLinks(Sbm.ItemLinkType.Transaction_Payment, Sbm.ItemType.Transaction, Id, itemLinks, internals.DbUpdateInfo))
{
}
else
{
SetErrorState("Failed to save transaction payment item links - " + internals.DataItemMgr.ErrorState);
}
if (itemLinks != null)
itemLinks.Clear();
}
return false;
}
}
//=======================================================================
}