Accounting Software
Small Business Software Estimating Software
Construction Estimating SoftwareBookkeeping SoftwareInventory SoftwareInventory Control SoftwareInventory Tracking SoftwareInventory Management SoftwareBusiness Management Software

Project Account Viewer (Source Code)

Link to: header | record viewer directory

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

Comments

CProjectAccountViewer

This class manages project accounts for the Goldenseal accounting software,
small business management software, construction project management software and
construction estimating software.

a viewer for project accounts. Handles screen display & actions for Project
account window.

Projects are the starting point for the Goldenseal job costing software,
project management software, and project billing software.

SUPERCLASS = CAccountViewer

Constructor

/*********************************************************************************
constructor
*********************************************************************************/
CProjectAccountViewer::CProjectAccountViewer(const SPaneInfo &inPaneInfo,
const SViewInfo &inViewInfo)
: CAccountViewer(inPaneInfo, inViewInfo)
{
}

Source Code

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

FinishUpdatingFields split TCS 4/17/00

Finish prep work after updating fields from an object, but before displaying them

*********************************************************************************/
void CProjectAccountViewer::FinishUpdatingFields(const UInt8 creationMethod,
DB_PersistentObject *viewerObject)
{
// the superclass handles basic field updating
THE_SUPERCLASS::FinishUpdatingFields(creationMethod, viewerObject);

// set enablement of draw schedule field
UInt8 projectType = GetPopupValue(tag_projecttype);
FormatDrawField(projectType);

// set enablement and amount of contract price field
FormatPriceField(GetFieldValue(tag_estimate));

// set params in the estimate transaction cv
DBClass accountID = GetFieldValue(tag_customer); // bugfix TCS 1/14/02
DBid accountClass = GetFieldValue(tag_customertype);
PrepareEstimateField(accountClass, accountID);

// set enablement of the 'view contacts' buttons TCS 10/13/02
UpdateContactButton(id_ProjectLog, button_viewprojectlog);
UpdateContactButton(id_BillingRecord, button_viewbills); // TCS 1/28/04

CProjectAccount *project = TCS_SAFE_CAST(viewerObject, CProjectAccount);

if (project) // TCS 1/20/04
{
UpdateButtonEnabled(button_viewchangeorders, project->GetChangeOrderCount());
UpdateButtonEnabled(button_viewallowances, project->GetAllowanceCount());
}
}
/*********************************************************************************

PrepareCVForUpdating TCS rev 5/17/00

prepare a cv field for updating. "Preparing" means setting the
class id and any other parameters, but NOT the value. This method
is called once, when the cv field is first created.

*********************************************************************************/
void CProjectAccountViewer::PrepareCVForUpdating(DB_Clairvoyant &cvField,
DB_PersistentObject *viewerObject,
const SMemberFieldInfo &fieldInfo)
{
switch (cvField.GetPaneID())
{
// formerly handled tag_customer here. TCS moved it to DB_RecordViewer
// on 10/22/98 so it would be available for printing prep

case tag_estimate:
// transaction cv's can be prepped here, since they are not
// needed when doing printing prep. TCS 5/10/99
{
CTransactionCV *cv = TCS_SAFE_CAST(&cvField, CTransactionCV);
if (cv)
{
TCS_FailNILMsg(viewerObject, TCS_GetErrString(errID_BadObject));

DBClass accountClass = 0;
DBid accountID = 0;

viewerObject->GetMemberValue(tag_customertype, type_objclass, &accountClass);
viewerObject->GetMemberValue(tag_customer, type_objectid, &accountID);

cv->SetAccountClassID(accountClass);
cv->SetAccountID(accountID);
}
}
return; // don't pass this along since superclass handles it differently
break;

default:
break;
}
// pass it along
THE_SUPERCLASS::PrepareCVForUpdating(cvField, viewerObject, fieldInfo);
}
#if CAN_USE_MARK
#pragma mark -
#endif
/*********************************************************************************

HandleEditChanged

an edit field has been changed, act accordingly

*********************************************************************************/
void CProjectAccountViewer::HandleEditChanged(CTCS_EditField *editField)
{
TCS_FailNILMsg(editField, TCS_GetErrString(errID_BadField));
switch (editField->GetPaneID())
{
case tag_contractamount: // TCS 3/2/01
RecalcAmountWithTax(true);
break;

default:
break;
}
// be sure to pass it along to the superclass
THE_SUPERCLASS::HandleEditChanged(editField);
}/*********************************************************************************

HandleCVChanged

a cv field has changed, act accordingly

*********************************************************************************/
void CProjectAccountViewer::HandleCVChanged(CTCS_CVField *cvField)
{
TCS_FailNILMsg(cvField, TCS_GetErrString(errID_BadClairvoyant));
DBid value = cvField->GetValue();

switch (cvField->GetPaneID())
{
case tag_estimate:
CheckEstimateDrawConflict(GetFieldValue(tag_drawschedule), value);
HandleEstimateChanged(value);
FormatPriceField(value);
break;

case tag_customer:
HandleCustomerChanged(value);
break;

case tag_taxrate: // TCS 2/21/00
RecalcAmountWithTax(true);
break;

case tag_jobtype: // TCS 5/4/00
HandleJobTypeChanged(value);
break;

case tag_drawschedule:
CheckEstimateDrawConflict(value, GetFieldValue(tag_estimate), true);
break;

/*case tag_paymentterm:
FormatDrawField(value);
break;*/

default:
break;
}
// we'll also let the superclass have a crack
THE_SUPERCLASS::HandleCVChanged(cvField);
}
/*********************************************************************************

HandleFindPopupClicked

handle a popup change while in find mode TCS 9/15/98

*********************************************************************************/
void CProjectAccountViewer::HandleFindPopupClicked(CTCS_StdPopupMenu *popupMenu)
{
// sanity check
TCS_FailNILMsg(popupMenu, TCS_GetErrString(errID_BadPopup));
// what we do depends on what was clicked
switch (popupMenu->GetPaneID())
{
case tag_customertype:
{
SetCVClassID(tag_customer, popupMenu->GetValue(), cEraseValue);
}
break;


default:
THE_SUPERCLASS::HandleFindPopupClicked(popupMenu);
break;
}
}/*********************************************************************************

HandlePopupChanged

a popup was clicked, process the result

*********************************************************************************/
void CProjectAccountViewer::HandlePopupChanged(CTCS_StdPopupMenu *popupMenu)
{
// sanity check
TCS_FailNILMsg(popupMenu, TCS_GetErrString(errID_BadPopup));
UInt8 value = popupMenu->GetValue();

// what we do depends on what was clicked
switch (popupMenu->GetPaneID())
{
case tag_customertype:
{
SetCVClassID(tag_customer, value, cEraseValue);
HandleCustomerChanged(0);
}
break;

case tag_projecttype:
FormatDrawField(value);
break;

default:
break;
}
// be sure to pass it along
THE_SUPERCLASS::HandlePopupChanged(popupMenu);
}
/*********************************************************************************

HandleDBButtonClicked TCS 1/20/04

a button in the layout was clicked.

*********************************************************************************/
void CProjectAccountViewer::HandleDBButtonClicked(const TagType btnID)
{
TCS_FailNILMsg(mCurrViewerObject, TCS_GetErrString(errID_BadObject));
switch (btnID)
{
case button_viewchangeorders:
case button_viewallowances:
{
CProjectAccount *project = TCS_SAFE_CAST(mCurrViewerObject, CProjectAccount);

if (project)
{
TObjectIDArray array;

if (btnID == button_viewchangeorders)
{
project->FetchChangeOrderArray(array);
DB_Editor::ShowEditorArray(id_ChangeOrder, array, cShowLastRecord);
}
else
{
project->FetchAllowanceArray(array);
DB_Editor::ShowEditorArray(id_Allowance, array, cShowLastRecord);
}

}
}
break;

default:
THE_SUPERCLASS::HandleDBButtonClicked(btnID);
}
}
#if CAN_USE_MARK
#pragma mark -
#endif
/*********************************************************************************

HandleCustomerChanged

when a customer is selected, fill in their current address etc

*********************************************************************************/
void CProjectAccountViewer::HandleCustomerChanged(const DBid accountID,
const Boolean clearEstimate)
{
// let's get the customer account from the id
TCS_FailNILMsg(gDBFile, TCS_GetErrString(errID_BadFile));

DBid customerType = GetPopupValue(tag_customertype);

DB_Account *account =
TCS_SAFE_CAST(gDBFile->GetOneObject(customerType, accountID), DB_Account);

CTextString text;

if (account)
{ // there is a customer account, so we can proceed
DB_ObjectWatcher watcher(account);

// update the address field
if (account->GetMemberValue(tag_address, type_cstring, &text))
SetFieldCString(tag_address, text);

// update the billing name field
if (account->GetMemberValue(tag_secondname, type_cstring, &text))
SetFieldCString(tag_secondname, text);

// update the phone field
if (account->GetMemberValue(tag_telephone, type_cstring, &text))
SetFieldCString(tag_telephone, text);

// update the job type field
SInt32 jobType;
if (account->GetMemberValue(tag_accounttype, type_objectid, &jobType))
SetFieldValue(tag_accounttype, jobType);

// update the sales rep field
SInt32 salesRep;
if (account->GetMemberValue(tag_salesrep, type_objectid, &salesRep))
SetFieldValue(tag_salesrep, salesRep);
}
else // no customer, so clear some fields
{
SetFieldCString(tag_address, text);
SetFieldCString(tag_secondname, text);
SetFieldCString(tag_telephone, text);
SetFieldValue(tag_accounttype, 0);
SetFieldValue(tag_salesrep, 0);
}

// set cv values in estimate field TCS 5/10/99 rev 1/27/00 rev 1/3/02
PrepareEstimateField(customerType, accountID);

if (clearEstimate)
SetFieldValue(tag_estimate, 0);

// set enablement of draw schedule field TCS 5/10/99
//FormatDrawField(GetFieldValue(tag_paymentterm)); bugfix TCS removed 9/17/01
}/*********************************************************************************

HandleEstimateChanged

when an estimate is filled in, put its price & other info into the correct fields,
and adjust the editability of the contract price field

*********************************************************************************/
void CProjectAccountViewer::HandleEstimateChanged(const DBid estimateID)
{
// let's get the account from the id
TCS_FailNILMsg(gDBFile, TCS_GetErrString(errID_BadFile));

if (!estimateID) // if no estimate, we might as well return now TCS 12/24/00
return;

CEstimate *estimate =
TCS_SAFE_CAST(gDBFile->GetOneObject(id_Estimate, estimateID), CEstimate);

if (estimate)
{ // there is an estimate, so we can proceed
DB_ObjectWatcher watcher(estimate);

// if no customer info, fill it in TCS 1/27/00
if (!GetFieldValue(tag_customer))
{
DBid customerID = estimate->GetMainAccountID();
SetFieldValue(tag_customer, customerID);
HandleCustomerChanged(customerID, false);
}

// TCS removed updating of address field 12/23/00

// update the project name field. Note that this may wipe out
// the name of an existing project. On the other hand, the current
// name may just be "Project 12", and we do want to encourage the
// estimate and project to have the same name, just to avoid confusion
CTextString estName;
if (estimate->GetMemberValue(tag_name, type_cstring, &estName))
{
SetFieldCString(tag_name, estName);
}

// update the billing name field
if (estimate->GetMemberValue(tag_secondname, type_cstring, &estName))
{
SetFieldCString(tag_secondname, estName);
}

// we don't need to update the amount, since FormatPriceField will do that

// update the job type field
DBid jobType;
if (estimate->GetMemberValue(tag_jobtype, type_objectid, &jobType))
{
SetFieldValue(tag_jobtype, jobType);
}

// update the sales rep field
DBid salesRep;
if (estimate->GetMemberValue(tag_salesrep, type_objectid, &salesRep))
{
SetFieldValue(tag_salesrep, salesRep);
}

// update the payment terms field
DBid pmtTerms;
if (estimate->GetMemberValue(tag_paymentterm, type_objectid, &pmtTerms))
{
SetFieldValue(tag_paymentterm, pmtTerms);
}

// update the sales tax field TCS 7/14/99
DBid salesTax;
if (estimate->GetMemberValue(tag_taxrate, type_objectid, &salesTax))
{
SetFieldValue(tag_taxrate, salesTax);
}

// update the cat system field TCS 7/14/99
DBid catSystem;
if (estimate->GetMemberValue(tag_catsystem, type_objectid, &catSystem))
{
SetFieldValue(tag_catsystem, catSystem);
}

// set enablement and amount of contract price field
FormatPriceField(GetFieldValue(tag_estimate));

// the draw schedule status may have changed TCS rev 7/13/99
FormatDrawField(GetFieldValue(tag_projecttype));

// update the location package field
DBid locationPackage;
if (estimate->GetMemberValue(tag_locationpackage, type_objectid, &locationPackage))
{
SetFieldValue(tag_locationpackage, locationPackage);
}
}
else
{
ReportMissingObject(id_Estimate, estimateID); // TCS 12/23/00
SetFieldValue(tag_estimate, 0);
}
}
/*********************************************************************************

HandleJobTypeChanged TCS 5/4/00

fill in data after a change of job type

*********************************************************************************/
void CProjectAccountViewer::HandleJobTypeChanged(const DBid newJobType)
{
// let's get the account from the id
TCS_FailNILMsg(gDBFile, TCS_GetErrString(errID_BadFile));
CJobType *jobType =
TCS_SAFE_CAST(gDBFile->GetOneObject(id_JobType, newJobType), CJobType);

if (jobType)
{ // there is a job type, so we can proceed
DB_ObjectWatcher watcher(jobType);

// update the address field
DBid catSystemID = jobType->GetCategorySystem();
if (catSystemID)
SetFieldValue(tag_catsystem, catSystemID);

DBid packageID = jobType->GetLocationPackage();
if (packageID)
SetFieldValue(tag_locationpackage, packageID);
}
}
#if CAN_USE_MARK
#pragma mark -
#endif
/*********************************************************************************

FormatDrawField

set the enablement of the draw schedule field TCS 7/21/98 rev 5/10/99

*********************************************************************************/
void CProjectAccountViewer::FormatDrawField(const UInt8 inValue)
{
// first we need to see if the pmt term is draw sched
Boolean isDraw = (inValue == project_DrawSchedule);

// if we're disabling it, let's also clear the value
if (!isDraw)
SetFieldValue(tag_drawschedule, 0);

// now we can set the enablement of the field
SetCVFieldEnabled(tag_drawschedule, isDraw);
} /*********************************************************************************

FormatPriceField

set the enablement and amount of the contract amount field TCS 12/8/98

Note that we update the price every time we open the record, since the estimate
may have changed recently.

*********************************************************************************/
void CProjectAccountViewer::FormatPriceField(const DBid inEstimateID)
{
// do we have an estimate?
Boolean hasEstimate = false;

if (inEstimateID)
{ // we have an estimate. Let's find the object
TCS_FailNILMsg(gDBFile, TCS_GetErrString(errID_BadFile));
CEstimate *estimate = TCS_SAFE_CAST(gDBFile->GetOneObject(id_Estimate,
inEstimateID), CEstimate);
if (estimate)
{
DB_ObjectWatcher watcher(estimate);
hasEstimate = true;

CMoney amount;

// fetch the gross amount
TCS_ASSERTMsg(estimate->GetMemberValue(tag_grossprice, type_money, &amount),
TCS_GetValueErrString(tag_grossprice));
SetFieldMoneyValue(tag_contractamount, amount);

// update the tax amount and total amount
RecalcAmountWithTax(true);
}
}

// now we can set the enablement of the contract field
SetFieldEnabled(tag_contractamount, !hasEstimate);
}
/*********************************************************************************

MainAccountHasChanged TCS 2/3/99

return whether the customer account has changed.

*********************************************************************************/
Boolean CProjectAccountViewer::MainAccountHasChanged()
{
// sanity check
TCS_FailNILMsg(mCurrViewerObject, TCS_GetErrString(errID_BadObject));

DBid oldAccount = 0,
newAccount = GetFieldValue(tag_customer);
DBClass oldAccountClass = 0,
newAccountClass = GetPopupValue(tag_customertype);

mCurrViewerObject->GetMemberValue(tag_customer, type_objectid, &oldAccount);
mCurrViewerObject->GetMemberValue(tag_customertype, type_objclass, &oldAccountClass);

return (oldAccount != newAccount || oldAccountClass != newAccountClass);
}
/*********************************************************************************

RecalcAmountWithTax TCS 2/21/00

recalculate the amount with tax. This is usually called if the contract price
or sales tax changes

*********************************************************************************/
void CProjectAccountViewer::RecalcAmountWithTax(const Boolean recalcTax,
const Boolean /*recalcWithholding*/)
{
// we do nothing when in find mode TCS 11/17/98
if (InFindMode())
return;

// let's get the gross price, if any
CTCS_EditField *grossField =
TCS_SAFE_CAST(FindMemberField(tag_contractamount), CTCS_EditField);
if (grossField)
{ // there is a gross price field, let's see if there's
// a tax field
DB_Clairvoyant *taxField =
TCS_SAFE_CAST(FindMemberField(tag_taxrate), DB_Clairvoyant);
if (taxField)
{ // ok, there's a tax field as well. Now let's see if
// there's an amount field
CTCS_EditField *amountField =
TCS_SAFE_CAST(FindMemberField(tag_amount), CTCS_EditField);
if (amountField)
{ // ok, we've got all three! Let's do the calc

CMoney grossAmount = grossField->GetMoneyValue();
CMoney taxAmount, finalAmount;

if (recalcTax) // rev TCS 7/11/00
{
taxAmount = CJobSalesTax::CalculateSalesTaxAmount(taxField->GetValue(),
grossAmount, 0);
SetFieldMoneyValue(tag_taxamount, taxAmount);
}
else
taxAmount = GetFieldMoneyValue(tag_taxamount);

finalAmount = grossAmount + taxAmount;
finalAmount.RoundPennies(); // TCS 8/20/01

amountField->SetMoneyValue(finalAmount);
}
}
}
}
/*********************************************************************************

CheckEstimateDrawConflict TCS 9/17/01

check whether this project uses both a fixed-dollar draw schedule and an
estimate. If so, we give a warning that the draws will be pro-rated.

*********************************************************************************/
Boolean CProjectAccountViewer::CheckEstimateDrawConflict(const DBid drawID,
const DBid estimateID,
const Boolean fillValue)
{
// if no draw schedule, there's no conflict
if (!drawID)
return false;

CDrawSchedule *schedule = TCS_SAFE_CAST(gDBFile->GetOneObject(id_DrawSchedule, drawID),
CDrawSchedule);

if (schedule)
{
DB_ObjectWatcher watcher(schedule);

if (schedule->GetCalcMethod() == calc_dollars)
{
if (estimateID)
{
TCS_InfoAlert(TCS_GetMsgString(msgID_DrawEstimateConflict));
return true;
}
else
{
if (fillValue)
{
CMoney drawAmount = schedule->GetAmount();
SetFieldMoneyValue(tag_contractamount, drawAmount);
RecalcAmountWithTax(true);
}
return false;
}
}
}

return false;
}