Accounting Software
Small Business Software Estimating Software
Inventory SoftwareInventory Tracking SoftwareInventory Control SoftwareInventory Management SoftwareConstruction Management SoftwareProject Management SoftwareBusiness Management Software

Base Transactions (Source Code)

Link to: header | transactions directory

Copyright Turtle Creek Software 1996-2006. All Rights Reserved.

Comments

DB_BaseTransaction

This class manages basic accounting transactions in the Goldenseal accounting software,
estimating software, project management software and construction accounting software.

It;s the abstract parent class for transactions and breakdown items. We have a few
basic functions here for tasks that can be handled by either a transaction
or a breakdown entry.

SUPERCLASS = DB_PersistentObject

Constructor

/*********************************************************************************
constructor
*********************************************************************************/
DB_BaseTransaction::DB_BaseTransaction()
:THE_SUPERCLASS()
{
mMainAccountClass = 0;

mJustImported = false;
mBeenPosted = false; // rev TCS 7/19/99
mBeenTandMBilled = mBeenPaid = false;
mBeenRecvBilled = false; // TCS 6/8/00
mBeenDeposited = false;
mIsMarked = false;
mBoolean = false;
mSpareBit = false;
mInstantPayment = false;

mIsInRemoteUse = false;

mTransFiller = 0;

mCurrentUser = 0;

mDisplayingViewer = nil;

mOldCreationType = 0;
mCreationType = 0;

mDBTPadding = 0; // TCS 6/25/03
}

Source Code

/*********************************************************************************

GetFileLength

return the file length to reserve for this object

*********************************************************************************/
NeoSize DB_BaseTransaction::GetFileLength(const CNeoFormat *aFormat) const
{
return THE_SUPERCLASS::GetFileLength(aFormat) +
cFileLength;
}/*********************************************************************************

CopyFrom

copy the data members from the passed object. This is used to implement
duplicate. source should be an object of the same class as this object

*********************************************************************************/
void DB_BaseTransaction::CopyFrom(DB_PersistentObject *source, const UInt8 /*copyFlags*/)
{
// no need to copy the superclass

DB_BaseTransaction *src = TCS_SAFE_CAST(source, DB_BaseTransaction);
TCS_FailNILMsg(src, TCS_GetErrString(errID_BadRecord));
// make sure the source is valid TCS 9/8/02
TCS_BlockMove(&src->mMainAccountClass, &mMainAccountClass, cCopyFileLength);
}/*********************************************************************************

GetMemberValue

return the value of the member with the given tag

*********************************************************************************/
Boolean DB_BaseTransaction::GetMemberValue(const TagType aTag, const TagType aType,
void *aValue) const
{
CDate date;
CMoney amount = 0;

switch (aTag)
{
case tag_mainaccountclass: // subclasses can override to use different menu etc
return ConvertEnumMember(mMainAccountClass, MENU_AccountClasses, aValue, aType); // rev TCS 6/28/01
break;

case tag_justimported:
return ConvertBitFieldMember(mJustImported, aValue, aType);
break;

case tag_paid:
return ConvertBitFieldMember(mBeenPaid, aValue, aType);
break;

case tag_beenbilled:
return ConvertBitFieldMember(mBeenTandMBilled, aValue, aType);
break;

case tag_beenposted:
return ConvertBitFieldMember(mBeenPosted, aValue, aType);
break;

case tag_amount: // default value, subclasses should override
return ConvertMember(&amount, type_money, aValue, aType);
break;

case tag_duedate: // TCS 8/4/99
date = GetDueDate();
return ConvertMember(&date, tag_date, aValue, aType);
break;

case tag_discountdate: // TCS 8/4/99
date = GetDiscountDate();
return ConvertMember(&date, tag_date, aValue, aType);
break;

case tag_billingdate: // TCS 8/4/99
date = GetBillingDate();
return ConvertMember(&date, tag_date, aValue, aType);
break;

case tag_datepaid: // TCS 8/4/99
date = GetDatePaid();
return ConvertMember(&date, tag_date, aValue, aType);
break;

case tag_debitamount: // TCS 12/29/00
amount = GetDebitAmount();
return ConvertMember(&amount, type_money, aValue, aType);
break;

case tag_creditamount: // TCS 12/29/00
amount = GetCreditAmount();
return ConvertMember(&amount, type_money, aValue, aType);
break;

case tag_incomeamount:
amount = GetIncomeAmount();
return ConvertMember(&amount, type_money, aValue, aType);
break;

case tag_taxamount: // new TCS 2/22/99
{ // this is 'last resort' calculation. As of 1/12/00,
// most or all transactions store tax amount as a member
CMoney amount = GetSalesTaxAmount();
return ConvertMember(&amount, type_money, aValue, aType);
}
break;

case tag_name: // last resort for name TCS 9/9/99
{
CTextString emptyString;
emptyString.MakeNull();
return ConvertMember(&emptyString, type_cstring, aValue, aType);
}
break;

case tag_creationtype: // TCS 6/28/03
{
UInt8 creationType = GetCreationType();
return ConvertEnumMember(creationType, MENU_CreationTypes, aValue, aType);
}
break;

default:
return THE_SUPERCLASS::GetMemberValue(aTag, aType, aValue);
break;
}
}/*********************************************************************************

SetMemberValue

set the value of the member with the given tag

*********************************************************************************/
Boolean DB_BaseTransaction::SetMemberValue(const TagType aTag, const TagType aType,
const void *aValue)
{
switch (aTag)
{
case tag_mainaccountclass:
return ConvertMember(aValue, aType, &mMainAccountClass, type_objclass);
break;

case tag_justimported:
mJustImported = ConvertDataToBitField(aValue, aType);
return true;
break;

case tag_beenbilled:
mBeenTandMBilled = ConvertDataToBitField(aValue, aType);
return true;
break;

case tag_paid:
mBeenPaid = ConvertDataToBitField(aValue, aType);
return true;
break;

case tag_beenposted:
mBeenPosted = ConvertDataToBitField(aValue, aType);
return true;
break;

case tag_debitamount: // calculated, no need to set
case tag_creditamount:
case tag_creationtype:
return true;
break;

case tag_billingdate: // these are usually calculated, no need to set
case tag_datepaid:
case tag_duedate:
case tag_discountdate:
return true;
break;

case tag_name: // many transactions don't store a name. If we
return true; // got this far, we'll just skip gracefully. TCS 5/26/00
break;

default:
return THE_SUPERCLASS::SetMemberValue(aTag, aType, aValue);
break;
}
}/*********************************************************************************

ReadObject

read the persistent object's data in from a stream
*********************************************************************************/
void DB_BaseTransaction::ReadObject(CNeoStream *aStream, const TagType aTag)
{
TCS_FailNILMsg(aStream, TCS_GetErrString(errID_BadStream));

CNeoDebugImport checker(aStream, this); // TCS 2/24/00

THE_SUPERCLASS::ReadObject(aStream, aTag);

/// aStream->ReadChunk(&mMainAccountClass, cFileLength);

mMainAccountClass = aStream->ReadChar(); // mfs_sa rev 20feb2k3
mCreationType = aStream->ReadChar();

// copy the bitfields MFS 6/10/03, rev TCS 6/28/03 bugfix 7/9/03
*(UInt8*)((UInt8*)&mCreationType + sizeof(mCreationType)) = aStream->ReadBits(8);
*(UInt8*)((UInt8*)&mCreationType + sizeof(mCreationType) + 1) = aStream->ReadBits(5);
if (HasBytesReversed()) // TCS 6/27/03
mOldCreationType = TCS_ReverseBits(mOldCreationType, 3);
}
/*********************************************************************************

WriteObject

write the persistent object's data to a stream
*********************************************************************************/
void DB_BaseTransaction::WriteObject(CNeoStream *aStream, const TagType aTag)
{
TCS_FailNILMsg(aStream, TCS_GetErrString(errID_BadStream));

CNeoDebugExport checker(aStream, this);

// write superclass data. NeoAccess uses 2 bytes of flags
// and 4 bytes with the object version number. It also now
// starts with a 4 byte safety tag TCS rev 9/13/02
THE_SUPERCLASS::WriteObject(aStream, aTag);

/// aStream->WriteChunk(&mMainAccountClass, cFileLength);

aStream->WriteChar(mMainAccountClass); // mfs_sa rev 20feb2k3
aStream->WriteChar(mCreationType);

// copy the bitfields MFS 6/10/03, rev TCS 6/28/03 bugfix 7/9/03
aStream->WriteChar(*(UInt8*)((UInt8*)&mCreationType + sizeof(mCreationType)));
aStream->WriteChar(*(UInt8*)((UInt8*)&mCreationType + sizeof(mCreationType) + 1));
}
#if CAN_USE_MARK
#pragma mark -
#endif
/*********************************************************************************

PrepareImportChange TCS 5/20/02 moved TCS 12/26/02

post an import action for an existing item that will be changed
*********************************************************************************/
void DB_BaseTransaction::PrepareImportChange()
{
PostRecordChanging(true, true);
}
/*********************************************************************************

PostImportChange TCS 5/20/02 moved TCS 12/26/02

post an import action for an existing item that was just changed
*********************************************************************************/
void DB_BaseTransaction::PostImportChange(const CMoney oldAmount)
{
PostRecordChanged(oldAmount, true, true);
}
#if CAN_USE_MARK
#pragma mark -
#endif
/*********************************************************************************

GetCreationType TCS 6/28/03

get the way this transaction was created. We have to futz since there have been
two systems for storing this.
*********************************************************************************/
UInt8 DB_BaseTransaction::GetCreationType() const
{
if (mCreationType)
{
return mCreationType;
}
else switch (mOldCreationType)
{
case record_oldvsnduplicate:
return record_duplicate;
break;

case record_oldvsnfromtemplate:
return record_fromtemplate;
break;

case record_oldvsnfromafw:
return record_fromafw;
break;

case record_oldvsnfromimport:
return record_fromimport;
break;

case record_oldvsnfromprocess:
return record_fromprocess;
break;

case record_oldvsnautotransfer:
return record_autotransfer;
break;

default:
return record_new;
break;
}
}
/*********************************************************************************

GetAmountPaid

get the amount paid on this transaction. Subclasses may override.

Note that it is possible that the amount paid will be greater than the
transaction amount(if an over-payment was made).
*********************************************************************************/
CMoney DB_BaseTransaction::GetAmountPaid() const
{
if (mBeenPaid)
return GetAmount();
else
return 0;
}
/*********************************************************************************

GetBilledAmount

get the amount billed. Subclasses may override
*********************************************************************************/
CMoney DB_BaseTransaction::GetBilledAmount(const Boolean /*includeTax*/) const
{
if (IsMarked())
return GetAmount();
else
return 0;
}
#if CAN_USE_MARK
#pragma mark -
#endif
/*********************************************************************************

SetStatus TCS 1/12/99

set the value of the status member. For some values, we also set flag bits

*********************************************************************************/
void DB_BaseTransaction::SetStatus(const UInt8 inValue)
{
SetMemberValue(tag_status, type_enum, &inValue);

switch (inValue)
{
//case status_Billed:
case status_TandMBilled:
mBeenTandMBilled = true;
break;

case status_ReceivableBilled:
mBeenRecvBilled = true;
break;

case status_Paid:
mBeenPaid = true;
break;

case status_Deposited:
mBeenDeposited = true;
break;

default:
break;
}

MakeDirty(); // added TCS 4/11/99
}
/******************************************************************************

setDirty TCS 5/29/00

We override here simply so it's easier to set breakpoints

*******************************************************************************/
void DB_BaseTransaction::setDirty(const NeoDirty aReason)
{
THE_SUPERCLASS::setDirty(aReason);
}
/*********************************************************************************

SetMainAccountClass

set the dest account to the given account ID
*********************************************************************************/
void DB_BaseTransaction::SetMainAccountClass(const DBClass inClass)
{
mMainAccountClass = inClass;
}
#if CAN_USE_MARK
#pragma mark -
#endif
/*********************************************************************************

FetchJobCostItemInfo TCS 9/11/98 moved 7/19/99

add job cost data to a category/location item
*********************************************************************************/
Boolean DB_BaseTransaction::FetchJobCostItemInfo(TJobCostItemArray &itemArray,
CTextString &catName,
const UInt8 costType)
{
if (GetJobCostClass() != costType && costType != costtype_all) // TCS 8/10/02
return true;

TCS_TRY
{
SJobCostItemInfo itemInfo;
itemInfo.id = GetDBID();
TCS_BufferFromText(itemInfo.category, catName);
TCS_BufferFromText(itemInfo.item, GetName());
TCS_BufferFromText(itemInfo.supplier, GetMainAccountName());
itemInfo.type = GetJobCostClass();
itemInfo.date = GetDate();

itemInfo.costAmount = GetJobCostAmount();

if (HasBeenTandMBilled()) // rev TCS 5/19/00
itemInfo.billedAmount = GetTandMAmount(true, false); // rev TCS 5/24/00
else
itemInfo.billedAmount = 0;

// we don't include overpayments rev TCS 5/2/00
itemInfo.paidAmount = TCS_MIN(GetAmount(), GetAmountPaid());
return (itemArray.Append(itemInfo) != LArray::index_Bad);
}
TCS_CATCH
{
}
return false;
}
/*********************************************************************************

FillJobCostCatInfo TCS 9/11/98 moved and rev 5/4/00

fill in a job cost category item
*********************************************************************************/
Boolean DB_BaseTransaction::FillJobCostCatInfo(SJobCostCategoryInfo &costInfo,
const CMoney &amount, const DBClass transactionClass,
const UInt8 costType)
{
// sanity check and initialize
TCS_FailNILMsg(costInfo.itemArray, TCS_GetErrString(errID_BadArray));

SObjectInfo itemInfo;
itemInfo.itemID = GetDBID();
itemInfo.classID = GetDBClassID();
itemInfo.transactionType = 0;

// add this transaction to the cat array
costInfo.itemArray->Append(itemInfo);

// add transaction totals to the basic cost info struct
switch (transactionClass)
{
case id_EquipmentHours:
costInfo.equipmentAmount += amount;
break;

case id_LaborHours:
costInfo.laborAmount += amount;
break;

case id_MaterialPurchase:
case id_InventoryUsed:
costInfo.materialAmount += amount;
break;

case id_SubcontractorLog:
costInfo.subcontractorAmount += amount;
break;

case id_OtherCost:
costInfo.otherAmount += amount;
break;

case id_ChangeOrder:
costInfo.changeAmount += amount;
break;

default:
{
switch (costType)
{
case costtype_equipment:
costInfo.equipmentAmount += amount;
break;

case costtype_labor:
case costtype_assmlabor:
costInfo.laborAmount += amount;
break;

case costtype_material:
case costtype_assembly:
case costtype_assmmaterial:
costInfo.materialAmount += amount;
break;

case costtype_subcontractor:
costInfo.subcontractorAmount += amount;
break;

case costtype_other:
costInfo.otherAmount += amount;
break;

case costtype_income: // restored TCS 4/16/01
costInfo.incomeAmount += amount;
break;

default:
break;
}
}
}

return true;
}
/*********************************************************************************

FillJobCostCompareInfo TCS 8/6/01

fill in a job cost comparison item
*********************************************************************************/
Boolean DB_BaseTransaction::FillJobCostCompareInfo(SJobCostCompareInfo &compareInfo,
const CMoney &amount, const DBClass transactionClass,
const UInt8 costType, const Boolean isEstimate)
{
// add transaction totals to the basic cost info struct
switch (transactionClass)
{
case id_EquipmentHours:
compareInfo.actualEquipment += amount;
break;

case id_LaborHours:
compareInfo.actualLabor += amount;
break;

case id_MaterialPurchase:
case id_InventoryUsed:
compareInfo.actualMaterials += amount;
break;

case id_SubcontractorLog:
compareInfo.actualSubcontractors += amount;
break;

case id_OtherCost:
compareInfo.actualOther += amount;
break;

default:
{
switch (costType)
{
case costtype_equipment:
if (isEstimate)
compareInfo.estEquipment += amount;
else
compareInfo.actualEquipment += amount;
break;

case costtype_labor:
if (isEstimate)
compareInfo.estLabor += amount;
else
compareInfo.actualLabor += amount;
break;

case costtype_material:
if (isEstimate)
compareInfo.estMaterials += amount; // bugfix TCS 1/7/03
else
compareInfo.actualMaterials += amount; // bugfix TCS 1/7/03
break;

case costtype_subcontractor:
if (isEstimate)
compareInfo.estSubcontractors += amount;
else
compareInfo.actualSubcontractors += amount;
break;

case costtype_other:
if (isEstimate)
compareInfo.estOther += amount;
else
compareInfo.actualOther += amount;
break;

default:
if (isEstimate)
compareInfo.estSoft += amount;
else
compareInfo.actualSoft += amount;
break;
}
}
}

if (compareInfo.itemArray && !isEstimate) // TCS 1/29/02
{
SObjectInfo info;
info.classID = GetDBClassID();
info.itemID = GetDBID();
info.transactionType = 0;

compareInfo.itemArray->Append(info);
}

return true;
}
/*********************************************************************************

FillCatSubcatInfo TCS 7/10/02

fill this item into a two-level array of category and subcategory
*********************************************************************************/
void DB_BaseTransaction::FillCatSubcatInfo(TTwoLevelArray *twoLevelArray,
const DBid catID, const DBid subcatID,
const Boolean isCredit) const
{
// start with the index at the default (last item)
SInt32 index = twoLevelArray->GetCount();
SInt32 subcatIndex = 1;

// we should have at least one category in the array
TCS_ASSERTMsg(index, "Oops, no categories in DB_BaseTransaction::FillCatSubcatInfo!");
STwoLevelInfo topLevelInfo;

// fetch the posting category
DBid refID = GetCategory();
if (!refID && GetDBClassID() != id_CostTransfer)
refID = catID;

if (refID)
{
TTwoLevelArrayIterator iter (*twoLevelArray);

while (iter.Next(topLevelInfo))
{
if (topLevelInfo.itemID == refID)
{
index = iter.GetCurrentIndex();
break;
}
}
}

// fetch the top level info
twoLevelArray->FetchItemAt(index, topLevelInfo);
TCS_FailNILMsg(topLevelInfo.groupArray, TCS_GetErrString(errID_BadArray));
// look for the subcategory
refID = GetSubcategory();
if (!refID && GetDBClassID() != id_CostTransfer)
refID = subcatID;

SReportGroupInfo groupInfo;

subcatIndex = topLevelInfo.groupArray->GetCount();
TCS_ASSERTMsg(subcatIndex, "Oops, no subcats in DB_BaseTransaction::FillCatSubcatInfo!");

TReportGroupArrayIterator iter (*topLevelInfo.groupArray);

while (iter.Next(groupInfo))
{
if (groupInfo.itemID == refID)
{
subcatIndex = iter.GetCurrentIndex();
break;
}
}

// fetch the subcat struct
topLevelInfo.groupArray->FetchItemAt(subcatIndex, groupInfo);
TCS_FailNILMsg(groupInfo.itemArray, TCS_GetErrString(errID_BadArray));

// fill in data for this item
SObjectInfo info;
info.itemID = GetDBID();
info.classID = GetDBClassID();
if (isCredit)
info.transactionType = condition_Credit;
else
info.transactionType = 0;

// add to the array
groupInfo.itemArray->Append(info);

topLevelInfo.hasItems = true;
twoLevelArray->AssignItemAt(index, topLevelInfo);
}
/*********************************************************************************

FillCatItemInfo TCS 1/25/03

fill this item into an array of categories and items
*********************************************************************************/
void DB_BaseTransaction::FillCatItemInfo(TReportGroupArray *catArray,
const DBid catID, const Boolean isCredit,
const Boolean isLocation) const
{
// start with the index at the default (last item)
SInt32 index = catArray->GetCount();

// we should have at least one category in the array
TCS_ASSERTMsg(index, "Oops, no categories in DB_BaseTransaction::FillCatItemInfo!");
SReportGroupInfo catInfo;

// fetch the posting category
DBid refID = 0;

if (isLocation) // TCS 3/10/03
refID = GetLocation();
else
refID = GetCategory();

if (!refID && GetDBClassID() != id_CostTransfer)
refID = catID;

if (refID)
{
TReportGroupArrayIterator iter (*catArray);

while (iter.Next(catInfo))
{
if (catInfo.itemID == refID)
{
index = iter.GetCurrentIndex();
break;
}
}
}

// fetch the category struct
catArray->FetchItemAt(index, catInfo);
TCS_FailNILMsg(catInfo.itemArray, TCS_GetErrString(errID_BadArray));

// fill in data for this item
SObjectInfo info;
info.itemID = GetDBID();
info.classID = GetDBClassID();
if (isCredit)
info.transactionType = condition_Credit;
else
info.transactionType = 0;

// add to the array
catInfo.itemArray->Append(info);
}
/*********************************************************************************

FillDataReport TCS 9/4/02

fill in a diagnostic table that shows data field values.

*********************************************************************************/
void DB_BaseTransaction::FillDataReport(CTCS_Table *table, CNeoStream *stream) const
{
TCS_FailNILMsg(table, TCS_GetErrString(errID_BadTable));
TCS_FailNILMsg(stream, TCS_GetErrString(errID_BadStream));

THE_SUPERCLASS::FillDataReport(table, stream);

FillFieldEnumRow(table, stream, tag_mainaccountclass, mMainAccountClass, MENU_AccountClasses);
FillFieldEnumRow(table, stream, tag_creationtype, mCreationType, MENU_CreationTypes);
FillFieldBitRow(table, stream, "mJustImported", mJustImported, true);
FillFieldBitRow(table, stream, "mBeenPosted", mBeenPosted);
FillFieldBitRow(table, stream, "mBeenTandMBilled", mBeenTandMBilled);
FillFieldBitRow(table, stream, "mBeenRecvBilled", mBeenRecvBilled);
FillFieldBitRow(table, stream, "mBeenPaid", mBeenPaid);
FillFieldBitRow(table, stream, "mBeenDeposited", mBeenDeposited);
FillFieldBitRow(table, stream, "mSpareBit", mSpareBit);
FillFieldBitRow(table, stream, "mIsMarked", mIsMarked);
FillFieldBitRow(table, stream, "mBoolean", mBoolean, true);
FillFieldBitRow(table, stream, "mInstantPayment", mInstantPayment);
FillFieldTableRow(table, stream, "mOldCreationType", -3, SInt32(mOldCreationType));
FillFieldStockRow(table, stream, stockID_Padding, -3, SInt32(mTransFiller));
}