475 lines
19 KiB
C#
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;
|
|
}
|
|
|
|
}
|
|
//=======================================================================
|
|
}
|