Link to: header | source
2 | transactions
directory
Copyright Turtle Creek Software 1996-2006. All Rights Reserved.
Comments
CLaborLog
This class manages employee hours for the Goldenseal accounting software,
time tracking software, construction
project management software and
payroll software.
It's a record of employee hours. This is the raw material for the Goldenseal
payroll software and time tracking-- it generates the wage or salary amount.
We also use labor hours records for job costing and for t&m billing.
They are are a general record of which employee did what where.
SUPERCLASS = CTimeLog
Constructor
/*********************************************************************************
constructor
*********************************************************************************/
CLaborLog::CLaborLog()
{
mWageSchedule = 0;
mTMBillingRate = mJobCostRate = 0;
mBillingAmount = mBurdenAmount = 0;
mWageRateAmount = 0;
mDaysWorked = 1; // rev TCS 9/26/00
mOvertimeType = condition_None;
mStatus = status_Entered; // bugfix TCS 2/23/00
mMainAccountClass = id_EmployeeAccount;
mConditions = condition_None;
mPayrollRecord = 0;
mWageBreakdownID = 0;
mStartDate.SetToToday();
mEndDate.SetToToday();
mEndSafetyTag = tag_endsafetytag; // TCS 9/8/02
}
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 CLaborLog::CopyFrom(DB_PersistentObject *source, const UInt8 copyFlags)
{
THE_SUPERCLASS::CopyFrom(source, copyFlags);
CLaborLog *src = TCS_SAFE_CAST(source, CLaborLog);
TCS_FailNILMsg(src, TCS_GetErrString(errID_BadRecord));
NeoVersion version = GetVersion();
if (version > 3) // TCS 4/20/04
TCS_BlockMove(&src->mWageSchedule, &mWageSchedule, cCopyFileLength4);
else
TCS_BlockMove(&src->mWageSchedule, &mWageSchedule, cCopyFileLength);
if (HasLockedStatus()) // TCS 2/2/99
mStatus = GetStarterStatus(); // rev TCS 3/8/00
}
/*********************************************************************************
GetFileLength rev TCS 8/31/01
return the file length used by this object
*********************************************************************************/
NeoSize CLaborLog::GetFileLength(const CNeoFormat *aFormat) const
{
NeoVersion version = GetVersion();
if (version > 3) // TCS 4/20/04
return THE_SUPERCLASS::GetFileLength(aFormat) + cFileLength4;
else
return THE_SUPERCLASS::GetFileLength(aFormat) + cFileLength;
}/*********************************************************************************
GetMemberValue
return the value of the member with the given tag
*********************************************************************************/
Boolean CLaborLog::GetMemberValue(const TagType aTag, const TagType aType,
void *aValue) const
{
CMoney amount = 0;
switch (aTag)
{
case tag_wagerate:
return ConvertObjectIDMember(mWageSchedule, id_WageSchedule, aValue, aType);
break;
case tag_payrecord:
return ConvertObjectIDMember(mPayrollRecord, id_PayrollRecord, aValue, aType);
break;
case tag_jobcostrate:
return ConvertObjectIDMember(mJobCostRate, id_LaborBillingRate, aValue, aType);
break;
case tag_breakdownref:
return ConvertObjectIDMember(mWageBreakdownID, id_WagesBreakdownEntry, aValue, aType);
break;
case tag_billingrate:
return ConvertObjectIDMember(mTMBillingRate, id_LaborBillingRate, aValue, aType);
break;
case tag_timeunit:
return ConvertEnumMember(mTimeUnit, MENU_HourToYearTimeUnits, aValue, aType);
break;
case tag_overtimetype:
return ConvertEnumMember(mOvertimeType, MENU_LaborLogOvertime, aValue, aType);
break;
case tag_breakdown:
return ConvertEnumMember(mBreakdownType, MENU_TimeCatItemBreakdown, aValue, aType);
break;
case tag_status:
return ConvertEnumMember(mStatus, MENU_LaborLogStatus, aValue, aType);
break;
case tag_wageamount: // we calculate wage amount from regular amount
return ConvertMember(&mAmount, type_money, aValue, aType);
break;
case tag_actuallabor: // for job cost item reports TCS 4/15/02
return ConvertMember(&mJobCostAmount, type_money, aValue, aType);
break;
case tag_billingamount:
return ConvertMember(&mBillingAmount, type_money, aValue, aType);
break;
case tag_burdenamount:
return ConvertMember(&mBurdenAmount, type_money, aValue, aType);
break;
case tag_daysworked:
return ConvertMember(&mDaysWorked, type_number, aValue, aType);
break;
case tag_startdate: // TCS 4/20/04
return ConvertMember(&mStartDate, type_date, aValue, aType);
break;
case tag_enddate: // TCS 4/20/04
return ConvertMember(&mEndDate, type_date, aValue, aType);
break;
case tag_starttime: // TCS 4/20/04
return ConvertMember(&mStartDate, type_time, aValue, aType);
break;
case tag_endtime: // TCS 4/20/04
return ConvertMember(&mEndDate, type_time, aValue, aType);
break;
case tag_jobname: // we fetch the job name from the job account
{
CTextString jobName;
if (mJob && mJobClass)
{
DB_PersistentObject *job = gDBFile->GetOneObject(mJobClass, mJob);
if (job)
{
DB_ObjectWatcher watcher(job);
job->GetMemberValue(tag_name, type_cstring, &jobName);
}
}
return ConvertMember(&jobName, type_cstring, aValue, aType);
}
break;
case tag_overtimeamount: // overtime amount is calculated from wage rate
// this is the amount ADDED to base wage
amount = GetOvertimeAmount();
return ConvertMember(&amount, type_money, aValue, aType);
break;
case tag_overtimerate: // overtime rate is calculated from wage rate
// this is the total hourly rate including overtime
amount = GetOvertimeRate(time_hour);
return ConvertMember(&amount, type_money, aValue, aType);
break;
case tag_wagerateamount: // the actual wage rate amount per unit
if (mWageRateAmount.IsPositive()) // rev TCS 8/31/01
amount = mWageRateAmount;
else
amount = CalcWageRateAmount(mWageSchedule, mTimeUnit, mMainAccount);
return ConvertMember(&amount, type_money, aValue, aType);
break;
case tag_costarea: // calculated-- for reports // TCS 7/10/02
return ConvertEnumMember(costtype_labor, MENU_EstimateItemCostTypes, aValue, aType);
break;
default:
return THE_SUPERCLASS::GetMemberValue(aTag, aType, aValue);
break;
}
}/*********************************************************************************
SetMemberValue
set the value of the member with the given tag
*********************************************************************************/
Boolean CLaborLog::SetMemberValue(const TagType aTag, const TagType aType,
const void *aValue)
{
CDate date;
switch (aTag)
{
case tag_wagerate:
return ConvertDataToObjectID(aValue, aType, &mWageSchedule, id_WageSchedule);
break;
case tag_billingrate:
return ConvertDataToObjectID(aValue, aType, &mTMBillingRate, id_LaborBillingRate);
break;
case tag_payrecord:
return ConvertDataToObjectID(aValue, aType, &mPayrollRecord, id_PayrollRecord);
break;
case tag_breakdownref:
return ConvertMember(aValue, aType, &mWageBreakdownID, type_objectid);
break;
case tag_jobcostrate:
return ConvertDataToObjectID(aValue, aType, &mJobCostRate, id_LaborBillingRate);
break;
case tag_conditions:
return ConvertMember(aValue, aType, &mConditions, type_enum);
break;
case tag_status:
return ConvertMember(aValue, aType, &mStatus, type_enum);
break;
case tag_overtimetype: // TCS 1/12/00
return ConvertMember(aValue, aType, &mOvertimeType, type_enum);
break;
case tag_billingamount:
return ConvertMember(aValue, aType, &mBillingAmount, type_money);
break;
case tag_wagerateamount: // TCS 8/31/01
return ConvertMember(aValue, aType, &mWageRateAmount, type_money);
break;
case tag_burdenamount:
return ConvertMember(aValue, aType, &mBurdenAmount, type_money);
break;
case tag_daysworked: // TCS 3/31/00
return ConvertMember(aValue, aType, &mDaysWorked, type_number);
break;
case tag_startdate: // TCS 4/20/04
if (ConvertMember(aValue, aType, &date, type_date))
{
mStartDate.SetDate(date);
return true;
}
else
return false;
break;
case tag_enddate: // TCS 4/20/04
if (ConvertMember(aValue, aType, &date, type_date))
{
mEndDate.SetDate(date);
return true;
}
else
return false;
break;
case tag_starttime: // TCS 4/20/04
if (ConvertMember(aValue, aType, &date, type_time))
{
mStartDate.SetTime(date);
return true;
}
else
return false;
break;
case tag_endtime: // TCS 4/20/04
if (ConvertMember(aValue, aType, &date, type_time))
{
mEndDate.SetTime(date);
return true;
}
else
return false;
break;
case tag_overtimeamount: // calculated, no need to set
case tag_overtimerate:
return true;
break;
default:
return THE_SUPERCLASS::SetMemberValue(aTag, aType, aValue);
break;
}
}/*********************************************************************************
ReadObject
read the persistent object's data in from a stream
*********************************************************************************/
void CLaborLog::ReadObject(CNeoStream *aStream, const TagType aTag)
{
TCS_FailNILMsg(aStream, TCS_GetErrString(errID_BadStream));
CNeoDebugImport checker(aStream, this, cCheckTooSmall); // TCS 2/24/00
THE_SUPERCLASS::ReadObject(aStream, aTag);
if (!IsIOValid()) // TCS 2/5/02
return;
NeoVersion version = GetVersion();
mWageSchedule = aStream->ReadID(); // mfs_sa rev 20feb2k3
mTMBillingRate = aStream->ReadID();
mJobCostRate = aStream->ReadID();
mBillingAmount.ReadFromStream(aStream);
mDaysWorked.ReadFromStream(aStream);
mWageRateAmount.ReadFromStream(aStream);
mOvertimeType = aStream->ReadChar();
mStatus = aStream->ReadChar();
if (version > 3) // TCS 4/20/04
{
mStartDate.ReadFromStream(aStream);
mEndDate.ReadFromStream(aStream);
}
mBurdenAmount.ReadFromStream(aStream);
mPayrollRecord = aStream->ReadID();
mWageBreakdownID = aStream->ReadID();
mEndSafetyTag = aStream->ReadEndSafetyTag(this);
if (!IsValidEndTag(mEndSafetyTag)) // TCS 9/8/02
ReportDamagedObject(GetDBClassID(), GetDBID());
}/*********************************************************************************
WriteObject
write the persistent object's data to a stream
*********************************************************************************/
void CLaborLog::WriteObject(CNeoStream *aStream, const TagType aTag)
{
TCS_FailNILMsg(aStream, TCS_GetErrString(errID_BadStream));
// make sure we have valid data to write TCS 9/8/02
if (!IsValidEndTag(mEndSafetyTag))
{
ReportDamagedObject(GetDBClassID(), GetDBID());
mEndSafetyTag = tag_endsafetytag; // TCS 11/26/02
}
CNeoDebugExport checker(aStream, this, cCheckTooSmall);
THE_SUPERCLASS::WriteObject(aStream, aTag);
NeoVersion version = GetVersion();
aStream->WriteID(mWageSchedule); // mfs_sa rev 20feb2k3
aStream->WriteID(mTMBillingRate);
aStream->WriteID(mJobCostRate);
mBillingAmount.WriteToStream(aStream);
mDaysWorked.WriteToStream(aStream);
mWageRateAmount.WriteToStream(aStream);
aStream->WriteChar(mOvertimeType);
aStream->WriteChar(mStatus);
if (version > 3) // TCS 4/20/04
{
mStartDate.WriteToStream(aStream);
mEndDate.WriteToStream(aStream);
}
mBurdenAmount.WriteToStream(aStream);
aStream->WriteID(mPayrollRecord);
aStream->WriteID(mWageBreakdownID);
aStream->WriteEndSafetyTag(mEndSafetyTag, this);
}
#if CAN_USE_MARK
#pragma mark -
#endif
/*********************************************************************************
FinishViewerCreate TCS 1/19/04
fill in values after creation
*********************************************************************************/
void CLaborLog::FinishViewerCreate()
{
// let the superclass do its stuff
THE_SUPERCLASS::FinishViewerCreate();
// for labor-only, fill in the employee ID and other info.
if (gDBFile->LaborHoursOnly())
{
FinishNonViewerCreate();
}
}
/*********************************************************************************
FinishTemplateCreate TCS 1/19/04
fill in values after creation from a template or recurring transaction.
*********************************************************************************/
void CLaborLog::FinishTemplateCreate()
{
if (gDBFile->LaborHoursOnly())
{
// for labor-only, fill in the employee ID and related info.
// we can do that via our existing method for non viewers
FinishNonViewerCreate();
}
else
THE_SUPERCLASS::FinishTemplateCreate();
}
/*********************************************************************************
FinishNonViewerCreate
fill in values after creation from an AFW drag
*********************************************************************************/
void CLaborLog::FinishNonViewerCreate()
{
// let the superclass do its stuff
THE_SUPERCLASS::FinishNonViewerCreate();
// for labor-only, fill in the employee ID TCS 1/19/04
if (gDBFile->LaborHoursOnly())
{
mMainAccount = gDBFile->GetEmployeeID();
}
// the reference number must always be equal to the object id
mReferenceNum = GetDBID();
DB_Account *account =
TCS_SAFE_CAST(gDBFile->GetOneObject(mMainAccountClass, mMainAccount),
DB_Account);
if (account)
{ // there is an account, so we can proceed
DB_ObjectWatcher watcher(account);
// update the wage schedule field
if (!mWageSchedule)
account->GetMemberValue(tag_wagerate, type_objectid, &mWageSchedule);
// update the billing rate field moved TCS 9/29/02
if (!mTMBillingRate)
account->GetMemberValue(tag_billingrate, type_objectid, &mTMBillingRate);
// update the job cost rate field
if (!mJobCostRate)
account->GetMemberValue(tag_jobcostrate, type_objectid, &mJobCostRate);
// no need to set billing amount or t&m amount, since both start at zero
}
// calculate the wage amount rev TCS 4/26/00
mAmount = CalculateWageAmount(mTimeUsed, mMainAccount,
mTimeUnit, mWageSchedule, mOvertimeType, mDaysWorked);
// calculate the t&m billing amount
mBillingAmount = CalculateTMBillingAmount(id_LaborHours, mTimeUsed, mMainAccount,
mTimeUnit, mTMBillingRate, mAmount, 0);
// calculate the job cost amount TCS 6/12/02
mJobCostAmount = CalculateJobCostAmount(id_LaborHours, mTimeUsed, mMainAccount,
mTimeUnit, mJobCostRate, mAmount, 0);
}
/*********************************************************************************
FinishImportCreate rev TCS 8/11/99
fill in values after creation from an import
*********************************************************************************/
void CLaborLog::FinishImportCreate()
{
// let the superclass do its stuff
THE_SUPERCLASS::FinishImportCreate();
// we used to recalc the wage amount and billing amount, but that causes
// problems if wage rate has changed. TCS removed 5/9/02
}
/*********************************************************************************
FinishBreakdownUpdate TCS 4/17/01 rev 2/22/02 rev 1/25/03 removed 6/10/03 rev 2/18/04
If there is no cost area column, we fill in the cost type
*********************************************************************************/
void CLaborLog::FinishBreakdownUpdate(CBreakdownEntry *breakdown, CBreakdownTable *table)
{
TCS_FailNILMsg(breakdown, TCS_GetErrString(errID_BadBreakdown));
TCS_FailNILMsg(table, TCS_GetErrString(errID_BadTable));
if (!table->HasColumn(tag_costarea))
{
UInt8 costArea = costtype_labor;
breakdown->SetMemberValue(tag_costarea, type_enum, &costArea);
}
}
#if CAN_USE_MARK
#pragma mark -
#endif
/*********************************************************************************
PostNewRecord TCS 11/21/03
post info for a new record
*********************************************************************************/
void CLaborLog::PostNewRecord(const UInt8 creationType)
{
PostUseCount(id_WageSchedule, mWageSchedule);
PostUseCount(id_LaborBillingRate, mTMBillingRate);
PostUseCount(id_LaborBillingRate, mJobCostRate);
// let the superclass do any posting
THE_SUPERCLASS::PostNewRecord(creationType);
}
/*********************************************************************************
PostDeletion TCS 11/21/03
post info from a deleted record
*********************************************************************************/
void CLaborLog::PostDeletion(const Boolean postAudit)
{
PostUseCount(id_WageSchedule, mWageSchedule, cRemoveItem);
PostUseCount(id_LaborBillingRate, mTMBillingRate, cRemoveItem);
PostUseCount(id_LaborBillingRate, mJobCostRate, cRemoveItem);
// let the superclass do any posting
THE_SUPERCLASS::PostDeletion(postAudit);
}
/*********************************************************************************
PostRecordChanging TCS 11/21/03
a record will be changing. Post the change.
*********************************************************************************/
void CLaborLog::PostRecordChanging(const Boolean accountChanging, const Boolean jobChanging)
{
PostUseCount(id_WageSchedule, mWageSchedule, cRemoveItem);
PostUseCount(id_LaborBillingRate, mTMBillingRate, cRemoveItem);
PostUseCount(id_LaborBillingRate, mJobCostRate, cRemoveItem);
// let the superclass do any posting
THE_SUPERCLASS::PostRecordChanging(accountChanging, jobChanging);
}
/*********************************************************************************
PostRecordChanged TCS 11/21/03
a record has changed. Post it.
*********************************************************************************/
void CLaborLog::PostRecordChanged(const CMoney &oldAmount, const Boolean accountChanged,
const Boolean jobChanged)
{
PostUseCount(id_WageSchedule, mWageSchedule);
PostUseCount(id_LaborBillingRate, mTMBillingRate);
PostUseCount(id_LaborBillingRate, mJobCostRate);
// let the superclass do any posting
THE_SUPERCLASS::PostRecordChanged(oldAmount, accountChanged, jobChanged);
}
#if CAN_USE_MARK
#pragma mark -
#endif
/*********************************************************************************
PostExpenseAccount TCS 12/5/00
post this transaction to a general ledger expense account. We override
since we need to reset the account if the wage rate has changed.
*********************************************************************************/
void CLaborLog::PostExpenseAccount(const Boolean removeItem)
{
// if this goes to a stock account, reset the account, just in
// case the wage type has changed
if (mExpenseAccount == account_LaborExpenses || mExpenseAccount == account_OwnerHours ||
mExpenseAccount == account_SweatEquity)
{
mExpenseAccount = GetDefaultExpenseAccount();
MakeDirty();
}
// pass it along
THE_SUPERCLASS::PostExpenseAccount(removeItem);
}
/*********************************************************************************
PostPayablesAccount TCS moved 4/25/01
post this transaction to a payables utility account. We override, since
we always post
*********************************************************************************/
void CLaborLog::PostPayablesAccount(const Boolean removeItem)
{
CUtilityAccount::AddToActiveArray(account_UnpaidLaborHrs, this, removeItem);
}
|