Link to: header | source
code | source 2 | source
4 | transactions
directory
Copyright Turtle Creek Software 1996-2006. All Rights Reserved.
Source Code
This class manages basic accounting transactions in the Goldenseal accounting software,
estimating software, project
management software
and construction
accounting software.
/*********************************************************************************
GetNumCosts TCS 11/12/03
get the number of cost transactions of the given type. We fetch it from the main
account. Subclasses should override if they keep a separate list of cost transactions
*********************************************************************************/
SInt32 CTransaction::GetNumCosts(const DBClass inClass) const
{
if (gDBFile && IS_TURTLE_CLASS_ID(mMainAccountClass))
{
DB_PersistentObject *account = gDBFile->GetOneObject(mMainAccountClass,
mMainAccount);
if (account)
{
DB_ObjectWatcher watcher (account);
return account->GetNumCosts(inClass);
}
}
// if we get this far, there are no contacts.
return 0;
}
/*********************************************************************************
GetNumContacts TCS 11/12/03
get the number of contacts of the given type. We fetch it from the main account.
*********************************************************************************/
SInt32 CTransaction::GetNumContacts(const DBClass inClass) const
{
if (gDBFile && IS_TURTLE_CLASS_ID(mMainAccountClass))
{
DB_PersistentObject *account = gDBFile->GetOneObject(mMainAccountClass,
mMainAccount);
if (account)
{
DB_ObjectWatcher watcher (account);
return account->GetNumContacts(inClass);
}
}
// if we get this far, there are no contacts.
return 0;
}
/*********************************************************************************
GetCompanyDivision TCS 4/10/04
return the company division. We use the main account. Subclasses may override.
*********************************************************************************/
DBid CTransaction::GetCompanyDivision() const
{
if (gIsClient)
{
return GetTagID(tag_companydivision);
}
else
{
DBClass accountClass = GetMainAccountClass();
if (IS_TURTLE_CLASS_ID(accountClass))
{
DB_PersistentObject *account = gDBFile->GetOneObject(accountClass, mMainAccount);
if (account)
{
DB_ObjectWatcher watcher(account);
return account->GetCompanyDivision();
}
}
// if we get this far there is no division
return 0;
}
}
/*********************************************************************************
FetchMeetingArray TCS 11/12/03
fetch an array of meeting entries of the given type for the main account
*********************************************************************************/
void CTransaction::FetchMeetingArray(const DBClass inClass, TObjectIDArray &array) const
{
if (gDBFile && IS_TURTLE_CLASS_ID(mMainAccountClass))
{
DB_PersistentObject *account = gDBFile->GetOneObject(mMainAccountClass,
mMainAccount);
if (account)
{
DB_ObjectWatcher watcher (account);
account->FetchMeetingArray(inClass, array);
}
}
}
/*********************************************************************************
FetchCostArray TCS 11/12/03
fetch an array of cost transactions of the given type for the main account
*********************************************************************************/
void CTransaction::FetchCostArray(const DBClass inClass, TObjectIDArray &array) const
{
if (gDBFile && IS_TURTLE_CLASS_ID(mMainAccountClass))
{
DB_PersistentObject *account = gDBFile->GetOneObject(mMainAccountClass,
mMainAccount);
if (account)
{
DB_ObjectWatcher watcher (account);
account->FetchCostArray(inClass, array);
}
}
}
#if CAN_USE_MARK
#pragma mark -
#endif
/*********************************************************************************
GetMessageText TCS 11/13/00
get the text of a message of the given id. The message text is stored in
the message- it's what we want to print on forms.
*********************************************************************************/
CTextString CTransaction::GetMessageText(const DBid messageID) const
{
TCS_FailNILMsg(gDBFile, TCS_GetErrString(errID_BadFile));
// fetch the message text from the given message id
CTextString outMessage;
CMessage *message = TCS_SAFE_CAST(gDBFile->GetOneObject(id_Message, messageID),
CMessage);
if (message)
{
DB_ObjectWatcher watcher(message);
outMessage = message->GetMessageText();
}
else
outMessage.MakeNull();
return outMessage;
}
/*********************************************************************************
GetPaymentTermText TCS 11/13/00
get the text of a payment term. This is what we print on forms, not the name
of the term itself.
*********************************************************************************/
CTextString CTransaction::GetPaymentTermText(const DBClass messageClass,
const DBid messageID) const
{
TCS_FailNILMsg(gDBFile, TCS_GetErrString(errID_BadFile));
// fetch the message text from the given message id
CTextString outMessage;
CPaymentTerm *term = TCS_SAFE_CAST(gDBFile->GetOneObject(messageClass, messageID),
CPaymentTerm);
if (term)
{
DB_ObjectWatcher watcher(term);
outMessage = term->GetMessageText();
}
else
outMessage.MakeNull();
return outMessage;
}
#if CAN_USE_MARK
#pragma mark -
#endif
/*********************************************************************************
CanBeDeleted TCS 4/24/01
ask first before deleting a record used in a template or recurring item
*********************************************************************************/
Boolean CTransaction::CanBeDeleted(const Boolean giveMessage) const
{
if (UsedAsTemplate())
{
if (giveMessage)
return TCS_OKCancelDialog(TCS_GetMsgString(msgID_RUSureDeleteTemplate));
else
return false;
}
else if (UsedAsRecurring())
{
if (giveMessage)
return TCS_OKCancelDialog(TCS_GetMsgString(msgID_RUSureDeleteRecurring));
else
return false;
}
else if (HasLockedStatus()) // TCS 1/29/02
{
if (giveMessage) // TCS bugfix 2/28/02
TCS_ErrorAlert(TCS_GetErrString(errID_CantDeleteTransaction));
return false;
}
else if (HasTransactions()) // TCS 3/28/02
{
if (giveMessage)
TCS_ErrorAlert(TCS_GetErrString(errID_CantDeleteTransaction));
return false;
}
// if we got this far, pass it along for judgement
return THE_SUPERCLASS::CanBeDeleted(giveMessage);
}
/*********************************************************************************
HasLockedStatus
certain status types are 'locked', meaning they cause the status menu and
most other fields to be non-user-accessible.
Note that some subclasses lock the status field but do NOT lock the entire record-
in that case they should return true for HasLockedStatus, but override
HasRecordLock to return false.
For a more general use of the status field, use HasInactiveStatus, HasActiveStatus
or one of the similar methods in DB_PersistentObject. You can also use
HasStatusMatch to match against record ranges in printing or reports, or access
DB_ClassDescriptor::GetStatusClass.
*********************************************************************************/
Boolean CTransaction::HasLockedStatus() const
{
switch (GetStatus())
{
case status_Awarded:
case status_BilledAndPaid:
case status_Collected: // TCS 3/13/02
case status_Completed: // TCS 12/22/00 use status_Finished if not locking
case status_Deposited:
case status_HighBid:
case status_InUse: // TCS 9/10/00
case status_Locked:
case status_LowBid:
case status_Overdue:
case status_Paid:
case status_CommishPaid: // TCS 7/29/02
case status_PartPaid:
case status_PayRecord: // TCS 6/5/00
case status_ReceivableBilled: // removed TCS 3/29/00 returned TCS 10/9/00
case status_Started: // TCS 9/11/00
case status_TandMBilled:
//case status_CarryOver:
return true;
break;
default:
return false;
break;
}
}
/*********************************************************************************
HasPaidCommission TCS 7/29/02
has a commission been paid on this transaction?
*********************************************************************************/
Boolean CTransaction::HasPaidCommission() const
{
CMoney commishPaid = GetCommissionPaid();
return commishPaid.IsNonZero();
}
/*********************************************************************************
HandleReplaceAll TCS 3/1/02
we've been changed by the 'replace all' command.
*********************************************************************************/
void CTransaction::HandleReplaceAll(const TMemberArray &memberArray)
{
TMemberArrayIterator iterator(memberArray);
SMemberInfo memberInfo;
Boolean dateChanged = false;
while (iterator.Next(memberInfo))
{
if (memberInfo.tag == tag_date)
dateChanged = true;
}
if (dateChanged)
HandleDateChanged();
}
#if CAN_USE_MARK
#pragma mark -
#endif
/*********************************************************************************
VerifyImport
return whether a record can be imported
*********************************************************************************/
SInt32 CTransaction::VerifyImport()
{
if (HasVoidStatus()) // TCS 5/1/01
return import_OK;
if (!NeedsMainAccountValue()) // TCS 8/2/01
return import_OK;
if (mMainAccount && IS_TURTLE_CLASS_ID(mMainAccountClass))
{
// we must have a valid main account
TCS_FailNILMsg(gDBFile, TCS_GetErrString(errID_BadFile));
if (gDBFile->ObjectExists(mMainAccountClass, mMainAccount))
return THE_SUPERCLASS::VerifyImport();
else
return import_Fatal;
}
else
return import_Fatal;
}
/*********************************************************************************
SetJustPrinted TCS 11/16/99
this object was just printed. Set the print status
*********************************************************************************/
void CTransaction::SetJustPrinted()
{
// note that we don't update the viewer, so there's no need to
// call PrepareViewerDisplay
// if it's not print flagged, there's no need to update TCS rev 10/24/03
if (!IsPrintFlagged())
return;
// update the transaction object
SetPrintStatus(false);
MakeDirty();
// change print flag in menu list TCS 10/27/00
DB_ListManager::ChangeMenuStatus(this);
// we may need to redraw the screen TCS 3/21/00 moved TCS 7/28/00
// TCS rev 3/26/01. We now update only the button, since the viewer update
// was causing problems in payroll records that had something other than hrs breakdown showing
UpdatePrinterFlag(false);
}
/*********************************************************************************
CalculateBillingDate (static) TCS 3/1/02
calculate the billing date. This method is static so it can also be used
by viewers.
*********************************************************************************/
CDate CTransaction::CalculateBillingDate(const UInt8 termsClass, const DBid paymentTermID,
const CDate defaultDate)
{
CDate outDate = defaultDate;
if (paymentTermID)
{
TCS_FailNILMsg(gDBFile, TCS_GetErrString(errID_BadFile));
CPaymentTerm *term =
TCS_SAFE_CAST(gDBFile->GetOneObject(termsClass, paymentTermID), CPaymentTerm);
if (term)
{
DB_ObjectWatcher watcher(term);
outDate = term->GetBillingDateAfter(defaultDate);
}
}
return outDate;
}
#if CAN_USE_MARK
#pragma mark -
#endif
/*********************************************************************************
PostNewRecord rev TCS 6/13/00
post creation of a transaction.
*********************************************************************************/
void CTransaction::PostNewRecord(const UInt8 creationType)
{
if (HasActiveStatus())
{
// we use the activation method to handle most posting,
// since it usually doesn't matter if record is new, or un-voided
PostRecordActivated(creationType);
}
else
{
// if we've made a new void record, we use a separate method
// since most transactions don't need to do any posting if void.
// those that do should fill in the PostNewVoidRecord method.
PostNewVoidRecord(creationType);
}
PostUseCount(mMainAccountClass, mMainAccount); // TCS 11/20/03
SetBeenPosted();
MakeDirty();
// let the file deal with the oldest date TCS 6/27/99
TCS_FailNILMsg(gDBFile, TCS_GetErrString(errID_BadFile));
gDBFile->UpdateEarlyLateDates(mDate);
// we do NOT pass it along to the superclass. We don't want the
// audit trail posting that it does there.
}
/*********************************************************************************
PostDeletion rev TCS 6/13/00
post deletion of a transaction.
*********************************************************************************/
void CTransaction::PostDeletion(const Boolean postAudit)
{
// for deletion of an active item, we just use the cancellation
// posting, since that has the same net result
if (HasActiveStatus()) // rev TCS 12/15/99
{
PostRecordCancelled(record_deleteactive);
if (postAudit) // moved TCS 12/26/02
CAuditEntry::CreateAuditEntry(entry_transactiondeleted, this);
}
else
{
// for deleting a void item we use a separate method since
// most transactions don't need to do anything. rev TCS 5/17/00
PostVoidRecordDeleted();
}
PostUseCount(mMainAccountClass, mMainAccount, cRemoveItem); // TCS 11/20/03
}
/*********************************************************************************
PostRecordActivated TCS 1/3/00
post info from a new or activated transaction
*********************************************************************************/
void CTransaction::PostRecordActivated(const UInt8 creationType)
{
switch (creationType) // for some creation types we make an audit entry
{
case record_new:
case record_newfromopen:
case record_fromtemplate:
case record_duplicate:
case record_fromafw:
CAuditEntry::CreateAuditEntry(entry_newtransaction, this);
break;
case record_fromprocess: // right now we don't record transactions TCS 6/8/01
break; // that were created from a dialog or auto transfer
case record_fromimport:
CAuditEntry::CreateAuditEntry(entry_transactionimported, this);
break;
case record_voidtoactive:
case record_jobcosttoactive:
CAuditEntry::CreateAuditEntry(entry_transactionrestored, this);
break;
default:
break;
}
// this is the end of the line TCS rev 12/26/02
}
/*********************************************************************************
PostRecordCancelled TCS 1/3/00
post info from a deleted or voided transaction TCS 9/24/98
*********************************************************************************/
void CTransaction::PostRecordCancelled(const UInt8 cancelType)
{
switch (cancelType)
{
// we used to post deleted records here, but that now happens
// in PostDeletion
case record_activetovoid:
case record_activetojobcost:
CAuditEntry::CreateAuditEntry(entry_transactionvoided, this);
break;
default:
break;
}
// this is the end of the line TCS rev 12/26/02
}
/*********************************************************************************
PostRecordChanging TCS 11/20/03
a record will be changing. Post the change.
*********************************************************************************/
void CTransaction::PostRecordChanging(const Boolean /*accountChanging*/, const Boolean /*jobChanging*/)
{
PostUseCount(mMainAccountClass, mMainAccount, cRemoveItem);
// no need to pass it any further- this is the end of the line
}
/*********************************************************************************
PostRecordChanged
post changes in the transaction.
*********************************************************************************/
void CTransaction::PostRecordChanged(const CMoney &/*oldAmount*/,
const Boolean /*accountChanged*/, const Boolean /*jobChanged*/)
{
CAuditEntry::CreateAuditEntry(entry_transactionchanged, this);
SetBeenPosted();
MakeDirty();
PostUseCount(mMainAccountClass, mMainAccount); // TCS 11/20/03
// let the file deal with the oldest date TCS 6/27/99
TCS_FailNILMsg(gDBFile, TCS_GetErrString(errID_BadFile));
gDBFile->UpdateEarlyLateDates(mDate);
// no need to pass it any further- this is the end of the line
}
/*********************************************************************************
PostImportNew renamed TCS 5/20/02
post a new item that was just imported
*********************************************************************************/
void CTransaction::PostImportNew(const Boolean /*fromPostAction*/)
{
if (HasBeenPosted())
{
// not sure if we'll even allow import changes for transactions
CAuditEntry::CreateAuditEntry(entry_transactionimportchange, this);
}
else
{
PostNewRecord(record_fromimport);
}
SetBeenPosted();
}
|