Accounting Software
Small Business Software Estimating Software
Time Tracking SoftwareTime Management SoftwareTime Billing SoftwareProject Management SoftwareBookkeeping SoftwareContact Management SoftwareBusiness Management Software

Wage Schedules (Source Code)

Link to: header | lists directory

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

Comments

CWageSchedule

an employee wage schedule. Includes wage and payday information, wage
rate and other payroll details. Each employee has a primary wage schedule,
but it is possible to assign a different wage rate in each Labor Hours record.

This class manages employee wages for the Goldenseal accounting software,
time tracking software and payroll software.

SUPERCLASS = CCommission

Constructor

/*********************************************************************************
default constructor
*********************************************************************************/
CWageSchedule::CWageSchedule()
{
mWageType = wage_hourly;
mWageUnit = time_hour; // override

mDailyOTType = mWeeklyOTType = over_timehalf;
mSaturdayOTType = over_timehalf;
mSundayOTType = over_doubletime;

mDailyOTRate = mWeeklyOTRate = mSaturdayOTRate = 1.5;
mSundayOTRate = 2;
mDailyOTLimit = 8;
mWeeklyOTLimit = 40;

mUseVariableWage = true; // rev TCS 11/9/99

mWageEndSafetyTag = 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 CWageSchedule::CopyFrom(DB_PersistentObject *source, const UInt8 copyFlags)
{
THE_SUPERCLASS::CopyFrom(source, copyFlags);

CWageSchedule *src = TCS_SAFE_CAST(source, CWageSchedule);
TCS_FailNILMsg(src, TCS_GetErrString(errID_BadRecord));

TCS_BlockMove(&src->mDailyOTRate, &mDailyOTRate, cCopyFileLength);
}/*********************************************************************************

GetMemberValue

return the value of the member with the given tag

*********************************************************************************/
Boolean CWageSchedule::GetMemberValue(const NeoTag aTag, const NeoTag aType,
void *aValue) const
{
switch (aTag)
{
case tag_wagetype:
return ConvertEnumMember(mWageType, MENU_PayrollWageTypes, aValue, aType);
break;

case tag_dailyOTtype:
return ConvertEnumMember(mDailyOTType, MENU_PayrollOvertimeTypes, aValue, aType);
break;

case tag_weeklyOTtype:
return ConvertEnumMember(mWeeklyOTType, MENU_PayrollOvertimeTypes, aValue, aType);
break;

case tag_satOTtype:
return ConvertEnumMember(mSaturdayOTType, MENU_PayrollOvertimeTypes, aValue, aType);
break;

case tag_sunOTtype:
return ConvertEnumMember(mSundayOTType, MENU_PayrollOvertimeTypes, aValue, aType);
break;

case tag_wageunit: // we override since menu is different
if (mWageType == wage_bonus)
return ConvertEnumMember(mWageUnit, MENU_PayrollBonusTypes, aValue, aType);
else
return ConvertEnumMember(mWageUnit, MENU_PerDayToYear, aValue, aType);
break;

case tag_dailyOTlimit:
return ConvertMember(&mDailyOTLimit, type_long, aValue, aType);
break;

case tag_weeklyOTlimit:
return ConvertMember(&mWeeklyOTLimit, type_long, aValue, aType);
break;

case tag_dailyOTrate:
return ConvertMember(&mDailyOTRate, type_money, aValue, aType);
break;

case tag_weeklyOTrate:
return ConvertMember(&mWeeklyOTRate, type_money, aValue, aType);
break;

case tag_satOTrate:
return ConvertMember(&mSaturdayOTRate, type_money, aValue, aType);
break;

case tag_sunOTrate:
return ConvertMember(&mSundayOTRate, type_money, aValue, aType);
break;

default:
return THE_SUPERCLASS::GetMemberValue(aTag, aType, aValue);
break;
}
}/*********************************************************************************

SetMemberValue

set the value of the member with the given tag

*********************************************************************************/
Boolean CWageSchedule::SetMemberValue(const NeoTag aTag, const NeoTag aType,
const void *aValue)
{
switch (aTag)
{
case tag_dailyOTlimit:
return ConvertMember(aValue, aType, &mDailyOTLimit, type_long);
break;

case tag_weeklyOTlimit:
return ConvertMember(aValue, aType, &mWeeklyOTLimit, type_long);
break;

case tag_dailyOTtype:
return ConvertMember(aValue, aType, &mDailyOTType, type_enum);
break;

case tag_weeklyOTtype:
return ConvertMember(aValue, aType, &mWeeklyOTType, type_enum);
break;

case tag_satOTtype:
return ConvertMember(aValue, aType, &mSaturdayOTType, type_enum);
break;

case tag_sunOTtype:
return ConvertMember(aValue, aType, &mSundayOTType, type_enum);
break;

case tag_dailyOTrate:
return ConvertMember(aValue, aType, &mDailyOTRate, type_money);
break;

case tag_weeklyOTrate:
return ConvertMember(aValue, aType, &mWeeklyOTRate, type_money);
break;

case tag_satOTrate:
return ConvertMember(aValue, aType, &mSaturdayOTRate, type_money);
break;

case tag_sunOTrate:
return ConvertMember(aValue, aType, &mSundayOTRate, type_money);
break;

default:
return THE_SUPERCLASS::SetMemberValue(aTag, aType, aValue);
break;
}
}/*********************************************************************************

ReadObject

read the persistent object's data in from a stream
*********************************************************************************/
void CWageSchedule::ReadObject(CNeoStream *aStream, const NeoTag 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;

/// aStream->ReadChunk(&mDailyOTRate, cFileLength);

mDailyOTRate.ReadFromStream(aStream); // mfs_sa rev 20feb2k3
mWeeklyOTRate.ReadFromStream(aStream);
mSaturdayOTRate.ReadFromStream(aStream);
mSundayOTRate.ReadFromStream(aStream);

mDailyOTLimit = aStream->ReadLong();
mWeeklyOTLimit = aStream->ReadLong();

mDailyOTType = aStream->ReadChar();
mWeeklyOTType = aStream->ReadChar();
mSaturdayOTType = aStream->ReadChar();
mSundayOTType = aStream->ReadChar();

mWageEndSafetyTag = aStream->ReadEndSafetyTag(this);

// validate the object end marker TCS 9/8/02
if (!IsValidEndTag(mWageEndSafetyTag))
ReportDamagedObject(GetDBClassID(), GetDBID());
}/*********************************************************************************

WriteObject

write the persistent object's data to a stream
*********************************************************************************/
void CWageSchedule::WriteObject(CNeoStream *aStream, const NeoTag aTag)
{
TCS_FailNILMsg(aStream, TCS_GetErrString(errID_BadStream));

// make sure we have valid data to write TCS 9/8/02
if (!IsValidEndTag(mWageEndSafetyTag))
{
ReportDamagedObject(GetDBClassID(), GetDBID());
mWageEndSafetyTag = tag_endsafetytag; // TCS 11/26/02
}

CNeoDebugExport checker(aStream, this, cCheckTooSmall);
THE_SUPERCLASS::WriteObject(aStream, aTag);

/// aStream->WriteChunk(&mDailyOTRate, cFileLength);

mDailyOTRate.WriteToStream(aStream); // mfs_sa rev 20feb2k3
mWeeklyOTRate.WriteToStream(aStream);
mSaturdayOTRate.WriteToStream(aStream);
mSundayOTRate.WriteToStream(aStream);

aStream->WriteLong(mDailyOTLimit);
aStream->WriteLong(mWeeklyOTLimit);

aStream->WriteChar(mDailyOTType);
aStream->WriteChar(mWeeklyOTType);
aStream->WriteChar(mSaturdayOTType);
aStream->WriteChar(mSundayOTType);

aStream->WriteEndSafetyTag(mWageEndSafetyTag, this);

}
#if CAN_USE_MARK
#pragma mark -
#endif
/*********************************************************************************

GetTableColInfo

return information about table columns. We need to have a separate copy of
the descriptor here. All of the i/o functions for the table are in the
superclass, CCommission.
*********************************************************************************/
Boolean CWageSchedule::CWageRate_Desc::GetTableColInfo(const TagType tag,
const TableIndexT col,
STableColInfo *colInfo)
{
if (tag == tag_paydaytable)
{
switch (col)
{
case col_startdate:
colInfo->colType = coltype_caption;
colInfo->fieldType = fieldtype_date;
colInfo->colData = 0;
TCS_BufferFromText(colInfo->colName,
TCS_GetStockString(stockID_PeriodStart), cTableColNameLength);
return true;
break;

case col_enddate:
colInfo->colType = coltype_caption;
colInfo->fieldType = fieldtype_date;
colInfo->colData = 0;
TCS_BufferFromText(colInfo->colName,
TCS_GetStockString(stockID_PeriodEnd), cTableColNameLength);
return true;
break;

case col_payday:
colInfo->colType = coltype_caption;
colInfo->fieldType = fieldtype_date;
colInfo->colData = 0;
TCS_BufferFromText(colInfo->colName,
TCS_GetStockString(stockID_Payday), cTableColNameLength);
return true;
break;

case col_paid:
colInfo->colType = coltype_caption;
colInfo->fieldType = fieldtype_string;
colInfo->colData = 0;
TCS_BufferFromText(colInfo->colName,
TCS_GetStockString(stockID_Pd), cTableColNameLength);
return true;
break;

default:
return false;
break;
}
}
else
return false;
}
#if CAN_USE_MARK
#pragma mark -
#endif
/*********************************************************************************

CanImportEnum TCS 9/14/99

is the given imported value OK? We override because of problems getting enum
for the wage unit field

*********************************************************************************/
Boolean CWageSchedule::CanImportEnum(const TagType tag, const SInt32 value) const
{
if (tag == tag_wageunit)
{
// we don't have menu enum info, so we just accept any value
return true;
}
else
return THE_SUPERCLASS::CanImportEnum(tag, value);
}
/*********************************************************************************

GetEnumMenuID TCS 6/13/99

return the id of the menu used for the given tag

*********************************************************************************/
ResIDT CWageSchedule::GetEnumMenuID(const TagType tag, const Boolean importing) const
{
switch (tag)
{
case tag_wagetype:
return MENU_PayrollWageTypes;
break;

case tag_wageunit:
switch (mWageType)
{
case wage_bonus:
return MENU_PayrollBonusTypes;
break;

case wage_hourly:
case wage_ownerhourly:
case wage_hourlyequity:
return MENU_PerHour;
break;

case wage_salary:
case wage_ownersalary:
case wage_salaryequity:
default:
return MENU_PerDayToYear;
break;
}

default:
break;
}

return THE_SUPERCLASS::GetEnumMenuID(tag, importing);
}
#if CAN_USE_MARK
#pragma mark -
#endif
/*********************************************************************************

GetWageForPeriod TCS 11/20/01

return the wage amount for one pay period. For an hourly rate this is
the hourly rate, for a salary it's the base amount divided by the period size

*********************************************************************************/
CMoney CWageSchedule::GetWageForPeriod(const CMoney &employeeAmount) const
{
CMoney amount;

if (HasVariableRate())
amount = employeeAmount;
else
amount = GetBaseWage();

if (mWageType == wage_salary || mWageType == wage_ownersalary ||
mWageType == wage_salaryequity) // bugfix TCS 2/9/04
{
amount.AdjustForPeriod(mWageUnit, mPayPeriod);
}

return amount;
}
/*********************************************************************************

GetWagesWithOvertime TCS 8/24/99

compute the amount of wages for a given time quantity. This form can be used for
inputs using any time unit

*********************************************************************************/
CMoney CWageSchedule::GetWagesWithOvertime(const CMoney &timeAmount, const UInt8 timeUnit,
const CMoney &wageRate, const UInt8 conditions,
const CMoney &daysWorked) const
{
CMoney hours, overtimeHrs, hourlyWage;

// we may need to convert the basic time unit
if (timeUnit == time_hour)
hours = timeAmount;
else
hours = timeAmount * CDate::GetWorkTimeConversion(timeUnit, time_hour);

// if we weren't passed a wage rate, use the stock rate rev TCS 4/26/00
if (wageRate.IsPositive())
hourlyWage = wageRate;
else
hourlyWage = mBaseWage;

// we may need to convert time units TCS 9/3/99
if (mWageUnit == time_hour)
hourlyWage = hourlyWage;
else
hourlyWage = hourlyWage * CDate::GetWorkTimeConversion(time_hour, mWageUnit);

CMoney baseAmount = hours * hourlyWage;

// figure the amount with overtime rev TCS 7/17/00
switch (conditions)
{
case condition_Overtime: // all at overtime rate
return baseAmount + GetOvertimeAmount(hours, hourlyWage, mDailyOTType, mDailyOTRate);
break;

case condition_SaturdayRate: // all at saturday rate
return baseAmount + GetOvertimeAmount(hours, hourlyWage, mSaturdayOTType, mSaturdayOTRate);
break;

case condition_SundayRate: // all at sunday rate
return baseAmount + GetOvertimeAmount(hours, hourlyWage, mSundayOTType, mSundayOTRate);
break;

case condition_NoOvertime: // no overtime
case condition_AddCompTime: // rev TCS 6/15/02
case condition_UseCompTime:
case condition_UseHoliday: // no overtime for holidays and vacations
case condition_UseSickTime:
case condition_UseVacation:
case condition_UseOtherVacation:
return baseAmount;
break;

default: // overtime only on amount > daily cutoff TCS 8/24/99
{
if (daysWorked.IsPositive())
overtimeHrs = hours - (daysWorked * mDailyOTLimit); // rev TCS 4/26/00
else
return baseAmount; // if no days worked, don't figure any overtime TCS 7/17/00

if (overtimeHrs.IsPositive())
{
return baseAmount + // bugfix TCS 7/17/00
GetOvertimeAmount(overtimeHrs, hourlyWage, mDailyOTType, mDailyOTRate);
}
else
return baseAmount;
}
break;
}
}
/*********************************************************************************

GetOvertimeRate TCS 8/25/99

return the rate per hour for overtime work

*********************************************************************************/
CMoney CWageSchedule::GetOvertimeRate(const UInt8 conditions, const UInt8 inTimeUnit,
const CMoney &accountRate) const
{
CMoney wageRate, hourlyRate;

if (accountRate.IsZero())
wageRate = mBaseWage;
else
wageRate = accountRate;

UInt8 timeUnit;
if (inTimeUnit)
timeUnit = inTimeUnit;
else
timeUnit = time_hour;

// adjust for different time periods TCS 9/6/99
hourlyRate = wageRate * CDate::GetWorkTimeConversion(timeUnit, mWageUnit);

switch (conditions)
{
case condition_Overtime: // basic overtime rate
case condition_None:
default:
return GetOvertimeRate(hourlyRate, mDailyOTType, mDailyOTRate);
break;

case condition_SaturdayRate: // all at saturday rate
return GetOvertimeRate(hourlyRate, mSaturdayOTType, mSaturdayOTRate);
break;

case condition_SundayRate: // all at sunday rate
return GetOvertimeRate(hourlyRate, mSundayOTType, mSundayOTRate);
break;

case condition_NoOvertime:
case condition_AddCompTime: // rev TCS 6/15/02
case condition_UseCompTime:
case condition_UseHoliday: // no overtime for holidays and vacations
case condition_UseSickTime:
case condition_UseVacation:
case condition_UseOtherVacation:
return wageRate;
break;
}
}
/*********************************************************************************

GetOvertimeRate TCS 8/25/99

calculate the overtime rate for the given wage rate and calc parameters

*********************************************************************************/
CMoney CWageSchedule::GetOvertimeRate(const CMoney &wageRate, const UInt8 OTType,
const CMoney &OTRate) const
{
switch (OTType)
{
case over_timehalf:
return wageRate * 1.5;
break;

case over_doubletime:
return wageRate + wageRate;
break;

case over_othermultiple:
return wageRate * OTRate;
break;

case over_additional:
return wageRate + OTRate;
break;

case over_straight:
return wageRate;
break;

default:
TCS_DebugAlert("Oops, bad case in CWageSchedule::GetOvertimeRate!");
return wageRate;
break;
}
}
/*********************************************************************************

GetOvertimeAmount rev TCS 8/25/99

calculate the total overtime amount for the given number of overtime hours,
wage rate and calc parameters. This is the amount that is ADDED to the base
wage(revised TCS 7/17/00)

Note that if only some hours get overtime, that processing must happen
before this method is called.

*********************************************************************************/
CMoney CWageSchedule::GetOvertimeAmount(const CMoney &hours, const CMoney &wageRate,
const UInt8 OTType, const CMoney &OTRate) const
{
switch (OTType)
{
case over_timehalf: // revised TCS 7/17/00
return wageRate * hours / 2;
break;

case over_doubletime:
return wageRate * hours;
break;

case over_othermultiple:
return wageRate * hours *(OTRate - 1);
break;

case over_additional:
return OTRate * hours;
break;

case over_straight:
return 0;
break;

default:
TCS_DebugAlert("Oops, bad case in CWageSchedule::GetOvertimeAmount!");
return 0;
break;
}
}
/*********************************************************************************

GetOvertimeCutoff TCS 12/10/98

return the number of hours in this pay period when overtime kicks in

*********************************************************************************/
SInt32 CWageSchedule::GetWeeklyOvertimeCutoff() const
{
if (mWageType == wage_hourly || mWageType == wage_hourlyequity)
{
switch (mPayPeriod)
{
case time_irregular:
return 0;
break;

case time_day:
return mWeeklyOTLimit / 5;
break;

case time_week:
return mWeeklyOTLimit;
break;

case time_twoweeks:
return mWeeklyOTLimit * 2;
break;

case time_halfmonth:
return mWeeklyOTLimit * 2.1666;
break;

case time_fourweeks:
return mWeeklyOTLimit * 4;
break;

case time_month:
return mWeeklyOTLimit * 4.3333;
break;

default:
return 0;
break;

}
}
else // we don't deal with overtime for salary etc
return 0;
}
#if CAN_USE_MARK
#pragma mark -
#endif
/*********************************************************************************

FillDataReport TCS 9/7/02

fill in a diagnostic table that shows data field values.

*********************************************************************************/
void CWageSchedule::FillDataReport(CTCS_Table *table, CNeoStream *stream) const
{
TCS_FailNILMsg(table, TCS_GetErrString(errID_BadTable));
TCS_FailNILMsg(stream, TCS_GetErrString(errID_BadStream));

THE_SUPERCLASS::FillDataReport(table, stream);

FillFieldTagRow(table, stream, tag_dailyOTrate, cMoneySize, mDailyOTRate.GetNumberString());
FillFieldTagRow(table, stream, tag_weeklyOTrate, cMoneySize, mWeeklyOTRate.GetNumberString());
FillFieldTagRow(table, stream, tag_satOTrate, cMoneySize, mSaturdayOTRate.GetNumberString());
FillFieldTagRow(table, stream, tag_sunOTrate, cMoneySize, mSundayOTRate.GetNumberString());

FillFieldTagRow(table, stream, tag_dailyOTlimit, cLongSize, mDailyOTLimit);
FillFieldTagRow(table, stream, tag_weeklyOTlimit, cLongSize, mWeeklyOTLimit);

FillFieldEnumRow(table, stream, tag_dailyOTtype, mDailyOTType, MENU_PayrollOvertimeTypes);
FillFieldEnumRow(table, stream, tag_weeklyOTtype, mWeeklyOTType, MENU_PayrollOvertimeTypes);
FillFieldEnumRow(table, stream, tag_sunOTtype, mSaturdayOTType, MENU_PayrollOvertimeTypes);
FillFieldEnumRow(table, stream, tag_sunOTtype, mSundayOTType, MENU_PayrollOvertimeTypes);

FillEndSafetyTag(table, stream, mWageEndSafetyTag);
}