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 SbmUserContext userContext; private SbmAccountMgr accountMgr; private SbmDataItemMgr dataItemMgr; private SbmStockMgr stockMgr; private SbmTransactionMgr transactionMgr; private SbmAccountsDfn accountDfn = null; private List transactionPayments = new List(); private readonly List transactionTypes; private readonly List transactionStatusCats; private readonly List requirementStatusCats; private readonly List constituentStatusCats; private readonly String statusCancelled = SacsSystem.GetStatusCode(SaStatus.Cancelled); //------------------------------------------------------------------- // Construction. public SbmTransaction_Dbas(SbmUserContext userContext, SysId id, SysId affIdOwner, SysId assocId, Sbm.TransactionType transactionType, ushort flags) : base(userContext, id, affIdOwner, assocId, transactionType) { this.userContext = userContext; transactionTypes = SbmSystem.GetCodesOfType(userContext, Sbm.SystemCode.TransactionType); transactionStatusCats = SbmSystem.GetCodesOfType(userContext, Sbm.SystemCode.TransactionStatusCat); requirementStatusCats = SbmSystem.GetCodesOfType(userContext, Sbm.SystemCode.RequirementStatusCat); constituentStatusCats = SbmSystem.GetCodesOfType(userContext, Sbm.SystemCode.ConstituentStatusCat); Flags = flags; } protected override void Dispose(bool disposing) { if (disposing) { if (accountMgr != null) accountMgr.Dispose(); if (transactionMgr != null) transactionMgr.Dispose(); if (dataItemMgr != null) dataItemMgr.Dispose(); if (accountDfn != null) accountDfn.Dispose(); } 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 (accountDfn == null) accountDfn = new SbmAccountsDfn(userContext); if (accountDfn != null) { if (accountDfn.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, userContext.GetOwnerOption_UpdateLimit(Sbm.OrgOption_PeriodDays.UpdateClosedTransaction, 0)); DateTime closed = Closed; detailsAreReadOnly = (DateUtil.IsValid(closed) && closed <= DateTime.Today.AddDays(-graceDaysUpdateClosedTrans)); } } return detailsAreReadOnly; } //------------------------------------------------------------------- // Internal Processing. public bool InitAccountMgr() { if (accountMgr == null) accountMgr = SbmGlobals.System.CreateAccountMgr(userContext); return (accountMgr != null); } public bool InitDataItemMgr() { if (dataItemMgr == null) dataItemMgr = SbmGlobals.System.CreateDataItemMgr(userContext); return (dataItemMgr != null); } public bool InitStockMgr() { if (stockMgr == null) stockMgr = SbmGlobals.System.CreateStockMgr(userContext); return (stockMgr != null); } public bool InitTransactionMgr() { if (transactionMgr == null) transactionMgr = SbmGlobals.System.CreateTransactionMgr(userContext); return (transactionMgr != null); } //------------------------------------------------------------------- // Associated data. public override bool IsReferencedByOtherTransactions() { ClearErrorState(); InitTransactionMgr(); return 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(); InitTransactionMgr(); return transactionMgr.TransactionHasConstituents(Id, constituentStatusCat); } public override bool HasContainerItems() { ClearErrorState(); InitTransactionMgr(); return transactionMgr.TransactionHasContainerItems(Id); } public override bool HasStockMovements() { ClearErrorState(); InitTransactionMgr(); return transactionMgr.TransactionHasStockMovements(Id); } public override bool HasPendingStockMovements() { ClearErrorState(); InitTransactionMgr(); return 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 = SbmGlobals.Application.GetDatabase(userContext.SessionContext); if (db != null) { List filter = new List(); 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 GetRequirements(SbmRequirement.StatusCat requirementStatusCat = SbmRequirement.StatusCat.Any) { if (SysId.IsValid(Id) && InitTransactionMgr()) { // Retrieve the current set of requirements for this transaction. SbmRequirement.Params prmRequirement = new SbmRequirement.Params(); //prmRequirement.RequirementStatusCat = requirementStatusCat; prmRequirement.TransIncludedIds.Add(Id); return transactionMgr.GetRequirementList(prmRequirement); } return new List(); } public override bool ItemsRequireJobNumber() { // Check whether Job Number should be allocated: SbmConfigConsole configConsole = SbmGlobals.GetConfigConsole(userContext.SessionContext); if (configConsole != null && configConsole.AllowOption(UserContext, Sbm.ConfigOption.SalesOrderItemJobNumber) && SbmGlobals.Application.ColumnExists(userContext.SessionContext, SbmDbDfn.ColumnIdx.Requirement_JobNumber)) return TransactionType == Sbm.TransactionType.SalesOrder; return false; } public override bool UpdateRequirements(List requirements) { if (this == null) return false; ClearErrorState(); SacsDatabase db = SbmGlobals.Application.GetDatabase(userContext.SessionContext) as SacsDatabase; if (db == null) return SetErrorState("Database not available"); if (!SysId.IsValid(Id)) return SetErrorState("transaction does not exist"); if (!InitTransactionMgr()) return SetErrorState("requirement manager is not available"); // 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(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, 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 requirementsNotUpdated = new List(requirements); // Retrieve each of the requirements currently specified for this transaction in turn. List requirementIdsUpdated = new List(); if (!HasErrorState() && InitTransactionMgr()) { List columnsQuery = new List(); String colRequirement_Id = SbmDbDfn.GetColumnName(SbmDbDfn.ColumnIdx.Requirement_Id); SbmRequirement.Params prmRequirement = new SbmRequirement.Params(); prmRequirement.TransIncludedIds.Add(Id); using (DbResultSet dbResultSet = 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 (transactionMgr.UpdateRequirement(requirement, userContext.DbUpdateInfo)) { if (!requirement.CommitAssociatedData()) SetErrorState("Failed to update requirement's data: " + requirement.ErrorState); } else SetErrorState("Failed to update requirement: " + transactionMgr.ErrorState); requirementsNotUpdated.Remove(requirement); } else { // Requirement not in list - remove it. SbmRequirement requirement = transactionMgr.GetRequirement(prmRequirement); if (requirement != null) { if (!transactionMgr.DeleteRequirement(requirement, TransactionType, userContext.DbUpdateInfo)) SetErrorState("Failed to remove requirement: " + transactionMgr.ErrorState); } else SetErrorState("Failed to retrieve requirement for deletion: " + 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 (transactionMgr.InsertRequirement(requirementNotUpdate, userContext.DbUpdateInfo)) { if (!requirementNotUpdate.CommitAssociatedData()) SetErrorState("Failed to update requirement's data: " + requirementNotUpdate.ErrorState); } else SetErrorState("Failed to create requirement: " + 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 = SbmGlobals.Application.GetDatabase(userContext.SessionContext); if (db != null) { if (!HasErrorState()) { // Delete interface data items. SaInterfaceConsole interfaceConsole = SbmGlobals.Application.GetInterfaceConsole(userContext); if (interfaceConsole != null) { if (!interfaceConsole.ClearInterfaceDataItems(new ItemId((short)Sbm.ItemType.Transaction, Id), userContext.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 (InitDataItemMgr()) { if (!dataItemMgr.ClearDataItem(Sbm.ItemType.Transaction, Id)) SetErrorState("failed to clear transaction item links"); } else SetErrorState("failed to initialise data item manager"); } // 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() && InitTransactionMgr()) { List requirements = GetRequirements(); if (requirements != null && requirements.Count > 0) { foreach (SbmRequirement requirement in requirements) { if (!transactionMgr.DeleteRequirement(requirement, TransactionType, userContext.DbUpdateInfo)) SetErrorState(transactionMgr.ErrorState.ToString()); requirements = null; } } if (requirements != null) requirements.Clear(); } // Clear addresses. if (!HasErrorState() && InitAccountMgr()) { if (!accountMgr.ClearAddressesFor(Sbm.ItemType.Transaction, new ItemId())) SetErrorState("failed to clear addresses - " + accountMgr.ErrorState); } // Clear any references to this transaction from other transactions: if (!HasErrorState()) { String filter = SbmDbDfn.GetColumnName(SbmDbDfn.ColumnIdx.Transaction_TransIdSource) + "=" + Id.ToString(); List values = new List(); 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) && InitDataItemMgr() && dataItemMgr != null) { SbmItemLink.Params prmItemLink = new SbmItemLink.Params { ItemLinkType = Sbm.ItemLinkType.Transaction_Payment, ItemTypeFrom = Sbm.ItemType.Transaction, ItemIdFrom = Id }; foreach (SbmItemLink itemLink in dataItemMgr.GetItemLinkList(prmItemLink)) if (itemLink != null) return true; } return false; } public override List GetPayments() { List transactionPaymentsCopy = new List(); if (transactionPayments == null && SysId.IsValid(Id) && InitDataItemMgr() && dataItemMgr != null) { SbmItemLink.Params prm = new SbmItemLink.Params(); prm.ItemLinkType = Sbm.ItemLinkType.Transaction_Payment; prm.ItemTypeFrom = Sbm.ItemType.Transaction; prm.ItemIdFrom = Id; List itemLinks = 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(); transactionPayments.Add(transactionPayment); } // Clean-up. itemLinks.Clear(); } } // Clone the list. transactionPaymentsCopy = transactionPayments.Clone(); transactionPaymentsCopy.Sort(); return transactionPaymentsCopy; } public override bool SetPayments(List 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) && InitDataItemMgr() && dataItemMgr != null) { // Build an item link list corresponding to the list of payment: List itemLinks = new List(); foreach (SbmTransactionPayment transactionPayment in transactionPayments) { if (transactionPayment == null) continue; SbmItemLink itemLink = 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 (dataItemMgr.StoreFromItemLinks(Sbm.ItemLinkType.Transaction_Payment, Sbm.ItemType.Transaction, Id, itemLinks, userContext.DbUpdateInfo)) { } else { SetErrorState("Failed to save transaction payment item links - " + dataItemMgr.ErrorState); } if (itemLinks != null) itemLinks.Clear(); } return false; } } //======================================================================= }