Link to: header |
source 1 | source
3 | transactions
directory
Copyright Turtle Creek Software 1996-2006. All Rights Reserved.
Source Code
This class manages breakdown transactions for the Goldenseal accounting software,
small business management software, construction
project management software and
construction
accounting software.
/*********************************************************************************
PostRecordActivated TCS 2/3/99
post info from a transaction that is newly created or activated.
We also activate all breakdown items.
*********************************************************************************/
void CBreakdownTransaction::PostRecordActivated(const UInt8 creationType)
{
// we need to activate all breakdown items
PostBreakdownsActivated(mBreakdownArray, mBreakdownClassID, creationType);
// let the superclass do any posting
THE_SUPERCLASS::PostRecordActivated(creationType);
}
/*********************************************************************************
PostRecordCancelled TCS 2/3/99 rev TCS 5/2/00
post info from a voided or deleted transaction. Breakdown deletion was formerly
handled elsewhere, but now we now handle it here also.
*********************************************************************************/
void CBreakdownTransaction::PostRecordCancelled(const UInt8 cancelType)
{
PostBreakdownsCancelled(mBreakdownArray, mBreakdownClassID, cancelType);
// let the superclass do any posting
THE_SUPERCLASS::PostRecordCancelled(cancelType);
}
/*********************************************************************************
PostRecordChanging TCS 1/30/99
a record will be changing. Post the change. We use jobChanging for changes
to the second account.
*********************************************************************************/
void CBreakdownTransaction::PostRecordChanging(const Boolean accountChanging, const Boolean jobChanging)
{
if (HasNewBreakdowns())
PostBreakdownsCancelled(mBreakdownArray, mBreakdownClassID, record_breakdownchange);
else
PostBreakdownsChanging(mBreakdownArray, mBreakdownClassID, accountChanging, jobChanging);
THE_SUPERCLASS::PostRecordChanging(accountChanging, jobChanging);
}
/*********************************************************************************
PostRecordChanged TCS 1/30/99
a record has changed. Post it.
*********************************************************************************/
void CBreakdownTransaction::PostRecordChanged(const CMoney &oldAmount, const Boolean accountChanged,
const Boolean jobChanged)
{
if (HasNewBreakdowns())
PostBreakdownsActivated(mBreakdownArray, mBreakdownClassID, record_breakdownchange);
else
PostBreakdownsChanged(mBreakdownArray, mBreakdownClassID, oldAmount, accountChanged, jobChanged);
THE_SUPERCLASS::PostRecordChanged(oldAmount, accountChanged, jobChanged);
}
/*********************************************************************************
PostBreakdownChanging TCS 4/12/00
the breakdown type will be changing. Better let anything deal with it
*********************************************************************************/
void CBreakdownTransaction::PostBreakdownChanging()
{
if (mBreakdownType != breakdown_none)
PostBreakdownsChanging(mBreakdownArray, mBreakdownClassID, false, false);
}
#if CAN_USE_MARK
#pragma mark -
#endif
/*********************************************************************************
PostBreakdownsActivated TCS 2/6/99 rev TCS 5/16/00
post activation to a set of breakdowns
*********************************************************************************/
void CBreakdownTransaction::PostBreakdownsActivated(const TObjectIDArray &array,
const DBClass breakdownClassID,
const UInt8 creationType)
{
TCS_FailNILMsg(gDBFile, TCS_GetErrString(errID_BadFile));
if (array.GetCount() > 0)
{
TObjectIDArrayIterator iterator(array);
DBid breakdownID;
DB_PersistentObject *breakdownItem;
while (iterator.Next(breakdownID))
{
breakdownItem = gDBFile->GetOneObject(breakdownClassID, breakdownID);
if (breakdownItem)
{
DB_ObjectWatcher watcher(breakdownItem);
breakdownItem->PostRecordActivated(creationType);
FinishBreakdownPosting(breakdownItem, record_activate);
}
}
}
}
/*********************************************************************************
PostBreakdownsCancelled TCS 2/6/99 rev TCS 5/16/00
post cancellation to a set of breakdowns
*********************************************************************************/
void CBreakdownTransaction::PostBreakdownsCancelled(const TObjectIDArray &array,
const DBClass breakdownClassID,
const UInt8 cancelType)
{
TCS_FailNILMsg(gDBFile, TCS_GetErrString(errID_BadFile));
if (array.GetCount() > 0)
{
TObjectIDArrayIterator iterator(array);
DBid breakdownID;
DB_PersistentObject *breakdownItem;
while (iterator.Next(breakdownID))
{
breakdownItem = gDBFile->GetOneObject(breakdownClassID, breakdownID);
if (breakdownItem)
{
DB_ObjectWatcher watcher(breakdownItem);
breakdownItem->PostRecordCancelled(cancelType); // rev TCS 9/6/99
FinishBreakdownPosting(breakdownItem, record_cancel);
}
}
}
}
/*********************************************************************************
PostBreakdownsChanging TCS 12/18/99 rev TCS 5/16/00
post a pending change to a set of breakdowns
*********************************************************************************/
void CBreakdownTransaction::PostBreakdownsChanging(const TObjectIDArray &array,
const DBClass breakdownClassID,
const Boolean accountChanging, const Boolean jobChanging)
{
if (array.GetCount() > 0)
{
TObjectIDArrayIterator iterator(array);
DBid breakdownID;
DB_PersistentObject *breakdownItem;
while (iterator.Next(breakdownID))
{
breakdownItem = gDBFile->GetOneObject(breakdownClassID, breakdownID);
if (breakdownItem)
{
DB_ObjectWatcher watcher(breakdownItem);
breakdownItem->PostRecordChanging(accountChanging, jobChanging);
FinishBreakdownPosting(breakdownItem, record_changing);
}
}
}
}
/*********************************************************************************
PostBreakdownsChanged TCS 12/18/99 rev TCS 5/16/00
post a past change to a set of breakdowns
*********************************************************************************/
void CBreakdownTransaction::PostBreakdownsChanged(const TObjectIDArray &array,
const DBClass breakdownClassID,
const CMoney &oldAmount, const Boolean accountChanged,
const Boolean jobChanged)
{
TCS_FailNILMsg(gDBFile, TCS_GetErrString(errID_BadFile));
if (array.GetCount() > 0)
{
TObjectIDArrayIterator iterator(array);
DBid breakdownID;
DB_PersistentObject *breakdownItem;
while (iterator.Next(breakdownID))
{
breakdownItem = gDBFile->GetOneObject(breakdownClassID, breakdownID);
if (breakdownItem)
{
DB_ObjectWatcher watcher(breakdownItem);
breakdownItem->PostRecordChanged(oldAmount, accountChanged, jobChanged);
FinishBreakdownPosting(breakdownItem, record_changed);
}
}
}
}
#if CAN_USE_MARK
#pragma mark -
#endif
/*********************************************************************************
GetTaxPercent TCS 2/11/01
return the percent sales tax rate used for this transaction. This is set
up generically so it works for sales or expenses
*********************************************************************************/
CMoney CBreakdownTransaction::GetTaxPercent() const
{
DBClass taxClass = GetTaxClass();
DBid taxRateID = GetTaxID();
if (taxClass && taxRateID)
{
TCS_FailNILMsg(gDBFile, TCS_GetErrString(errID_BadFile));
DB_PersistentObject *taxRate = gDBFile->GetOneObject(taxClass, taxRateID);
if (taxRate)
{
DB_ObjectWatcher watcher(taxRate);
return taxRate->GetTaxPercent();
}
else
return 0;
}
else
return 0;
}
/*********************************************************************************
GetTaxName TCS 2/12/01
return the name of the sales tax used for this transaction. This is set
up generically so it works for sales or expenses
*********************************************************************************/
CTextString CBreakdownTransaction::GetTaxName() const
{
DBClass taxClass = GetTaxClass();
DBid taxRateID = GetTaxID();
if (taxClass && taxRateID)
{
TCS_FailNILMsg(gDBFile, TCS_GetErrString(errID_BadFile));
DB_PersistentObject *taxRate = gDBFile->GetOneObject(taxClass, taxRateID);
if (taxRate)
{
DB_ObjectWatcher watcher(taxRate);
return taxRate->GetName();
}
else
return cEmptyString;
}
else
return cEmptyString;
}
/*********************************************************************************
GetWithholdingName TCS 10/4/02
return the name of the withholding rate
*********************************************************************************/
CTextString CBreakdownTransaction::GetWithholdingName() const
{
DBid taxRateID = GetWithholdingRateID();
if (taxRateID)
{
TCS_FailNILMsg(gDBFile, TCS_GetErrString(errID_BadFile));
DB_PersistentObject *taxRate = gDBFile->GetOneObject(id_VendorWithholding, taxRateID);
if (taxRate)
{
DB_ObjectWatcher watcher(taxRate);
return taxRate->GetName();
}
else
return cEmptyString;
}
else
return cEmptyString;
}
/*********************************************************************************
GetPaymentReceiptAmount
return the amount that has been paid in already via payment receipt
*********************************************************************************/
CMoney CBreakdownTransaction::GetPaymentReceiptAmount() const
{
TCS_FailNILMsg(gDBFile, TCS_GetErrString(errID_BadFile));
CMoney amount = 0, receiptAmount;
DB_PersistentObject *receipt;
if (mPaymentArray.GetCount() > 0)
{
TObjectInfoArrayIterator iterator(mPaymentArray);
SObjectInfo info;
while (iterator.Next(info))
{
if (info.classID == id_PaymentReceipt)
{
receipt = gDBFile->GetOneObject(id_PaymentReceipt, info.itemID);
if (receipt)
{
DB_ObjectWatcher watcher(receipt);
receiptAmount = receipt->GetAmount();
amount += receiptAmount;
}
}
}
}
return amount;
}
/*********************************************************************************
GetPaymentTransactionClass TCS 4/11/00
return the object class id used for payment transaction.
*********************************************************************************/
UInt8 CBreakdownTransaction::GetPaymentTransactionClass() const
{
if (mPaymentArray.GetCount() > 0)
{
SObjectInfo info;
Boolean hasDeposit = false;
if (IsCostTransaction())
{ // for expenses, we just use the first payment
mPaymentArray.FetchItemAt(1, info);
return info.classID;
}
else if (GetConditions() == condition_Return || GetConditions() == condition_Credit)
{
// for credits, we have a regular bank payment TCS 2/7/03
mPaymentArray.FetchItemAt(1, info);
return info.classID;
}
else
{ // for income transactions, we search for payment receipts
TObjectInfoArrayIterator iterator(mPaymentArray);
while (iterator.Next(info))
{
if (info.classID == id_PaymentReceipt)
return id_PaymentReceipt;
else if (info.classID == id_BankDeposit) // rev TCS 6/6/00
hasDeposit = true;
}
// if we got this far, there is no payment receipt
if (hasDeposit)
return id_BankDeposit;
else
return 0;
}
}
else
return 0;
}
/*********************************************************************************
GetPaymentTransactionID TCS 4/11/00
return the object id used for payment transactions. We return the first
payment receipt, or if no pmt receipts, then the last deposit
*********************************************************************************/
DBid CBreakdownTransaction::GetPaymentTransactionID() const
{
if (mPaymentArray.GetCount() > 0)
{
SObjectInfo info;
DBid lastDepositID = 0;
if (IsCostTransaction())
{
// for expenses, we just use the first payment
mPaymentArray.FetchItemAt(1, info);
return info.itemID;
}
else if (GetConditions() == condition_Return || GetConditions() == condition_Credit)
{
// for credits, we have a regular bank payment TCS 2/7/03
mPaymentArray.FetchItemAt(1, info);
return info.itemID;
}
else
{ // for income transactions, we check for pmt receipts
TObjectInfoArrayIterator iterator(mPaymentArray);
while (iterator.Next(info))
{
if (info.classID == id_PaymentReceipt)
return info.itemID;
else if (DB_ClassDescriptor::IsBankTransaction(info.classID)) // rev TCS 6/6/00, bugfix 5/4/01
lastDepositID = info.itemID;
}
return lastDepositID;
}
}
else
return 0;
}
/*********************************************************************************
GetBreakdownLaborHours TCS 5/16/02
return the total # of labor hours in the breakdown items.
*********************************************************************************/
CMoney CBreakdownTransaction::GetBreakdownLaborHours() const
{
CMoney totalHours = 0, itemHours;
TObjectIDArrayIterator iterator(mBreakdownArray);
DBid id;
while (iterator.Next(id))
{
DB_PersistentObject *breakdown = gDBFile->GetOneObject(mBreakdownClassID, id);
if (breakdown)
{
DB_ObjectWatcher watcher (breakdown);
itemHours = breakdown->GetLaborHours();
totalHours += itemHours;
}
}
return totalHours;
}
/*********************************************************************************
GetCategoryFromBreakdowns TCS 11/12/03
get a category from the breakdowns. We just grab the first item
*********************************************************************************/
DBid CBreakdownTransaction::GetCategoryFromBreakdowns() const
{
TObjectIDArrayIterator iterator(mBreakdownArray);
DBid id, categoryID = 0;
while (iterator.Next(id) && !categoryID)
{
DB_PersistentObject *breakdown = gDBFile->GetOneObject(mBreakdownClassID, id);
if (breakdown)
{
DB_ObjectWatcher watcher (breakdown);
categoryID = breakdown->GetCategory();
}
}
return categoryID;
}
#if CAN_USE_MARK
#pragma mark -
#endif
/*********************************************************************************
FillCategoryArray TCS 7/18/99
fill in category cost info. We override since we'll get cost info
from the breakdown items, if available
*********************************************************************************/
void CBreakdownTransaction::FillCategoryArray(TJobCostCategoryArray &catArray,
const UInt8 breakdownType,
const DBid matchCategory,
const UInt8 restrictions)
{
// we don't fill in income from breakdowns
if (restrictions == costtype_income) // TCS 5/8/01 moved 7/20/01 rev 11/27/01
return THE_SUPERCLASS::FillCategoryArray(catArray, breakdownType, matchCategory, restrictions);
// for some breakdown classes, we get job cost info from the breakdowns rev TCS 5/9/01
if (mBreakdownType == breakdown_costitem || mBreakdownType == breakdown_costcategory ||
mBreakdownType == breakdown_laboritem || mBreakdownType == breakdown_laborcategory)
{
// fetch the transaction value to use as a default,
// in case breakdowns do not have a category/location
DBid parentValue = 0, parentSubcategory = 0;
if (breakdownType == breakdown_location)
GetMemberValue(tag_location, type_long, &parentValue);
else
{
GetMemberValue(tag_category, type_long, &parentValue);
GetMemberValue(tag_subcategory, type_long, &parentSubcategory);
}
// now loop thru breakdown items and have them fill the array
if (mBreakdownArray.GetCount() > 0)
{
TObjectIDArrayIterator iterator(mBreakdownArray);
DBid breakdownID;
CBreakdownEntry *breakdownItem;
while (iterator.Next(breakdownID))
{
breakdownItem =
TCS_SAFE_CAST(gDBFile->GetOneObject(mBreakdownClassID, breakdownID),
CBreakdownEntry);
if (breakdownItem)
{
DB_ObjectWatcher watcher(breakdownItem);
breakdownItem->FillBreakdownCostItem(catArray, breakdownType, matchCategory, // rev TCS 7/30/01
parentValue, parentSubcategory);
}
}
}
}
else
{ // for 'none' breakdown or other breakdown types, we just pass it along
THE_SUPERCLASS::FillCategoryArray(catArray, breakdownType, matchCategory, restrictions);
return;
}
// add an item for sales tax?? TCS 9/3/99
// %%%INCOMPLETE %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
}
/*********************************************************************************
FillCompareArray TCS 8/6/01
fill in cost info for a job cost comparison. We override since we'll get cost info
from the breakdown items, if available
*********************************************************************************/
void CBreakdownTransaction::FillCompareArray(TJobCostCompareArray &compareArray, const DBid reportID)
{
Boolean useLocations = (reportID == id_JobCostLocationReport || reportID == id_JobCostLocationClassReport);
Boolean useSubcats = reportID == id_JobCostSubcatReport;
// for some breakdown classes, we get job cost info from the breakdowns
if (mBreakdownType == breakdown_costitem || mBreakdownType == breakdown_costcategory ||
mBreakdownType == breakdown_laboritem || mBreakdownType == breakdown_laborcategory)
{
// fetch the transaction value to use as a default,
// in case breakdowns do not have a category/location
DBid parentCategory = 0;
if (useLocations) // TCS 11/7/01
{
GetMemberValue(tag_location, type_long, &parentCategory);
}
else
{
if (useSubcats)
GetMemberValue(tag_subcategory, type_long, &parentCategory);
if (!parentCategory)
GetMemberValue(tag_category, type_long, &parentCategory);
}
// now loop thru breakdown items and have them fill the array
if (mBreakdownArray.GetCount() > 0)
{
TObjectIDArrayIterator iterator(mBreakdownArray);
DBid breakdownID;
CBreakdownEntry *breakdownItem;
while (iterator.Next(breakdownID))
{
breakdownItem =
TCS_SAFE_CAST(gDBFile->GetOneObject(mBreakdownClassID, breakdownID),
CBreakdownEntry);
if (breakdownItem)
{
DB_ObjectWatcher watcher(breakdownItem);
breakdownItem->FillBreakdownCompareItem(compareArray, parentCategory,
useLocations, useSubcats);
}
}
}
}
else
{ // for 'none' breakdown or other breakdown types, we just pass it along
THE_SUPERCLASS::FillCompareArray(compareArray, reportID);
return;
}
}
/*********************************************************************************
FillCatSubcatArray TCS 9/7/02
fill job cost info into a two-level array of cat/subcats
*********************************************************************************/
void CBreakdownTransaction::FillCatSubcatArray(const DBid reportID, TTwoLevelArray *twoLevelArray,
const Boolean hideSoftCosts, CMoney &softCostAmount,
CMoney &hardCostAmount) const
{
if (mBreakdownType == breakdown_costitem || mBreakdownType == breakdown_costcategory ||
mBreakdownType == breakdown_laboritem || mBreakdownType == breakdown_laborcategory)
{
// fetch the transaction value to use as a default,
// in case breakdowns do not have a category/location
DBid parentCategory = GetCategory();
DBid parentSubcategory = GetSubcategory();
// now loop thru breakdown items and have them fill the array
if (mBreakdownArray.GetCount() > 0)
{
TObjectIDArrayIterator iterator(mBreakdownArray);
DBid breakdownID;
CBreakdownEntry *breakdownItem;
while (iterator.Next(breakdownID))
{
breakdownItem =
TCS_SAFE_CAST(gDBFile->GetOneObject(mBreakdownClassID, breakdownID),
CBreakdownEntry);
if (breakdownItem)
{
DB_ObjectWatcher watcher(breakdownItem);
breakdownItem->FillCatSubcatInfo(twoLevelArray, parentCategory,
parentSubcategory);
}
}
}
}
else
{ // for 'none' breakdown or other breakdown types, we just pass it along
THE_SUPERCLASS::FillCatSubcatArray(reportID, twoLevelArray, hideSoftCosts,
softCostAmount, hardCostAmount);
return;
}
}
/*********************************************************************************
FillCatItemArray TCS 1/25/03
fill job cost info into a two-level array of cat/subcats
*********************************************************************************/
void CBreakdownTransaction::FillCatItemArray(const DBid reportID,
TReportGroupArray *catArray) const
{
if (mBreakdownType == breakdown_costitem || mBreakdownType == breakdown_costcategory ||
mBreakdownType == breakdown_laboritem || mBreakdownType == breakdown_laborcategory)
{
// fetch the transaction value to use as a default,
// in case breakdowns do not have a category/location
DBid parentCategory = GetCategory();
// now loop thru breakdown items and have them fill the array
if (mBreakdownArray.GetCount() > 0)
{
TObjectIDArrayIterator iterator(mBreakdownArray);
DBid breakdownID;
CBreakdownEntry *breakdownItem;
while (iterator.Next(breakdownID))
{
breakdownItem =
TCS_SAFE_CAST(gDBFile->GetOneObject(mBreakdownClassID, breakdownID),
CBreakdownEntry);
if (breakdownItem)
{
DB_ObjectWatcher watcher(breakdownItem);
breakdownItem->FillCatItemInfo(catArray, parentCategory);
}
}
}
}
else
{ // for 'none' breakdown or other breakdown types, we just pass it along
THE_SUPERCLASS::FillCatItemArray(reportID, catArray);
return;
}
}
/*********************************************************************************
FillProgressArray TCS 9/15/99
fill in category cost info. We override since we'll get cost info
from the breakdown items, if available
*********************************************************************************/
void CBreakdownTransaction::FillProgressArray(TJobCostProgressArray &catArray,
const UInt8 breakdownType) const
{
// if no breakdowns, the superclass can handle it. TCS bugfix 9/17/99
if (mBreakdownType == breakdown_none)
{
THE_SUPERCLASS::FillProgressArray(catArray, breakdownType);
return;
}
// fetch the transaction match value to use as a default
DBid defaultValue = 0;
if (breakdownType == breakdown_location)
GetMemberValue(tag_location, type_long, &defaultValue);
else
GetMemberValue(tag_category, type_long, &defaultValue);
// now loop thru breakdown items and have them fill the array
if (mBreakdownArray.GetCount() > 0)
{
TObjectIDArrayIterator iterator(mBreakdownArray);
DBid breakdownID;
CBreakdownEntry *breakdownItem;
while (iterator.Next(breakdownID))
{
breakdownItem =
TCS_SAFE_CAST(gDBFile->GetOneObject(mBreakdownClassID, breakdownID),
CBreakdownEntry);
if (breakdownItem)
{
DB_ObjectWatcher watcher(breakdownItem);
breakdownItem->FillProgressArray(catArray, defaultValue, breakdownType);
}
}
}
}
|