Link to: header |
source 1 | source 2 | source
3 | transactions
directory
Copyright Turtle Creek Software 1996-2006. All Rights Reserved.
Comments
CExpenseTransaction
This class manages expense transactions for the Goldenseal accounting software,
small business management software, construction
project management software and
construction
accounting software.
This is the parent transaction class for bids, time logs, purchases, purchase/work orders.
This class is used for all expenses that might appear in accounts payable, job
costs or time & materials billing.
The subclasses of Expense Transactions are entered in large quantities-- they
are an important part of the Goldenseal job costing software and accounting software.
SUPERCLASS = CJobCostTransaction
Constructor
/*********************************************************************************
constructor
*********************************************************************************/
CExpenseTransaction::CExpenseTransaction()
{
mExpenseAccount = GetDefaultExpenseAccount();
mAdjustmentAmount = 0;
mAmountBilled = 0;
mAmountPaid = 0;
mCheckbookNumber = 0;
mTransactionRef = 0;
mExpenseExpansion = 0;
}
Source Code
/*********************************************************************************
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 CExpenseTransaction::CopyFrom(DB_PersistentObject *source, const UInt8 copyFlags)
{
THE_SUPERCLASS::CopyFrom(source, copyFlags);
CExpenseTransaction *src = TCS_SAFE_CAST(source, CExpenseTransaction);
TCS_FailNILMsg(src, TCS_GetErrString(errID_BadRecord));
TCS_BlockMove(&src->mExpenseAccount, &mExpenseAccount, cCopyFileLength);
}/*********************************************************************************
GetFileLength
return the file length used by this object
*********************************************************************************/
NeoSize CExpenseTransaction::GetFileLength(const CNeoFormat *aFormat) const
{
return THE_SUPERCLASS::GetFileLength(aFormat) + cFileLength;
}/*********************************************************************************
GetMemberValue
return the value of the member with the given tag
*********************************************************************************/
Boolean CExpenseTransaction::GetMemberValue(const TagType aTag, const TagType aType,
void *aValue) const
{
TCS_FailNILMsg(gDBFile, TCS_GetErrString(errID_BadFile));
CDate date;
CMoney amount = 0;
switch (aTag)
{
case tag_expenseaccount:
return ConvertObjectIDMember(mExpenseAccount, id_UtilityAccount, aValue, aType);
break;
// tag_conditions is handled in subclasses
/*case tag_details:
return ConvertMember(&mDetails, type_cstring, aValue, aType);
break;*/
case tag_transactionref: // TCS 1/12/00 moved 1/17/00
{
UInt8 refClass = GetTransactionRefClass(); // rev TCS 11/20/03
if (refClass)
return ConvertObjectIDMember(mTransactionRef, refClass, aValue, aType);
else
return ConvertMember(&mTransactionRef, type_objectid, aValue, aType);
}
break;
case tag_adjustment:
return ConvertMember(&mAdjustmentAmount, type_money, aValue, aType);
break;
case tag_over30:
date = gDBFile->GetStartDate();
if (GetDaysOverdue(date))
amount = GetAmountDue();
return ConvertMember(&amount, type_money, aValue, aType);
break;
case tag_over60:
date = gDBFile->GetStartDate();
if (GetDaysOverdue(date) > 30) // rev TCS 9/14/00
amount = GetAmountDue();
return ConvertMember(&amount, type_money, aValue, aType);
break;
case tag_over90:
date = gDBFile->GetStartDate();
if (GetDaysOverdue(date) > 60) // rev TCS 9/14/00
amount = GetAmountDue();
return ConvertMember(&amount, type_money, aValue, aType);
break;
case tag_duedate: // TCS 4/23/01
date = GetDueDate();
return ConvertMember(&date, type_date, aValue, aType);
break;
case tag_timeused: // TCS 2/4/03
amount = 1;
return ConvertMember(&amount, type_number, aValue, aType);
break;
case tag_tandmperunit: // TCS 2/4/03
amount = GetTandMAmount();
return ConvertMember(&amount, type_money, aValue, aType);
break;
default:
break;
}
return THE_SUPERCLASS::GetMemberValue(aTag, aType, aValue);
}
/*********************************************************************************
SetMemberValue
set the value of the member with the given tag
*********************************************************************************/
Boolean CExpenseTransaction::SetMemberValue(const TagType aTag, const TagType aType,
const void *aValue)
{
switch (aTag)
{
case tag_expenseaccount:
return ConvertDataToObjectID(aValue, aType, &mExpenseAccount, id_UtilityAccount);
break;
case tag_transactionref:
return ConvertMember(aValue, aType, &mTransactionRef, type_objectid);
break;
/*case tag_details:
return SafeConvertString(aValue, aType, &mDetails);
break;*/
case tag_adjustment:
return ConvertMember(aValue, aType, &mAdjustmentAmount, type_money);
break;
case tag_mainaccountclass: // this should never be set from outside- all have fixed class
return true; // TCS 2/10/00
break;
case tag_over30: // calculated, no need to set
case tag_over60:
case tag_over90:
case tag_duedate:
return true;
break;
default:
return THE_SUPERCLASS::SetMemberValue(aTag, aType, aValue);
break;
}
}/*********************************************************************************
ReadObject
read the persistent object's data in from a stream
*********************************************************************************/
void CExpenseTransaction::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);
if (!IsIOValid()) // TCS 2/5/02
return;
/// aStream->ReadChunk(&mExpenseAccount, cFileLength);
mExpenseAccount = aStream->ReadID(); // mfs_sa rev 20feb2k3
mTransactionRef = aStream->ReadID();
mAmountBilled.ReadFromStream(aStream);
mAmountPaid.ReadFromStream(aStream);
mAdjustmentAmount.ReadFromStream(aStream);
mExpenseExpansion = aStream->ReadID();
}/*********************************************************************************
WriteObject
write the persistent object's data to a stream
*********************************************************************************/
void CExpenseTransaction::WriteObject(CNeoStream *aStream, const TagType aTag)
{
TCS_FailNILMsg(aStream, TCS_GetErrString(errID_BadStream));
CNeoDebugExport checker(aStream, this);
THE_SUPERCLASS::WriteObject(aStream, aTag);
/// aStream->WriteChunk(&mExpenseAccount, cFileLength);
aStream->WriteID(mExpenseAccount); // mfs_sa rev 20feb2k3
aStream->WriteID(mTransactionRef);
mAmountBilled.WriteToStream(aStream);
mAmountPaid.WriteToStream(aStream);
mAdjustmentAmount.WriteToStream(aStream);
aStream->WriteID(mExpenseExpansion);
}
#if CAN_USE_MARK
#pragma mark -
#endif
/*********************************************************************************
FinishImportCreate TCS 12/7/00
fill in values after creation from an import. We wipe out paid and billed
status values, since they will be updated during posting of the actual
transactions
Users probably won't ever have a wrong status, but we definitely need this to
help tidy up our sample data!
*********************************************************************************/
void CExpenseTransaction::FinishImportCreate()
{
// let the superclass do its stuff
THE_SUPERCLASS::FinishImportCreate();
UInt8 status = GetStatus();
if (status == status_Paid || status == status_PartPaid || status == status_TandMBilled ||
status == status_BilledAndPaid)
{
SetToStarterStatus();
}
// we need to erase the adjusted amount, since it will be
// reset by subsequent posting. TCS 1/7/02
SetAdjustmentAmount(0);
}
/*********************************************************************************
CanImportEnum TCS 3/7/02
is the given imported value OK? We override to accept mainaccountclass
since it's a fixed value
*********************************************************************************/
Boolean CExpenseTransaction::CanImportEnum(const TagType tag, const SInt32 value) const
{
if (tag == tag_mainaccountclass)
{
// we don't have menu enum info, so we just accept any value
return true;
}
else
return THE_SUPERCLASS::CanImportEnum(tag, value);
}
#if CAN_USE_MARK
#pragma mark -
#endif
/*********************************************************************************
PostNewRecord TCS 11/20/03
post info for a new record. Note that most new record posting happens in
PostRecordActivated.
*********************************************************************************/
void CExpenseTransaction::PostNewRecord(const UInt8 creationType)
{
PostUseCount(id_UtilityAccount, mExpenseAccount);
// let the superclass do any posting
THE_SUPERCLASS::PostNewRecord(creationType);
}
/*********************************************************************************
PostDeletion TCS 11/20/03
post info from a deleted record . Note that most deletion posting happens in
PostRecordCancelled.
*********************************************************************************/
void CExpenseTransaction::PostDeletion(const Boolean postAudit)
{
PostUseCount(id_UtilityAccount, mExpenseAccount, cRemoveItem);
// let the superclass do any posting
THE_SUPERCLASS::PostDeletion(postAudit);
}
/*********************************************************************************
PostRecordActivated TCS moved and rev 7/19/99
post info from a newly created or activated transaction record
*********************************************************************************/
void CExpenseTransaction::PostRecordActivated(const UInt8 creationType)
{
// update account balances. Note that we post all
// expenses, whether billed or cash. For an instant purchase
// the bank payment will reduce the amount in the account
CMoney amountUnpaid = GetAmount() - GetAmountPaid(); // rev TCS 1/25/03
AdjustMainAccount(amountUnpaid);
// post job costs
//if (creationType != record_jobcosttoactive) // rev TCS 12/17/99 removed TCS 1/25/01
// we always add- if going job cost to active
// it was subtracted in PostVoidRecordChanging
AdjustJobCosts(GetJobCostAmount(), cAdjustArrays);
// post to expense account TCS 9/5/99
PostExpenseAccount();
// post to allowances etc TCS 1/18/00
AdjustExpenseTransaction();
// subclasses handle creation of offset transactions, since they are not used
// for labor or equipment hours
// let the superclass do any posting
THE_SUPERCLASS::PostRecordActivated(creationType);
}
/*********************************************************************************
PostNewVoidRecord TCS 2/11/00
a void transaction was created. If it was 'job cost only' we still need
to do some posting
*********************************************************************************/
void CExpenseTransaction::PostNewVoidRecord(const UInt8 creationType)
{
if (GetStatus() == status_JobCostOnly)
{
AdjustJobCosts(GetJobCostAmount(), cAdjustArrays);
AdjustMainAccount(0, cDontRemoveItem, true); // TCS 5/17/04
}
THE_SUPERCLASS::PostNewVoidRecord(creationType);
}
/*********************************************************************************
PostRecordCancelled TCS moved and rev 7/19/99
post info from a deleted or voided transaction record
*********************************************************************************/
void CExpenseTransaction::PostRecordCancelled(const UInt8 cancelType)
{
// update account balances
AdjustMainAccount(-GetAmountUnpaid(), cRemoveItem);
// cancel job costs
//if (cancelType != record_activetojobcost) // rev TCS 12/17/99 removed TCS 1/25/01
// we always subtract- if going active to job cost
// it will be added back in PostRecordVoided
AdjustJobCosts(-GetJobCostAmount(), cAdjustArrays, cRemoveItem);
// post to expense account TCS 9/5/99 rev TCS 4/3/01
PostExpenseAccount(cRemoveItem);
// post to allowances etc TCS 1/18/00
AdjustExpenseTransaction(cRemoveItem);
// let the superclass do any posting
THE_SUPERCLASS::PostRecordCancelled(cancelType);
}
/*********************************************************************************
PostVoidRecordDeleted TCS 5/17/00
a void record was deleted. If it was 'job cost only' we still need to post
*********************************************************************************/
void CExpenseTransaction::PostVoidRecordDeleted()
{
UInt8 status = GetStatus();
if (status == status_JobCostOnly)
{
AdjustJobCosts(-GetJobCostAmount(), cAdjustArrays, cRemoveItem);
AdjustMainAccount(0, cRemoveItem, true); // TCS 5/17/04
}
THE_SUPERCLASS::PostVoidRecordDeleted();
}
/*********************************************************************************
PostRecordChanging TCS 2/8/99 TCS moved and rev 7/19/99
a record will be changing. Post the change.
*********************************************************************************/
void CExpenseTransaction::PostRecordChanging(const Boolean accountChanging, const Boolean jobChanging)
{
AdjustMainAccount(-GetAmountUnpaid(), cRemoveItem); // rev TCS 10/25/00
// unpost job costs rev TCS 7/19/99
if (jobChanging)
AdjustJobCosts(-GetJobCostAmount(), cAdjustArrays, cRemoveItem);
else
AdjustJobCosts(-GetJobCostAmount(), cDontAdjustArrays);
// post to expense account TCS 9/5/99
PostExpenseAccount(cRemoveItem);
// post to allowances etc TCS 1/18/00
AdjustExpenseTransaction(cRemoveItem);
PostUseCount(id_UtilityAccount, mExpenseAccount, cRemoveItem); // TCS 11/20/03
// let the superclass do any posting
THE_SUPERCLASS::PostRecordChanging(accountChanging, jobChanging);
}
/*********************************************************************************
PostVoidRecordChanging TCS 12/17/99
a void record will be changing. Post the change.
*********************************************************************************/
void CExpenseTransaction::PostVoidRecordChanging(const Boolean accountChanging, const Boolean jobChanging,
const UInt8 startingStatus, const UInt8 finalStatus)
{
if (startingStatus == status_JobCostOnly)
{
AdjustJobCosts(-GetJobCostAmount(), cAdjustArrays, cRemoveItem);
AdjustMainAccount(0, cRemoveItem, true); // TCS 5/17/04
}
THE_SUPERCLASS::PostVoidRecordChanging(accountChanging, jobChanging, startingStatus, finalStatus);
}
/*********************************************************************************
PostRecordChanged TCS 2/8/99 TCS moved and rev 7/19/99
a record has changed. Post it.
*********************************************************************************/
void CExpenseTransaction::PostRecordChanged(const CMoney &oldAmount, const Boolean accountChanged,
const Boolean jobChanged)
{
AdjustMainAccount(GetAmountUnpaid()); // rev TCS 10/25/00
// adjust job costs
if (jobChanged)
AdjustJobCosts(GetJobCostAmount(), cAdjustArrays);
else
AdjustJobCosts(GetJobCostAmount(), cDontAdjustArrays);
// post to expense account TCS 9/5/99
PostExpenseAccount();
// post to allowances etc TCS 1/18/00
AdjustExpenseTransaction();
PostUseCount(id_UtilityAccount, mExpenseAccount); // TCS 11/20/03
// subclasses handle change of offset transactions, since they are not used
// for labor or equipment hours
// let the superclass do any posting
THE_SUPERCLASS::PostRecordChanged(oldAmount, accountChanged, jobChanged);
}
/*********************************************************************************
PostVoidRecordChanged TCS 9/24/02
a void record has changed. Post the change.
*********************************************************************************/
void CExpenseTransaction::PostVoidRecordChanged(const CMoney &oldAmount, const Boolean accountChanged,
const Boolean jobChanged)
{
if (GetStatus() == status_JobCostOnly)
{
if (jobChanged)
AdjustJobCosts(GetJobCostAmount(), cAdjustArrays);
else
AdjustJobCosts(GetJobCostAmount(), cDontAdjustArrays);
AdjustMainAccount(0, cDontRemoveItem, true); // TCS 5/17/04
}
THE_SUPERCLASS::PostVoidRecordChanged(oldAmount, accountChanged, jobChanged);
}
/*********************************************************************************
PostRecordVoided TCS 12/17/99
a record has changed from active to inactive status. Post the change.
*********************************************************************************/
void CExpenseTransaction::PostRecordVoided(const Boolean accountChanged, const Boolean jobChanged,
const UInt8 startStatus, const UInt8 finalStatus)
{
if (finalStatus == status_JobCostOnly)
{
AdjustJobCosts(GetJobCostAmount(), cAdjustArrays);
AdjustMainAccount(0, cDontRemoveItem, true); // TCS 5/17/04
}
THE_SUPERCLASS::PostRecordVoided(accountChanged, jobChanged, startStatus, finalStatus);
}
#if CAN_USE_MARK
#pragma mark -
#endif
/*********************************************************************************
IsDue
return whether this cost is due or overdue on the given date
*********************************************************************************/
Boolean CExpenseTransaction::IsDue(const CDate theDate) const
{
return (GetBillingDate() <= theDate);
}
/*********************************************************************************
IsVendorInvoiced TCS 9/1/99 renamed 4/25/01
return whether this transaction was or will be billed
*********************************************************************************/
Boolean CExpenseTransaction::IsVendorInvoiced() const
{
return (GetPaymentType() == method_billed);
}
/*********************************************************************************
HasBeenTandMBilled TCS 10/31/01
return whether this transaction already has been used for T&M billing. We
override to use the status, rather than the flag bit.
*********************************************************************************/
Boolean CExpenseTransaction::HasBeenTandMBilled() const
{
UInt8 status = GetStatus();
return (status == status_TandMBilled || status == status_BilledAndPaid);
}
/*********************************************************************************
HasSpecialStatus TCS 3/25/02
return which status types are considered special
*********************************************************************************/
Boolean CExpenseTransaction::HasSpecialStatus() const
{
return (GetConditions() != condition_None);
}
/*********************************************************************************
CanBeTandMBilled TCS 7/2/01 rev 10/31/01
return whether this transaction should be included in a regular time and
materials billing
*********************************************************************************/
Boolean CExpenseTransaction::CanBeTandMBilled() const
{
if (HasVoidStatus())
return false;
else if (GetConditions() == id_ChangeOrder || GetConditions() == id_Allowance)
return false;
else if (GetStatus() == status_JobCostOnly)
return false;
else if (GetStatus() == status_Planned) // TCS 12/13/02
return false;
else if (HasBeenTandMBilled())
return false;
else if (mCategory)
{
// check if the category allows T&M billing TCS 11/7/02
DB_PersistentObject *category = gDBFile->GetOneObject(id_Category, mCategory);
if (category)
{
DB_ObjectWatcher watcher (category);
return category->CanBeTandMBilled();
}
}
// if we get this far, it's ok to bill
return true;
}
/*********************************************************************************
CanBeJobCosted TCS 7/2/01
return whether this transaction should be included in job cost reports
*********************************************************************************/
Boolean CExpenseTransaction::CanBeJobCosted() const
{
if (GetStatus() == status_PriceUpdateOnly || HasVoidStatus())
return false;
else if (GetConditions() == id_ChangeOrder) // rev TCS 7/30/01
return !GetPrefsBoolean(id_ExpensePrefs, tag_skipchangeorders);
else if (GetConditions() == id_Allowance)
return !GetPrefsBoolean(id_ExpensePrefs, tag_skipallowances);
else
return true;
}
|