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 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(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 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)) { // 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(); } public override bool ItemsRequireJobNumber() { // Check whether Job Number should be allocated. SbmConfigConsole configConsole = internals.ConfigConsole; ISacsDatabase db = internals.BusMgrDatabase; if (configConsole != null && configConsole.AllowOption(UserContext, Sbm.ConfigOption.SalesOrderItemJobNumber) && SbmGlobals.Application.DbColumnExists(db, 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 = 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 requirementsNotUpdated = new List(requirements); // Retrieve each of the requirements currently specified for this transaction in turn. List requirementIdsUpdated = new List(); if (!HasErrorState()) { 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 = 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 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 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)) { 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 GetPayments() { List transactionPaymentsCopy = new List(); 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 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(); 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)) { // 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 = 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; } } //======================================================================= }