Ejemplo n.º 1
0
		public static Employee CreateEmployee(string prefix){
			Employee emp=new Employee();
			emp.ClockStatus="Home";
			emp.FName=prefix+"Bob";
			emp.LName=prefix+"Boberson";
			emp.MiddleI=prefix+"Bobbity";
			Employees.Insert(emp);
			return emp;
		}
Ejemplo n.º 2
0
		///<summary>Only called from Chart for now.  No validation is performed here.  Validate before calling.  There are many validtion checks, including the NPI must be exactly 10 digits.</summary>
		public static string BuildClickThroughXml(Provider prov,Employee emp,Patient pat) {
			NCScript ncScript=new NCScript();
			ncScript.Credentials=new CredentialsType();
			ncScript.Credentials.partnerName=NewCropPartnerName;
			ncScript.Credentials.name=NewCropAccountName;
			ncScript.Credentials.password=NewCropAccountPasssword;
			ncScript.Credentials.productName=NewCropProductName;
			ncScript.Credentials.productVersion=NewCropProductVersion;
			ncScript.UserRole=new UserRoleType();
			if(emp==null) {
				ncScript.UserRole.user=UserType.LicensedPrescriber;
				ncScript.UserRole.role=RoleType.doctor;
			}
			else {
				ncScript.UserRole.user=UserType.Staff;
				ncScript.UserRole.role=RoleType.nurse;
			}
			ncScript.Destination=new DestinationType();
			ncScript.Destination.requestedPage=RequestedPageType.compose;//This is the tab that the user will want 90% of the time.
			string practiceTitle=PrefC.GetString(PrefName.PracticeTitle);//May be blank.
			string practicePhone=PrefC.GetString(PrefName.PracticePhone);//Validated to be 10 digits within the chart.
			string practiceFax=PrefC.GetString(PrefName.PracticeFax);//Validated to be 10 digits within the chart.
			string practiceAddress=PrefC.GetString(PrefName.PracticeAddress);//Validated to exist in chart.
			string practiceAddress2=PrefC.GetString(PrefName.PracticeAddress2);//May be blank.
			string practiceCity=PrefC.GetString(PrefName.PracticeCity);//Validated to exist in chart.
			string practiceState=PrefC.GetString(PrefName.PracticeST);//Validated to be a US state code in chart.
			string practiceZip=Regex.Replace(PrefC.GetString(PrefName.PracticeZip),"[^0-9]*","");//Zip with all non-numeric characters removed. Validated to be 9 digits in chart.
			string practiceZip4=practiceZip.Substring(5);//Last 4 digits of zip.
			practiceZip=practiceZip.Substring(0,5);//First 5 digits of zip.
			string country="US";//Always United States for now.
			//if(CultureInfo.CurrentCulture.Name.Length>=2) {
			//  country=CultureInfo.CurrentCulture.Name.Substring(CultureInfo.CurrentCulture.Name.Length-2);
			//}
			ncScript.Account=new AccountTypeRx();
			//Each LicensedPrescriberID must be unique within an account. Since we send ProvNum for LicensedPrescriberID, each OD database must have a unique AccountID.
			ncScript.Account.ID=PrefC.GetString(PrefName.NewCropAccountId);//Customer account number then a dash then a random alpha-numeric string of 3 characters, followed by 2 digits.
			ncScript.Account.accountName=practiceTitle;//May be blank.
			ncScript.Account.siteID="1";//Always send 1.  For each AccountID/SiteID pair, a separate database will be created in NewCrop.
			ncScript.Account.AccountAddress=new AddressType();
			ncScript.Account.AccountAddress.address1=practiceAddress;//Validated to exist in chart.
			ncScript.Account.AccountAddress.address2=practiceAddress2;//May be blank.
			ncScript.Account.AccountAddress.city=practiceCity;//Validated to exist in chart.
			ncScript.Account.AccountAddress.state=practiceState;//Validated to be a US state code in chart.
			ncScript.Account.AccountAddress.zip=practiceZip;//Validated to be 9 digits in chart. First 5 digits go in this field.
			ncScript.Account.AccountAddress.zip4=practiceZip4;//Validated to be 9 digits in chart. Last 4 digits go in this field.
			ncScript.Account.AccountAddress.country=country;//Validated above.
			ncScript.Account.accountPrimaryPhoneNumber=practicePhone;//Validated to be 10 digits within the chart.
			ncScript.Account.accountPrimaryFaxNumber=practiceFax;//Validated to be 10 digits within the chart.
			ncScript.Location=new LocationType();
			if(PrefC.GetBool(PrefName.EasyNoClinics) || pat.ClinicNum==0) { //No clinics.
				ncScript.Location.ID="0";//Always 0, since clinicnums must be >= 1, will never overlap with a clinic if the office turns clinics on after first use.
				ncScript.Location.locationName=practiceTitle;//May be blank.
				ncScript.Location.LocationAddress=new AddressType();
				ncScript.Location.LocationAddress.address1=practiceAddress;//Validated to exist in chart.
				ncScript.Location.LocationAddress.address2=practiceAddress2;//May be blank.
				ncScript.Location.LocationAddress.city=practiceCity;//Validated to exist in chart.
				ncScript.Location.LocationAddress.state=practiceState;//Validated to be a US state code in chart.
				ncScript.Location.LocationAddress.zip=practiceZip;//Validated to be 9 digits in chart. First 5 digits go in this field.
				ncScript.Location.LocationAddress.zip4=practiceZip4;//Validated to be 9 digits in chart. Last 4 digits go in this field.
				ncScript.Location.LocationAddress.country=country;//Validated above.
				ncScript.Location.primaryPhoneNumber=practicePhone;//Validated to be 10 digits within the chart.
				ncScript.Location.primaryFaxNumber=practiceFax;//Validated to be 10 digits within the chart.
				ncScript.Location.pharmacyContactNumber=practicePhone;//Validated to be 10 digits within the chart.
			}
			else { //Using clinics.
				Clinic clinic=Clinics.GetClinic(pat.ClinicNum);
				ncScript.Location.ID=clinic.ClinicNum.ToString();//A positive integer.
				ncScript.Location.locationName=clinic.Description;//May be blank.
				ncScript.Location.LocationAddress=new AddressType();
				ncScript.Location.LocationAddress.address1=clinic.Address;//Validated to exist in chart.
				ncScript.Location.LocationAddress.address2=clinic.Address2;//May be blank.
				ncScript.Location.LocationAddress.city=clinic.City;//Validated to exist in chart.
				ncScript.Location.LocationAddress.state=clinic.State;//Validated to be a US state code in chart.
				string clinicZip=Regex.Replace(clinic.Zip,"[^0-9]*","");//Zip with all non-numeric characters removed. Validated to be 9 digits in chart.
				string clinicZip4=clinicZip.Substring(5);//Last 4 digits of zip.
				clinicZip=clinicZip.Substring(0,5);//First 5 digits of zip.
				ncScript.Location.LocationAddress.zip=clinicZip;//Validated to be 9 digits in chart. First 5 digits go in this field.
				ncScript.Location.LocationAddress.zip4=clinicZip4;//Validated to be 9 digits in chart. Last 4 digits go in this field.
				ncScript.Location.LocationAddress.country=country;//Validated above.
				ncScript.Location.primaryPhoneNumber=clinic.Phone;//Validated to be 10 digits within the chart.
				ncScript.Location.primaryFaxNumber=clinic.Fax;//Validated to be 10 digits within the chart.
				ncScript.Location.pharmacyContactNumber=clinic.Phone;//Validated to be 10 digits within the chart.
			}
			ncScript.LicensedPrescriber=new LicensedPrescriberType();
			//Each unique provider ID sent to NewCrop will cause a billing charge.
			//Some customer databases have provider duplicates, because they have one provider record per clinic with matching NPIs.
			//We send NPI as the ID to prevent extra NewCrop charges.
			//Conversation with NewCrop:
			//Question: If one of our customers clicks through to NewCrop with 2 different LicensedPrescriber.ID values, 
			//          but with the same provider name and NPI, will Open Dental be billed twice or just one time for the NPI used?
			//Answer:   "They would be billed twice. The IDs you send us should always be maintained and unique. 
			//          Users are always identified by LicensedPrescriber ID, since their name or credentials could potentially change."
			ncScript.LicensedPrescriber.ID=prov.NationalProvID;
			//UPIN is obsolete
			ncScript.LicensedPrescriber.LicensedPrescriberName=new PersonNameType();
			ncScript.LicensedPrescriber.LicensedPrescriberName.last=prov.LName.Trim();//Cannot be blank.
			ncScript.LicensedPrescriber.LicensedPrescriberName.first=prov.FName.Trim();//Cannot be blank.
			ncScript.LicensedPrescriber.LicensedPrescriberName.middle=prov.MI;//May be blank.
			ncScript.LicensedPrescriber.LicensedPrescriberName.suffix=PersonNameSuffix.DDS;//There is no blank or none option, so we have to pick a default value. DDS=0, so would be default anyway.
			string[] suffixes=prov.Suffix.ToUpper().Split(' ','.');
			for(int i=0;i<suffixes.Length;i++) {
				if(suffixes[i]=="I") {
					ncScript.LicensedPrescriber.LicensedPrescriberName.suffix=PersonNameSuffix.I;
					break;
				}
				else if(suffixes[i]=="II") {
					ncScript.LicensedPrescriber.LicensedPrescriberName.suffix=PersonNameSuffix.II;
					break;
				}
				else if(suffixes[i]=="III") {
					ncScript.LicensedPrescriber.LicensedPrescriberName.suffix=PersonNameSuffix.III;
					break;
				}
				else if(suffixes[i]=="JR") {
					ncScript.LicensedPrescriber.LicensedPrescriberName.suffix=PersonNameSuffix.Jr;
					break;
				}
				else if(suffixes[i]=="SR") {
					ncScript.LicensedPrescriber.LicensedPrescriberName.suffix=PersonNameSuffix.Sr;
					break;
				}
			}
			if(prov.DEANum.ToLower()=="none") {
				ncScript.LicensedPrescriber.dea="NONE";
			}
			else {
				ncScript.LicensedPrescriber.dea=prov.DEANum;
			}
			ncScript.LicensedPrescriber.licenseState=prov.StateWhereLicensed;//Validated to be a US state code in the chart.
			ncScript.LicensedPrescriber.licenseNumber=prov.StateLicense;//Validated to exist in chart.
			ncScript.LicensedPrescriber.npi=prov.NationalProvID;//Validated to be 10 digits in chart.
			//ncScript.LicensedPrescriber.freeformCredentials=;//This is where DDS and DMD should go, but we don't support this yet. Probably not necessary anyway.
			if(emp!=null) {
				ncScript.Staff=new StaffType();
				ncScript.Staff.ID="emp"+emp.EmployeeNum.ToString();//A positive integer. Returned in the ExternalUserID field when retreiving prescriptions from NewCrop. Also, provider ID is returned in the same field if a provider created the prescription, so that we can create a distintion between employee IDs and provider IDs.
				ncScript.Staff.StaffName=new PersonNameType();
				ncScript.Staff.StaffName.first=emp.FName;//First name or last name will not be blank. Validated in Chart.
				ncScript.Staff.StaffName.last=emp.LName;//First name or last name will not be blank. Validated in Chart.
				ncScript.Staff.StaffName.middle=emp.MiddleI;//May be blank.
			}
			ncScript.Patient=new PatientType();
			ncScript.Patient.ID=pat.PatNum.ToString();//A positive integer.
			ncScript.Patient.PatientName=new PersonNameType();
			ncScript.Patient.PatientName.last=pat.LName;//Validated to exist in Patient Edit window.
			ncScript.Patient.PatientName.first=pat.FName;//May be blank.
			ncScript.Patient.PatientName.middle=pat.MiddleI;//May be blank.
			ncScript.Patient.medicalRecordNumber=pat.PatNum.ToString();//A positive integer.
			//NewCrop specifically requested that we do not send SSN.
			//ncScript.Patient.socialSecurityNumber=Regex.Replace(pat.SSN,"[^0-9]*","");//Removes all non-numerical characters.
			ncScript.Patient.PatientAddress=new AddressOptionalType();
			ncScript.Patient.PatientAddress.address1=pat.Address;//May be blank.
			ncScript.Patient.PatientAddress.address2=pat.Address2;//May be blank.
			ncScript.Patient.PatientAddress.city=pat.City;//May be blank.
			ncScript.Patient.PatientAddress.state=pat.State;//May be blank. Validated in chart to be blank or to be a valid US state code.
			ncScript.Patient.PatientAddress.zip=pat.Zip;//May be blank.
			ncScript.Patient.PatientAddress.country=country;//Validated above.
			ncScript.Patient.PatientContact=new ContactType();
			ncScript.Patient.PatientContact.homeTelephone=pat.HmPhone;//May be blank. Does not need to be 10 digits.
			ncScript.Patient.PatientCharacteristics=new PatientCharacteristicsType();
			ncScript.Patient.PatientCharacteristics.dob=pat.Birthdate.ToString("yyyyMMdd");//DOB must be in CCYYMMDD format.
			if(pat.Gender==PatientGender.Male) {
				ncScript.Patient.PatientCharacteristics.gender=GenderType.M;
			}
			else if(pat.Gender==PatientGender.Female) {
				ncScript.Patient.PatientCharacteristics.gender=GenderType.F;
			}
			else {
				ncScript.Patient.PatientCharacteristics.gender=GenderType.U;
			}
			ncScript.Patient.PatientCharacteristics.genderSpecified=true;
			//NewCrop programmer's comments regarding other fields we are not currently using (these fields are sent back when fetching prescriptions in the Chart):
			//ExternalPrescriptionId = your unique identifier for the prescription, only to be used if you are generating the prescription on your own UI.
			//	This is referenced by NewCrop, and cannot be populated with any other value. 
			//EncounterIdentifier = unique ID for the patient visit (e.g. John Doe, 11/11/2013).
			//	This is used by NewCrop for reporting events against a visit, but otherwise does not impact the session. 
			//EpisodeIdentifier = unique ID for the patient’s issue (e.g. John Doe’s broken leg) which may include multiple visits.
			//	Currently not used by NewCrop except for being echoed back; it is possible this functionality would be expanded in the future based on its intent as noted. 
			//ExternalSource = a codified field noting the origin of the prescription. This may not be used.
			//Serialize
			MemoryStream memoryStream=new MemoryStream();
			XmlSerializer xmlSerializer=new XmlSerializer(typeof(NCScript));
			xmlSerializer.Serialize(memoryStream,ncScript);
			byte[] memoryStreamInBytes=memoryStream.ToArray();
			return Encoding.UTF8.GetString(memoryStreamInBytes,0,memoryStreamInBytes.Length);
		}
Ejemplo n.º 3
0
		private void AddEmployeeToBucket(int bucketIndex, Employee employee){
			buckets[bucketIndex]+=1;
			List<Employee> employees = null;
			if(!DictEmployeesPerBucket.TryGetValue(bucketIndex,out employees)) {
				employees=new List<Employee>();
			}
			if(employee!=null) {
				employees.Add(employee);
			}
			DictEmployeesPerBucket[bucketIndex]=employees;
		}
Ejemplo n.º 4
0
		///<summary>This is a modified version of FormTimeCard.FillMain().  It fills one time card per employee.</summary>
		private ODGrid GetGridForPrinting(Employee emp) {
			ODGrid gridTimeCard=new ODGrid();
			List<ClockEvent> clockEventList=ClockEvents.Refresh(emp.EmployeeNum,PIn.Date(textDateStart.Text),PIn.Date(textDateStop.Text),false);
			List<TimeAdjust> timeAdjustList=TimeAdjusts.Refresh(emp.EmployeeNum,PIn.Date(textDateStart.Text),PIn.Date(textDateStop.Text));
			ArrayList mergedAL=new ArrayList();
			for(int i=0;i<clockEventList.Count;i++) {
				mergedAL.Add(clockEventList[i]);
			}
			for(int i=0;i<timeAdjustList.Count;i++) {
				mergedAL.Add(timeAdjustList[i]);
			}
			IComparer myComparer=new ObjectDateComparer();
			mergedAL.Sort(myComparer);
			gridTimeCard.BeginUpdate();
			gridTimeCard.Columns.Clear();
			ODGridColumn col=new ODGridColumn(Lan.g(this,"Date"),70);
			gridTimeCard.Columns.Add(col);
			col=new ODGridColumn(Lan.g(this,"Weekday"),70);
			gridTimeCard.Columns.Add(col);
			col=new ODGridColumn(Lan.g(this,"In"),60,HorizontalAlignment.Right);
			gridTimeCard.Columns.Add(col);
			col=new ODGridColumn(Lan.g(this,"Out"),60,HorizontalAlignment.Right);
			gridTimeCard.Columns.Add(col);
			col=new ODGridColumn(Lan.g(this,"Total"),50,HorizontalAlignment.Right);
			gridTimeCard.Columns.Add(col);
			col=new ODGridColumn(Lan.g(this,"Adjust"),55,HorizontalAlignment.Right);
			gridTimeCard.Columns.Add(col);
			col=new ODGridColumn(Lan.g(this,"Rate2"),55,HorizontalAlignment.Right);
			gridTimeCard.Columns.Add(col);
			col=new ODGridColumn(Lan.g(this,"Overtime"),55,HorizontalAlignment.Right);
			gridTimeCard.Columns.Add(col);
			col=new ODGridColumn(Lan.g(this,"Daily"),50,HorizontalAlignment.Right);
			gridTimeCard.Columns.Add(col);
			col=new ODGridColumn(Lan.g(this,"Weekly"),50,HorizontalAlignment.Right);
			gridTimeCard.Columns.Add(col);
			col=new ODGridColumn(Lan.g(this,"Note"),5);
			gridTimeCard.Columns.Add(col);
			gridTimeCard.Rows.Clear();
			ODGridRow row;
			TimeSpan[] weeklyTotals=new TimeSpan[mergedAL.Count];
			TimeSpan alteredSpan=new TimeSpan(0);//used to display altered times
			TimeSpan oneSpan=new TimeSpan(0);//used to sum one pair of clock-in/clock-out
			TimeSpan oneAdj;
			TimeSpan oneOT;
			TimeSpan daySpan=new TimeSpan(0);//used for daily totals.
			TimeSpan weekSpan=new TimeSpan(0);//used for weekly totals.
			if(mergedAL.Count>0){
				weekSpan=ClockEvents.GetWeekTotal(emp.EmployeeNum,GetDateForRow(0,mergedAL));
			}
			TimeSpan periodSpan=new TimeSpan(0);//used to add up totals for entire page.
			TimeSpan otspan=new TimeSpan(0);//overtime for the entire period
			TimeSpan rate2span=new TimeSpan(0);//rate2 hours total
			Calendar cal=CultureInfo.CurrentCulture.Calendar;
			CalendarWeekRule rule=CultureInfo.CurrentCulture.DateTimeFormat.CalendarWeekRule;
			DateTime curDate=DateTime.MinValue;
			DateTime previousDate=DateTime.MinValue;
			Type type;
			ClockEvent clock;
			TimeAdjust adjust;
			for(int i=0;i<mergedAL.Count;i++){
				row=new ODGridRow();
				type=mergedAL[i].GetType();
				row.Tag=mergedAL[i];
				previousDate=curDate;
				//clock event row---------------------------------------------------------------------------------------------
				if(type==typeof(ClockEvent)){
					clock=(ClockEvent)mergedAL[i];
					curDate=clock.TimeDisplayed1.Date;
					if(curDate==previousDate){
						row.Cells.Add("");
						row.Cells.Add("");
					}
					else{
						row.Cells.Add(curDate.ToShortDateString());
						row.Cells.Add(curDate.DayOfWeek.ToString());
					}
					//altered--------------------------------------
					//deprecated
					//status--------------------------------------
					//row.Cells.Add(clock.ClockStatus.ToString());
					//in------------------------------------------
					row.Cells.Add(clock.TimeDisplayed1.ToShortTimeString());
					if(clock.TimeEntered1!=clock.TimeDisplayed1){
						row.Cells[row.Cells.Count-1].ColorText = Color.Red;
					}
					//out-----------------------------
					if(clock.TimeDisplayed2.Year<1880){
						row.Cells.Add("");//not clocked out yet
					}
					else{
						row.Cells.Add(clock.TimeDisplayed2.ToShortTimeString());
						if (clock.TimeEntered2!=clock.TimeDisplayed2)
						{
							row.Cells[row.Cells.Count-1].ColorText = Color.Red;
						}
					}
					//total-------------------------------
					if(clock.TimeDisplayed2.Year<1880){
						row.Cells.Add("");
					}
					else{
						oneSpan=clock.TimeDisplayed2-clock.TimeDisplayed1;
						row.Cells.Add(ClockEvents.Format(oneSpan));
						daySpan+=oneSpan;
						weekSpan+=oneSpan;
						periodSpan+=oneSpan;
					}
					//Adjust---------------------------------
					oneAdj=TimeSpan.Zero;
					if(clock.AdjustIsOverridden) {
						oneAdj+=clock.Adjust;
					}
					else {
						oneAdj+=clock.AdjustAuto;//typically zero
					}
					daySpan+=oneAdj;
					weekSpan+=oneAdj;
					periodSpan+=oneAdj;
					row.Cells.Add(ClockEvents.Format(oneAdj));
					if(clock.AdjustIsOverridden) {
						row.Cells[row.Cells.Count-1].ColorText = Color.Red;
					}
					//Rate2---------------------------------
					if(clock.Rate2Hours!=TimeSpan.FromHours(-1)) {
						rate2span+=clock.Rate2Hours;
						row.Cells.Add(ClockEvents.Format(clock.Rate2Hours));
						row.Cells[row.Cells.Count-1].ColorText = Color.Red;
					}
					else {
						rate2span+=clock.Rate2Auto;
						row.Cells.Add(ClockEvents.Format(clock.Rate2Auto));
					}
					//Overtime------------------------------
					oneOT=TimeSpan.Zero;
					if(clock.OTimeHours!=TimeSpan.FromHours(-1)) {//overridden
						oneOT=clock.OTimeHours;
					}
					else {
						oneOT=clock.OTimeAuto;//typically zero
					}
					otspan+=oneOT;
					daySpan-=oneOT;
					weekSpan-=oneOT;
					periodSpan-=oneOT;
					row.Cells.Add(ClockEvents.Format(oneOT));
					if(clock.OTimeHours!=TimeSpan.FromHours(-1)) {//overridden
						row.Cells[row.Cells.Count-1].ColorText = Color.Red;
					}
					//Daily-----------------------------------
					//if this is the last entry for a given date
					if(i==mergedAL.Count-1//if this is the last row
						|| GetDateForRow(i+1,mergedAL) != curDate)//or the next row is a different date
					{
						row.Cells.Add(ClockEvents.Format(daySpan));
						daySpan=new TimeSpan(0);
					}
					else{//not the last entry for the day
						row.Cells.Add("");
					}
					//Weekly-------------------------------------
					weeklyTotals[i]=weekSpan;
					//if this is the last entry for a given week
					if(i==mergedAL.Count-1//if this is the last row 
						|| cal.GetWeekOfYear(GetDateForRow(i+1,mergedAL),rule,(DayOfWeek)PrefC.GetInt(PrefName.TimeCardOvertimeFirstDayOfWeek))//or the next row has a
						!= cal.GetWeekOfYear(clock.TimeDisplayed1.Date,rule,(DayOfWeek)PrefC.GetInt(PrefName.TimeCardOvertimeFirstDayOfWeek)))//different week of year
					{
						row.Cells.Add(ClockEvents.Format(weekSpan));
						weekSpan=new TimeSpan(0);
					}
					else {
						//row.Cells.Add(ClockEvents.Format(weekSpan));
						row.Cells.Add("");
					}
					//Note-----------------------------------------
					row.Cells.Add(clock.Note);
				}
				//adjustment row--------------------------------------------------------------------------------------
				else if(type==typeof(TimeAdjust)){
					adjust=(TimeAdjust)mergedAL[i];
					curDate=adjust.TimeEntry.Date;
					if(curDate==previousDate){
						row.Cells.Add("");
						row.Cells.Add("");
					}
					else{
						row.Cells.Add(curDate.ToShortDateString());
						row.Cells.Add(curDate.DayOfWeek.ToString());
					}
					//altered--------------------------------------
					//Deprecated
					//status--------------------------------------
					//row.Cells.Add("");//3
					//in/out------------------------------------------
					row.Cells.Add("");//4
					//time-----------------------------
					row.Cells.Add(adjust.TimeEntry.ToShortTimeString());//5
					//total-------------------------------
					row.Cells.Add("");//
					//Adjust------------------------------
					daySpan+=adjust.RegHours;//might be negative
					weekSpan+=adjust.RegHours;
					periodSpan+=adjust.RegHours;
					row.Cells.Add(ClockEvents.Format(adjust.RegHours));//6
					//Rate2-------------------------------
					row.Cells.Add("");//
					//Overtime------------------------------
					otspan+=adjust.OTimeHours;
					row.Cells.Add(ClockEvents.Format(adjust.OTimeHours));//7
					//Daily-----------------------------------
					//if this is the last entry for a given date
					if(i==mergedAL.Count-1//if this is the last row
						|| GetDateForRow(i+1,mergedAL) != curDate)//or the next row is a different date
					{
						row.Cells.Add(ClockEvents.Format(daySpan));//
						daySpan=new TimeSpan(0);
					}
					else{
						row.Cells.Add("");
					}
					//Weekly-------------------------------------
					weeklyTotals[i]=weekSpan;
					//if this is the last entry for a given week
					if(i==mergedAL.Count-1//if this is the last row 
						|| cal.GetWeekOfYear(GetDateForRow(i+1,mergedAL),rule,(DayOfWeek)PrefC.GetInt(PrefName.TimeCardOvertimeFirstDayOfWeek))//or the next row has a
						!= cal.GetWeekOfYear(adjust.TimeEntry.Date,rule,(DayOfWeek)PrefC.GetInt(PrefName.TimeCardOvertimeFirstDayOfWeek)))//different week of year
					{
						ODGridCell cell=new ODGridCell(ClockEvents.Format(weekSpan));
						cell.ColorText=Color.Black;
						row.Cells.Add(cell);
						weekSpan=new TimeSpan(0);
					}
					else {
						row.Cells.Add("");
					}
					//Note-----------------------------------------
					row.Cells.Add("(Adjust)"+adjust.Note);//used to indicate adjust rows.
					row.Cells[row.Cells.Count-1].ColorText=Color.Red;
				}
				gridTimeCard.Rows.Add(row);
			}
			gridTimeCard.EndUpdate();
			totalTime=periodSpan.ToStringHmm();
			overTime=otspan.ToStringHmm();
			rate2Time=rate2span.ToStringHmm();
			totalTime2=periodSpan.TotalHours.ToString("n");
			overTime2=otspan.TotalHours.ToString("n");
			rate2Time2=rate2span.TotalHours.ToString("n");
			return gridTimeCard;
		}
Ejemplo n.º 5
0
 /*public static Employee[] GetListByExtension(){
     if(ListShort==null){
         return new Employee[0];
     }
     Employee[] arrayCopy=new Employee[ListShort.Length];
     ListShort.CopyTo(arrayCopy,0);
     int[] arrayKeys=new int[ListShort.Length];
     for(int i=0;i<ListShort.Length;i++){
         arrayKeys[i]=ListShort[i].PhoneExt;
     }
     Array.Sort(arrayKeys,arrayCopy);
     //List<Employee> retVal=new List<Employee>(ListShort);
     //retVal.Sort(
     return arrayCopy;
 }*/
 ///<summary></summary>
 public static void Update(Employee Cur)
 {
     if(RemotingClient.RemotingRole==RemotingRole.ClientWeb) {
         Meth.GetVoid(MethodBase.GetCurrentMethod(),Cur);
         return;
     }
     if(Cur.LName=="" && Cur.FName=="") {
         throw new ApplicationException(Lans.g("FormEmployeeEdit","Must include either first name or last name"));
     }
     Crud.EmployeeCrud.Update(Cur);
 }
Ejemplo n.º 6
0
 ///<summary></summary>
 public static long Insert(Employee Cur)
 {
     if(RemotingClient.RemotingRole==RemotingRole.ClientWeb) {
         Cur.EmployeeNum=Meth.GetLong(MethodBase.GetCurrentMethod(),Cur);
         return Cur.EmployeeNum;
     }if(Cur.LName=="" && Cur.FName=="") {
         throw new ApplicationException(Lans.g("FormEmployeeEdit","Must include either first name or last name"));
     }
     return Crud.EmployeeCrud.Insert(Cur);
 }
Ejemplo n.º 7
0
        /*
        ///<summary>Returns LName,FName MiddleI for the provided employee.</summary>
        public static string GetNameLF(Employee emp){
            return(emp.LName+", "+emp.FName+" "+emp.MiddleI);
        }

        ///<summary>Loops through List to find matching employee, and returns LName,FName MiddleI.</summary>
        public static string GetNameLF(int employeeNum){
            for(int i=0;i<ListLong.Length;i++){
                if(ListLong[i].EmployeeNum==employeeNum){
                    return GetNameLF(ListLong[i]);
                }
            }
            return "";
        }*/
        ///<summary>Returns FName MiddleI LName for the provided employee.</summary>
        public static string GetNameFL(Employee emp)
        {
            //No need to check RemotingRole; no call to db.
            return (emp.FName+" "+emp.MiddleI+" "+emp.LName);
        }
Ejemplo n.º 8
0
        ///<summary>this code is similar to code in the phone tracking server.  But here, we frequently only change clockStatus and ColorBar by setting employeeNum=-1.  If employeeNum is not -1, then EmployeeName also gets set.  If employeeNum==0, then clears employee from that row.</summary>
        public static void SetPhoneStatus(ClockStatusEnum clockStatus, int extens, long employeeNum = -1)
        {
            if (RemotingClient.RemotingRole == RemotingRole.ClientWeb)
            {
                Meth.GetVoid(MethodBase.GetCurrentMethod(), clockStatus, extens, employeeNum);
                return;
            }
            string command = @"SELECT phoneempdefault.EmployeeNum,phoneempdefault.IsTriageOperator,Description,phoneempdefault.EmpName,HasColor,phone.ClockStatus "
                             + "FROM phone "
                             + "LEFT JOIN phoneempdefault ON phone.Extension=phoneempdefault.PhoneExt "
                             + "WHERE phone.Extension=" + POut.Long(extens);
            DataTable tablePhone = Db.GetTable(command);

            if (tablePhone.Rows.Count == 0)
            {
                //It would be nice if we could create a phone row for this extension.
                return;
            }
            long     empNum           = PIn.Long(tablePhone.Rows[0]["EmployeeNum"].ToString());
            bool     isTriageOperator = PIn.Bool(tablePhone.Rows[0]["IsTriageOperator"].ToString());
            string   empName          = PIn.String(tablePhone.Rows[0]["EmpName"].ToString());
            string   clockStatusDb    = PIn.String(tablePhone.Rows[0]["ClockStatus"].ToString());
            Employee emp = Employees.GetEmp(employeeNum);

            if (emp != null)           //A new employee is going to take over this extension.
            {
                empName = emp.FName;
                empNum  = emp.EmployeeNum;
            }
            else if (employeeNum == 0)           //Clear the employee from that row.
            {
                empName = "";
                empNum  = 0;
            }
            //if these values are null because of missing phoneempdefault row, they will default to false
            //PhoneEmpStatusOverride statusOverride=(PhoneEmpStatusOverride)PIn.Int(tablePhone.Rows[0]["StatusOverride"].ToString());
            bool hasColor = PIn.Bool(tablePhone.Rows[0]["HasColor"].ToString());

            #region DateTimeStart
            //When a user shows up as a color on the phone panel, we want a timer to be constantly going to show how long they've been off the phone.
            string dateTimeStart = "";
            //It's possible that a new user has never clocked in before, therefore their clockStatus will be empty.  Simply set it to the status that they are trying to go to.
            if (clockStatusDb == "")
            {
                clockStatusDb = clockStatus.ToString();
            }
            if (clockStatus == ClockStatusEnum.Break ||
                clockStatus == ClockStatusEnum.Lunch)
            {
                //The user is going on Lunch or Break.  Start the DateTimeStart counter so we know how long they have been gone.
                dateTimeStart = "DateTimeStart=NOW(), ";
            }
            else if (clockStatus == ClockStatusEnum.Home)
            {
                //User is going Home.  Always clear the DateTimeStart column no matter what.
                dateTimeStart = "DateTimeStart='0001-01-01', ";
            }
            else              //User shows as a color on big phones and is not going to a status of Home, Lunch, or Break.  Example: Available, Training etc.
                              //Get the current clock status from the database.
            {
                ClockStatusEnum clockStatusCur = (ClockStatusEnum)Enum.Parse(typeof(ClockStatusEnum), clockStatusDb);
                //Start the clock if the user is going from a break status to any other non-break status.
                if (clockStatusCur == ClockStatusEnum.Home ||
                    clockStatusCur == ClockStatusEnum.Lunch ||
                    clockStatusCur == ClockStatusEnum.Break)
                {
                    //The user is clocking in from home, lunch, or break.  Start the timer up.
                    if (hasColor)                     //Only start up the timer when someone with color clocks in.
                    {
                        dateTimeStart = "DateTimeStart=NOW(), ";
                    }
                    else                       //Someone with no color then reset the timer. They are back from break, that's all we need to know.
                    {
                        dateTimeStart = "DateTimeStart='0001-01-01', ";
                    }
                }
            }
            string dateTimeNeedsHelpStart;
            if (clockStatus == ClockStatusEnum.NeedsHelp)
            {
                dateTimeNeedsHelpStart = "DateTimeNeedsHelpStart=NOW(), ";
            }
            else
            {
                dateTimeNeedsHelpStart = "DateTimeNeedsHelpStart=" + POut.DateT(DateTime.MinValue) + ", ";
            }
            #endregion
            //Update the phone row to reflect the new clock status of the user.
            string clockStatusNew = clockStatus.ToString();
            if (clockStatus == ClockStatusEnum.None)
            {
                clockStatusNew = "";
            }
            if (clockStatus == ClockStatusEnum.HelpOnTheWay && clockStatusDb == ClockStatusEnum.HelpOnTheWay.ToString())           //If HelpOnTheWay already
            {
                clockStatusNew = ClockStatusEnum.Available.ToString();
            }
            command = "UPDATE phone SET ClockStatus='" + POut.String(clockStatusNew) + "', "
                      + dateTimeStart
                      + dateTimeNeedsHelpStart
                      //+"ColorBar=-1, " //ColorBar is now determined at runtime by OD using Phones.GetPhoneColor.
                      + "EmployeeNum=" + POut.Long(empNum) + ", "
                      + "EmployeeName='" + POut.String(empName) + "' "
                      + "WHERE Extension=" + extens;
            Db.NonQ(command);
            //Zero out any duplicate phone table rows for this employee.
            //This is possible if a user logged off and another employee logs into their computer. This would cause duplicate entries in the big phones window.
            UpdatePhoneToEmpty(employeeNum, extens);
        }
Ejemplo n.º 9
0
		/// <summary>This was originally analogous to the FormTimeCard.FillGrid(), before this logic was moved to the business layer.</summary>
		private static List<TimeSpan> FillWeeklyTotalsHelper(bool fromDB,Employee EmployeeCur,ArrayList mergedAL) {
			List<TimeSpan> retVal = new List<TimeSpan>();
			TimeSpan[] WeeklyTotals=new TimeSpan[mergedAL.Count];
			TimeSpan alteredSpan=new TimeSpan(0);//used to display altered times
			TimeSpan oneSpan=new TimeSpan(0);//used to sum one pair of clock-in/clock-out
			TimeSpan oneAdj;
			TimeSpan oneOT;
			TimeSpan daySpan=new TimeSpan(0);//used for daily totals.
			TimeSpan weekSpan=new TimeSpan(0);//used for weekly totals.
			if(mergedAL.Count>0) {
				weekSpan=ClockEvents.GetWeekTotal(EmployeeCur.EmployeeNum,GetDateForRowHelper(mergedAL[0]));
			}
			TimeSpan periodSpan=new TimeSpan(0);//used to add up totals for entire page.
			TimeSpan otspan=new TimeSpan(0);//overtime for the entire period
			Calendar cal=CultureInfo.CurrentCulture.Calendar;
			CalendarWeekRule rule=CalendarWeekRule.FirstFullWeek;// CultureInfo.CurrentCulture.DateTimeFormat.CalendarWeekRule;
			DateTime curDate=DateTime.MinValue;
			DateTime previousDate=DateTime.MinValue;
			Type type;
			ClockEvent clock;
			TimeAdjust adjust;
			for(int i=0;i<mergedAL.Count;i++) {
				type=mergedAL[i].GetType();
				previousDate=curDate;
				//clock event row---------------------------------------------------------------------------------------------
				if(type==typeof(ClockEvent)) {
					clock=(ClockEvent)mergedAL[i];
					curDate=clock.TimeDisplayed1.Date;
					if(clock.TimeDisplayed2.Year<1880) {
					}
					else {
						oneSpan=clock.TimeDisplayed2-clock.TimeDisplayed1;
						daySpan+=oneSpan;
						weekSpan+=oneSpan;
						periodSpan+=oneSpan;
					}
					//Adjust---------------------------------
					oneAdj=TimeSpan.Zero;
					if(clock.AdjustIsOverridden) {
						oneAdj+=clock.Adjust;
					}
					else {
						oneAdj+=clock.AdjustAuto;//typically zero
					}
					daySpan+=oneAdj;
					weekSpan+=oneAdj;
					periodSpan+=oneAdj;
					//Overtime------------------------------
					oneOT=TimeSpan.Zero;
					if(clock.OTimeHours!=TimeSpan.FromHours(-1)) {//overridden
						oneOT=clock.OTimeHours;
					}
					else {
						oneOT=clock.OTimeAuto;//typically zero
					}
					otspan+=oneOT;
					daySpan-=oneOT;
					weekSpan-=oneOT;
					periodSpan-=oneOT;
					//Daily-----------------------------------
					//if this is the last entry for a given date
					if(i==mergedAL.Count-1//if this is the last row
		        || GetDateForRowHelper(mergedAL[i+1]) != curDate)//or the next row is a different date
		      {
						daySpan=new TimeSpan(0);
					}
					else {//not the last entry for the day
					}
					//Weekly-------------------------------------
					WeeklyTotals[i]=weekSpan;
					//if this is the last entry for a given week
					if(i==mergedAL.Count-1//if this is the last row 
		        || cal.GetWeekOfYear(GetDateForRowHelper(mergedAL[i+1]),rule,(DayOfWeek)PrefC.GetInt(PrefName.TimeCardOvertimeFirstDayOfWeek))//or the next row has a
		        != cal.GetWeekOfYear(clock.TimeDisplayed1.Date,rule,(DayOfWeek)PrefC.GetInt(PrefName.TimeCardOvertimeFirstDayOfWeek)))//different week of year
		      {
						weekSpan=new TimeSpan(0);
					}
				}
				//adjustment row--------------------------------------------------------------------------------------
				else if(type==typeof(TimeAdjust)) {
					adjust=(TimeAdjust)mergedAL[i];
					curDate=adjust.TimeEntry.Date;
					//Adjust------------------------------
					daySpan+=adjust.RegHours;//might be negative
					weekSpan+=adjust.RegHours;
					periodSpan+=adjust.RegHours;
					//Overtime------------------------------
					otspan+=adjust.OTimeHours;
					//Daily-----------------------------------
					//if this is the last entry for a given date
					if(i==mergedAL.Count-1//if this is the last row
		        || GetDateForRowHelper(mergedAL[i+1]) != curDate)//or the next row is a different date
		      {
						daySpan=new TimeSpan(0);
					}
					//Weekly-------------------------------------
					WeeklyTotals[i]=weekSpan;
					//if this is the last entry for a given week
					if(i==mergedAL.Count-1//if this is the last row 
		        || cal.GetWeekOfYear(GetDateForRowHelper(mergedAL[i+1]),rule,(DayOfWeek)PrefC.GetInt(PrefName.TimeCardOvertimeFirstDayOfWeek))//or the next row has a
		        != cal.GetWeekOfYear(adjust.TimeEntry.Date,rule,(DayOfWeek)PrefC.GetInt(PrefName.TimeCardOvertimeFirstDayOfWeek)))//different week of year
		      {
						weekSpan=new TimeSpan(0);
					}
				}
			}
			foreach(TimeSpan week in WeeklyTotals) {
				retVal.Add(week);
			}
			return retVal;
		}
Ejemplo n.º 10
0
		///<summary>Calculates weekly overtime and inserts TimeAdjustments accordingly.</summary>
		public static void CalculateWeeklyOvertime(Employee EmployeeCur,DateTime StartDate,DateTime StopDate) {
			List<ClockEvent> listClockEvent=new List<ClockEvent>();
			List<TimeAdjust> listTimeAdjust=new List<TimeAdjust>();
			string errors="";
			string clockErrors="";
			string timeAdjustErrors="";
			//Fill lists and catch validation error messages------------------------------------------------------------------------------------------------------------
			try{listClockEvent=ClockEvents.GetValidList(EmployeeCur.EmployeeNum,StartDate,StopDate,false)	;}catch(Exception ex) {clockErrors+=ex.Message;}
			try{listTimeAdjust=TimeAdjusts.GetValidList(EmployeeCur.EmployeeNum,StartDate,StopDate)				;}catch(Exception ex) {timeAdjustErrors+=ex.Message;}
			//Report Errors---------------------------------------------------------------------------------------------------------------------------------------------
			errors=clockErrors+timeAdjustErrors;
			if(errors!="") {
				throw new Exception(Employees.GetNameFL(EmployeeCur)+" has the following errors:\r\n"+errors);
			}
			


			//first, delete all existing non manual overtime entries
			for(int i=0;i<listTimeAdjust.Count;i++) {
				if(listTimeAdjust[i].IsAuto) {
					TimeAdjusts.Delete(listTimeAdjust[i]);
				}
			}
			//refresh list after it has been cleaned up.
			
			
			listTimeAdjust=TimeAdjusts.Refresh(EmployeeCur.EmployeeNum,StartDate,StopDate);
			ArrayList mergedAL = new ArrayList();
			foreach(ClockEvent clockEvent in listClockEvent) {
				mergedAL.Add(clockEvent);
			}
			foreach(TimeAdjust timeAdjust in listTimeAdjust) {
				mergedAL.Add(timeAdjust);
			}
			//then, fill grid
			Calendar cal=CultureInfo.CurrentCulture.Calendar;
			CalendarWeekRule rule=CalendarWeekRule.FirstFullWeek;//CultureInfo.CurrentCulture.DateTimeFormat.CalendarWeekRule;
			//rule=CalendarWeekRule.FirstFullWeek;//CalendarWeekRule is an Enum. For these calculations, we want to use FirstFullWeek, not FirstDay;
			List<TimeSpan> WeeklyTotals = new List<TimeSpan>();
			WeeklyTotals = FillWeeklyTotalsHelper(true,EmployeeCur,mergedAL);
			//loop through all rows
			for(int i=0;i<mergedAL.Count;i++) {
				//ignore rows that aren't weekly totals
				if(i<mergedAL.Count-1//if not the last row
					//if the next row has the same week as this row
					&& cal.GetWeekOfYear(GetDateForRowHelper(mergedAL[i+1]),rule,(DayOfWeek)PrefC.GetInt(PrefName.TimeCardOvertimeFirstDayOfWeek))//Default is 0-Sunday
					== cal.GetWeekOfYear(GetDateForRowHelper(mergedAL[i]),rule,(DayOfWeek)PrefC.GetInt(PrefName.TimeCardOvertimeFirstDayOfWeek))) {
					continue;
				}
				if(WeeklyTotals[i]<=TimeSpan.FromHours(40)) {
					continue;
				}
				//found a weekly total over 40 hours
				TimeAdjust adjust=new TimeAdjust();
				adjust.IsAuto=true;
				adjust.EmployeeNum=EmployeeCur.EmployeeNum;
				adjust.TimeEntry=GetDateForRowHelper(mergedAL[i]).AddHours(20);//puts it at 8pm on the same day.
				adjust.OTimeHours=WeeklyTotals[i]-TimeSpan.FromHours(40);
				adjust.RegHours=-adjust.OTimeHours;
				TimeAdjusts.Insert(adjust);
			}
		}
Ejemplo n.º 11
0
		///<summary>Calculates weekly overtime and inserts TimeAdjustments accordingly.</summary>
		public static void CalculateWeeklyOvertime_Old(Employee EmployeeCur,DateTime StartDate,DateTime StopDate) {
			List<TimeAdjust> TimeAdjustList=TimeAdjusts.Refresh(EmployeeCur.EmployeeNum,StartDate,StopDate);
			List<ClockEvent> ClockEventList=ClockEvents.Refresh(EmployeeCur.EmployeeNum,StartDate,StopDate,false);
			//first, delete all existing overtime entries
			for(int i=0;i<TimeAdjustList.Count;i++) {
				if(TimeAdjustList[i].OTimeHours==TimeSpan.Zero) {
					continue;
				}
				if(!TimeAdjustList[i].IsAuto) {
					continue;
				}
				TimeAdjusts.Delete(TimeAdjustList[i]);
			}
			//refresh list after it has been cleaned up.
			TimeAdjustList=TimeAdjusts.Refresh(EmployeeCur.EmployeeNum,StartDate,StopDate);
			ArrayList mergedAL = new ArrayList();
			foreach(ClockEvent clockEvent in ClockEventList) {
				mergedAL.Add(clockEvent);
			}
			foreach(TimeAdjust timeAdjust in TimeAdjustList) {
				mergedAL.Add(timeAdjust);
			}
			//then, fill grid
			Calendar cal=CultureInfo.CurrentCulture.Calendar;
			CalendarWeekRule rule=CalendarWeekRule.FirstFullWeek;//CultureInfo.CurrentCulture.DateTimeFormat.CalendarWeekRule;
			//rule=CalendarWeekRule.FirstFullWeek;//CalendarWeekRule is an Enum. For these calculations, we want to use FirstFullWeek, not FirstDay;
			List<TimeSpan> WeeklyTotals = new List<TimeSpan>();
			WeeklyTotals = FillWeeklyTotalsHelper(true,EmployeeCur,mergedAL);
			//loop through all rows
			for(int i=0;i<mergedAL.Count;i++) {
				//ignore rows that aren't weekly totals
				if(i<mergedAL.Count-1//if not the last row
					//if the next row has the same week as this row
					&& cal.GetWeekOfYear(GetDateForRowHelper(mergedAL[i+1]),rule,(DayOfWeek)PrefC.GetInt(PrefName.TimeCardOvertimeFirstDayOfWeek))//Default is 0-Sunday
					== cal.GetWeekOfYear(GetDateForRowHelper(mergedAL[i]),rule,(DayOfWeek)PrefC.GetInt(PrefName.TimeCardOvertimeFirstDayOfWeek))) {
					continue;
				}
				if(WeeklyTotals[i]<=TimeSpan.FromHours(40)) {
					continue;
				}
				//found a weekly total over 40 hours
				TimeAdjust adjust=new TimeAdjust();
				adjust.IsAuto=true;
				adjust.EmployeeNum=EmployeeCur.EmployeeNum;
				adjust.TimeEntry=GetDateForRowHelper(mergedAL[i]).AddHours(20);//puts it at 8pm on the same day.
				adjust.OTimeHours=WeeklyTotals[i]-TimeSpan.FromHours(40);
				adjust.RegHours=-adjust.OTimeHours;
				TimeAdjusts.Insert(adjust);
			}

		}
Ejemplo n.º 12
0
		///<summary>Deprecated.  This function is aesthetic and has no bearing on actual OT calculations. It adds adjustments to breaks so that when viewing them you can see if they went over 30 minutes.</summary>
		private static void AdjustBreaksHelper(Employee EmployeeCur,DateTime StartDate,DateTime StopDate) {
			if(!PrefC.GetBool(PrefName.TimeCardsMakesAdjustmentsForOverBreaks)){
				//Only adjust breaks if preference is set.
				return;
			}
			List<ClockEvent> breakList=ClockEvents.Refresh(EmployeeCur.EmployeeNum,StartDate,StopDate,true);//PIn.Date(textDateStart.Text),PIn.Date(textDateStop.Text),true);
			TimeSpan totalToday=TimeSpan.Zero;
			TimeSpan totalOne=TimeSpan.Zero;
			DateTime previousDate=DateTime.MinValue;
			for(int b=0;b<breakList.Count;b++) {
				if(breakList[b].TimeDisplayed2.Year<1880) {
					return;
				}
				if(breakList[b].TimeDisplayed1.Date != breakList[b].TimeDisplayed2.Date) {
					//MsgBox.Show(this,"Error. One break spans multiple dates.");
					return;
				}
				//calc time for the one break
				totalOne=breakList[b].TimeDisplayed2-breakList[b].TimeDisplayed1;
				//calc daily total
				if(previousDate.Date != breakList[b].TimeDisplayed1.Date) {//if date changed, this is the first pair of the day
					totalToday=TimeSpan.Zero;//new day
					previousDate=breakList[b].TimeDisplayed1.Date;//for the next loop
				}
				totalToday+=totalOne;
				//decide if breaks for the day went over 30 min.
				if(totalToday > TimeSpan.FromMinutes(31)) {//31 to prevent silly fractions less than 1.
					breakList[b].AdjustAuto=-(totalToday-TimeSpan.FromMinutes(30));
					ClockEvents.Update(breakList[b]);
					totalToday=TimeSpan.FromMinutes(30);//reset to 30.  Therefore, any additional breaks will be wholly adjustments.
				}
			}//end breaklist
		}
Ejemplo n.º 13
0
		///<summary>Calculates daily overtime.  Daily overtime does not take into account any time adjust events.  All manually entered time adjust events are assumed to be entered correctly and should not be used in calculating automatic totals.  Throws exceptions when encountering errors.</summary>
		public static void CalculateDailyOvertime(Employee employee,DateTime dateStart,DateTime dateStop) {
			#region Fill Lists, validate data sets, generate error messages.
			List<ClockEvent> listClockEvent=new List<ClockEvent>();
			List<ClockEvent> listClockEventBreak=new List<ClockEvent>();
			List<TimeCardRule> listTimeCardRule=new List<TimeCardRule>();
			string errors="";
			string clockErrors="";
			string breakErrors="";
			string ruleErrors="";
			//Fill lists and catch validation error messages------------------------------------------------------------------------------------------------------------
			try{ listClockEvent			=ClockEvents	.GetValidList(employee.EmployeeNum,dateStart,dateStop,false); } catch(Exception ex){clockErrors			+=ex.Message;}
			try{ listClockEventBreak=ClockEvents	.GetValidList(employee.EmployeeNum,dateStart,dateStop,true);	} catch(Exception ex){breakErrors			+=ex.Message;}
			try{ listTimeCardRule		=TimeCardRules.GetValidList(employee);																			} catch(Exception ex){ruleErrors			+=ex.Message;}
			//Validation between two or more lists above----------------------------------------------------------------------------------------------------------------
			for(int b=0;b<listClockEventBreak.Count;b++) {
				bool isValidBreak=false;
				for(int c=0;c<listClockEvent.Count;c++) {
					if(timeClockEventsOverlapHelper(listClockEventBreak[b],listClockEvent[c])) {
						if(listClockEventBreak[b].TimeDisplayed1>listClockEvent[c].TimeDisplayed1//break started after work did
							&& listClockEventBreak[b].TimeDisplayed2<listClockEvent[c].TimeDisplayed2)//break ended before working hours
						{
							//valid break.
							isValidBreak=true;
							break;
						}
						//invalid break.
						isValidBreak=false;//redundant, but harmless. Makes code more readable.
						break;
					}
				}
				if(isValidBreak) {
					continue;
				}
				breakErrors+="  "+listClockEventBreak[b].TimeDisplayed1.ToString()+" : break found during non-working hours.\r\n";//ToString() instead of ToShortDateString() to show time.
			}
			//Report Errors---------------------------------------------------------------------------------------------------------------------------------------------
			errors=ruleErrors+clockErrors+breakErrors;
			if(errors!="") {
				throw new Exception(Employees.GetNameFL(employee)+" has the following errors:\r\n"+errors);
			}
			#endregion
			#region Fill time card rules
			//Begin calculations=========================================================================================================================================
			TimeSpan tsHoursWorkedTotal			=new TimeSpan()				;
			TimeSpan tsOvertimeHoursRule		=new TimeSpan(24,0,0)	;//Example 10:00 for overtime rule after 10 hours per day.
			TimeSpan tsDifferentialAMRule		=new TimeSpan()				;//Example 06:00 for differential rule before 6am.
			TimeSpan tsDifferentialPMRule		=new TimeSpan(24,0,0)	;//Example 17:00 for differential rule after  5pm.
			//Fill over hours rule from list-------------------------------------------------------------------------------------
			for(int i=0;i<listTimeCardRule.Count;i++){//loop through rules for this one employee, including any that apply to all emps.
				if(listTimeCardRule[i].OverHoursPerDay!=TimeSpan.Zero) {//OverHours Rule
					tsOvertimeHoursRule=listTimeCardRule[i].OverHoursPerDay;//at most, one non-zero OverHours rule available at this point.
				}
				if(listTimeCardRule[i].BeforeTimeOfDay!=TimeSpan.Zero) {//AM Rule
					tsDifferentialAMRule=listTimeCardRule[i].BeforeTimeOfDay;//at most, one non-zero AM rule available at this point.
				}
				if(listTimeCardRule[i].AfterTimeOfDay!=TimeSpan.Zero) {//PM Rule
					tsDifferentialPMRule=listTimeCardRule[i].AfterTimeOfDay;//at most, one non-zero PM rule available at this point.
				}
			}
			#endregion
			//Calculations: Regular Time, Overtime, Rate2 time---------------------------------------------------------------------------------------------------
			TimeSpan tsDailyBreaksAdjustTotal=new TimeSpan();//used to adjust the clock event
			TimeSpan tsDailyBreaksTotal=new TimeSpan();//used in calculating breaks over 30 minutes per day.
			TimeSpan tsDailyDifferentialTotal=new TimeSpan();//hours before and after AM/PM diff rules. Adjusted for overbreaks.
			//Note: If TimeCardsMakesAdjustmentsForOverBreaks is true, only the first 30 minutes of break per day are paid. 
			//All breaktime thereafter will be calculated as if the employee was clocked out at that time.
			for(int i=0;i<listClockEvent.Count;i++) {
				#region  Differential pay (including overbreak adjustments)--------------------------------------------------------------
				if(i==0 || listClockEvent[i].TimeDisplayed1.Date!=listClockEvent[i-1].TimeDisplayed1.Date) {
					tsDailyDifferentialTotal=TimeSpan.Zero;
				}
				//AM-----------------------------------
				if(listClockEvent[i].TimeDisplayed1.TimeOfDay<tsDifferentialAMRule) {//clocked in before AM differential rule
					tsDailyDifferentialTotal+=tsDifferentialAMRule-listClockEvent[i].TimeDisplayed1.TimeOfDay;
					if(listClockEvent[i].TimeDisplayed2.TimeOfDay<tsDifferentialAMRule) {//clocked out before AM differential rule also
						tsDailyDifferentialTotal+=listClockEvent[i].TimeDisplayed1.TimeOfDay-tsDifferentialAMRule;//add a negative timespan
					}
					//Adjust AM differential by overbreaks-----
					TimeSpan tsAMBreakTimeCounter=new TimeSpan();
					for(int b=0;b<listClockEventBreak.Count;b++) {
						if(tsAMBreakTimeCounter>TimeSpan.FromMinutes(30)) {
							tsAMBreakTimeCounter=TimeSpan.FromMinutes(30);//reset overages for next calculation.
						}
						if(listClockEventBreak[b].TimeDisplayed1.Date!=listClockEvent[i].TimeDisplayed1.Date) {
							continue;//skip breaks for other days.
						}
						tsAMBreakTimeCounter+=listClockEventBreak[b].TimeDisplayed2-listClockEventBreak[b].TimeDisplayed1;
						if(tsAMBreakTimeCounter<TimeSpan.FromMinutes(30)) {
							continue;//not over thirty minutes yet.
						}
						if(timeClockEventsOverlapHelper(listClockEvent[i],listClockEventBreak[b])) {
							continue;//There must be multiple clock events for this day, and we have gone over breaks during a later clock event period
						}
						if(listClockEventBreak[b].TimeDisplayed1.TimeOfDay>tsDifferentialAMRule) {
							continue;//this break started after the AM differential so there is nothing left to do in this loop. break out of the entire loop.
						}
						if(listClockEventBreak[b].TimeDisplayed2.TimeOfDay-(tsAMBreakTimeCounter-TimeSpan.FromMinutes(30))>tsDifferentialAMRule) {
							continue;//entirety of break overage occured after AM differential time.
						}
						//Make adjustments because: 30+ minutes of break, break occured during clockEvent, break started before the AM rule.
						TimeSpan tsAMAdjustAmount=TimeSpan.Zero;
						tsAMAdjustAmount+=tsDifferentialAMRule-(listClockEventBreak[b].TimeDisplayed2.TimeOfDay-(tsAMBreakTimeCounter-TimeSpan.FromMinutes(30)));//should be negative timespan
						tsDailyDifferentialTotal+=tsAMAdjustAmount;
					}
				}
				//PM-------------------------------------
				if(listClockEvent[i].TimeDisplayed2.TimeOfDay>tsDifferentialPMRule) {//clocked out after PM differential rule
					tsDailyDifferentialTotal+=listClockEvent[i].TimeDisplayed2.TimeOfDay-tsDifferentialPMRule;
					if(listClockEvent[i].TimeDisplayed1.TimeOfDay>tsDifferentialPMRule) {//clocked in after PM differential rule also
						tsDailyDifferentialTotal+=tsDifferentialPMRule-listClockEvent[i].TimeDisplayed1.TimeOfDay;//add a negative timespan
					}
					//Adjust PM differential by overbreaks-----
					TimeSpan tsPMBreakTimeCounter=new TimeSpan();
					for(int b=0;b<listClockEventBreak.Count;b++) {
						if(tsPMBreakTimeCounter>TimeSpan.FromMinutes(30)) {
							tsPMBreakTimeCounter=TimeSpan.FromMinutes(30);//reset overages for next calculation.
						}
						if(listClockEventBreak[b].TimeDisplayed1.Date!=listClockEvent[i].TimeDisplayed1.Date) {
							continue;//skip breaks for other days.
						}
						tsPMBreakTimeCounter+=listClockEventBreak[b].TimeDisplayed2-listClockEventBreak[b].TimeDisplayed1;
						if(tsPMBreakTimeCounter<TimeSpan.FromMinutes(30)) {
							continue;//not over thirty minutes yet.
						}
						if(!timeClockEventsOverlapHelper(listClockEvent[i],listClockEventBreak[b])) {
							continue;//There must be multiple clock events for this day, and we have gone over breaks during a different clock event period
						}
						if(listClockEventBreak[b].TimeDisplayed2.TimeOfDay<tsDifferentialPMRule) {
							continue;//this break ended before the PM differential so there is nothing left to do in this loop. break out of the entire loop.
						}
						if(listClockEventBreak[b].TimeDisplayed2.TimeOfDay<tsDifferentialPMRule) {
							continue;//entirety of break overage occured before PM differential time.
						}
						//Make adjustments because: 30+ minutes of break, break occured during clockEvent, break ended after the PM rule.
						TimeSpan tsPMAdjustAmount=TimeSpan.Zero;
						tsPMAdjustAmount+=tsDifferentialPMRule-(listClockEventBreak[b].TimeDisplayed2.TimeOfDay-(tsPMBreakTimeCounter-TimeSpan.FromMinutes(30)));//should be negative timespan
						tsDailyDifferentialTotal+=tsPMAdjustAmount;
					}
				}
				//Apply differential to clock event-----------------------------------------------------------------------------------
				if(tsDailyDifferentialTotal<TimeSpan.Zero) {
					//this should never happen. If it ever does, we need to know about it, because that means some math has been miscalculated.
					throw new Exception(" - "+listClockEvent[i].TimeDisplayed1.Date.ToShortDateString()+" : calculated differential hours was negative.");
				}
				listClockEvent[i].Rate2Auto=tsDailyDifferentialTotal;//should be zero or greater.
				#endregion
				#region Regular hours and OT hours calulations (including overbreak adjustments)----------------------------------------
				listClockEvent[i].OTimeAuto	=TimeSpan.Zero;
				listClockEvent[i].AdjustAuto=TimeSpan.Zero;
				if(i==0 || listClockEvent[i].TimeDisplayed1.Date!=listClockEvent[i-1].TimeDisplayed1.Date) {
					tsHoursWorkedTotal=TimeSpan.Zero;
					tsDailyBreaksAdjustTotal=TimeSpan.Zero;
					tsDailyBreaksTotal=TimeSpan.Zero;
					tsDailyDifferentialTotal=TimeSpan.Zero;
				}
				tsHoursWorkedTotal+=listClockEvent[i].TimeDisplayed2-listClockEvent[i].TimeDisplayed1;//Hours worked
				if(tsHoursWorkedTotal>tsOvertimeHoursRule) {//if OverHoursPerDay then make AutoOTAdjustments.
					listClockEvent[i].OTimeAuto	+=tsHoursWorkedTotal-tsOvertimeHoursRule;//++OTimeAuto
					//listClockEvent[i].AdjustAuto-=tsHoursWorkedTotal-tsOvertimeHoursRule;//--AdjustAuto
				}
				if(i==listClockEvent.Count-1 || listClockEvent[i].TimeDisplayed1.Date!=listClockEvent[i+1].TimeDisplayed1.Date) {
					//Either the last clock event in the list or last clock event for the day.
					//OVERBREAKS--------------------------------------------------------------------------------------------------------
					if(PrefC.GetBool(PrefName.TimeCardsMakesAdjustmentsForOverBreaks)) {//Apply overbreaks to this clockEvent.
						tsDailyBreaksAdjustTotal=new TimeSpan();//used to adjust the clock event
						tsDailyBreaksTotal=new TimeSpan();//used in calculating breaks over 30 minutes per day.
						for(int b=0;b<listClockEventBreak.Count;b++) {//check all breaks for current day.
							if(listClockEventBreak[b].TimeDisplayed1.Date!=listClockEvent[i].TimeDisplayed1.Date) {
								continue;//skip breaks for other dates than current ClockEvent
							}
							tsDailyBreaksTotal+=(listClockEventBreak[b].TimeDisplayed2.TimeOfDay-listClockEventBreak[b].TimeDisplayed1.TimeOfDay);
							if(tsDailyBreaksTotal>TimeSpan.FromMinutes(31)) {//over 31 to avoid adjustments less than 1 minutes.
								listClockEventBreak[b].AdjustAuto=TimeSpan.FromMinutes(30)-tsDailyBreaksTotal;
								ClockEvents.Update(listClockEventBreak[b]);//save adjustments to breaks.
								tsDailyBreaksAdjustTotal+=listClockEventBreak[b].AdjustAuto;
								tsDailyBreaksTotal=TimeSpan.FromMinutes(30);//reset daily breaks to 30 minutes so the next break is all adjustment.
							}//end overBreaks>31 minutes
						}//end checking all breaks for current day
						//OverBreaks applies to overtime and then to RegularTime
						listClockEvent[i].OTimeAuto+=tsDailyBreaksAdjustTotal;//tsDailyBreaksTotal<=TimeSpan.Zero
						listClockEvent[i].AdjustAuto+=tsDailyBreaksAdjustTotal;//tsDailyBreaksTotal is less than or equal to zero
						if(listClockEvent[i].OTimeAuto<TimeSpan.Zero) {//we have adjusted OT too far
							//listClockEvent[i].AdjustAuto+=listClockEvent[i].OTimeAuto;
							listClockEvent[i].OTimeAuto=TimeSpan.Zero;
						}
						tsDailyBreaksTotal=TimeSpan.Zero;//zero out for the next day.
						tsHoursWorkedTotal=TimeSpan.Zero;//zero out for next day.
					}//end overbreaks
				}
				#endregion
				ClockEvents.Update(listClockEvent[i]);
			}//end clockEvent loop.
		}
Ejemplo n.º 14
0
		///<summary>Calculates daily overtime. Throws exceptions when encountering errors, though all errors SHOULD have been caught already by using the ValidatePayPeriod() function and generating a msgbox.</summary>
		public static void CalculateDailyOvertime_Old(Employee EmployeeCur,DateTime StartDate,DateTime StopDate) {
			DateTime previousDate;
			List<ClockEvent> ClockEventList=ClockEvents.Refresh(EmployeeCur.EmployeeNum,StartDate,StopDate,false);//PIn.Date(textDateStart.Text),PIn.Date(textDateStop.Text),IsBreaks);
			//Over breaks-------------------------------------------------------------------------------------------------
			if(PrefC.GetBool(PrefName.TimeCardsMakesAdjustmentsForOverBreaks)) {
				//set adj auto to zero for all.
				for(int i=0;i<ClockEventList.Count;i++) {
					ClockEventList[i].AdjustAuto=TimeSpan.Zero;
					ClockEvents.Update(ClockEventList[i]);
				}
				List<ClockEvent> breakList=ClockEvents.Refresh(EmployeeCur.EmployeeNum,StartDate,StopDate,true);//PIn.Date(textDateStart.Text),PIn.Date(textDateStop.Text),true);
				TimeSpan totalToday=TimeSpan.Zero;
				TimeSpan totalOne=TimeSpan.Zero;
				previousDate=DateTime.MinValue;
				for(int b=0;b<breakList.Count;b++) {
					if(breakList[b].TimeDisplayed2.Year<1880) {
						throw new Exception("Error. Employee break malformed.");
					}
					if(breakList[b].TimeDisplayed1.Date != breakList[b].TimeDisplayed2.Date) {
						throw new Exception("Error. One break spans multiple dates.");
					}
					//calc time for the one break
					totalOne=breakList[b].TimeDisplayed2-breakList[b].TimeDisplayed1;
					//calc daily total
					if(previousDate.Date != breakList[b].TimeDisplayed1.Date) {//if date changed, this is the first pair of the day
						totalToday=TimeSpan.Zero;//new day
						previousDate=breakList[b].TimeDisplayed1.Date;//for the next loop
					}
					totalToday+=totalOne;
					//decide if breaks for the day went over 30 min.
					if(totalToday > TimeSpan.FromMinutes(31)) {//31 to prevent silly fractions less than 1.
						//loop through all ClockEvents in this grid to find one to adjust.
						//Go backwards to find the last entry for a given date.
						for(int c=ClockEventList.Count-1;c>=0;c--) {
							if(ClockEventList[c].TimeDisplayed1.Date==breakList[b].TimeDisplayed1.Date) {
								ClockEventList[c].AdjustAuto-=(totalToday-TimeSpan.FromMinutes(30));
								ClockEvents.Update(ClockEventList[c]);
								totalToday=TimeSpan.FromMinutes(30);//reset to 30.  Therefore, any additional breaks will be wholly adjustments.
								break;
							}
							if(c==0) {//we never found a match
								throw new Exception("Error. Over breaks, but could not adjust because not regular time entered for date:"
								  +breakList[b].TimeDisplayed1.Date.ToShortDateString());
							}
						}
					}
				}
			}
			//OT-------------------------------------------------------------------------------------------------------------
			TimeCardRule afterTimeRule=null;
			TimeCardRule beforeTimeRule=null;
			TimeCardRule overHoursRule=null;
			//loop through timecardrules to find one rule of each kind.
			for(int i=0;i<TimeCardRules.Listt.Count;i++) {
				if(TimeCardRules.Listt[i].EmployeeNum!=0 && TimeCardRules.Listt[i].EmployeeNum!=EmployeeCur.EmployeeNum) {
					continue;
				}
				if(TimeCardRules.Listt[i].AfterTimeOfDay > TimeSpan.Zero) {
					if(afterTimeRule != null) {//already found a match, and this is a second match
						throw new Exception("Error.  Multiple matches of AfterTimeOfDay found for this employee.  Only one allowed.");
						//return;
					}
					afterTimeRule=TimeCardRules.Listt[i];
				}
				else if(TimeCardRules.Listt[i].OverHoursPerDay > TimeSpan.Zero) {
					if(overHoursRule != null) {//already found a match, and this is a second match
						throw new Exception("Error.  Multiple matches of OverHoursPerDay found for this employee.  Only one allowed.");
						//return;
					}
					overHoursRule=TimeCardRules.Listt[i];
				}
				if(afterTimeRule!= null && overHoursRule != null) {
					throw new Exception("Error.  Both an OverHoursPerDay and an AfterTimeOfDay found for this employee.  Only one or the other is allowed.");
					//return;
				}
				if(beforeTimeRule != null && overHoursRule != null) {
					throw new Exception("Error.  Both an OverHoursPerDay and an BeforeTimeOfDay found for this employee.  Only one or the other is allowed.");
					//return;
				}
				if(TimeCardRules.Listt[i].BeforeTimeOfDay > TimeSpan.Zero) {
					if(beforeTimeRule != null) {//already found a match, and this is a second match
						throw new Exception("Error.  Multiple matches of BeforeTimeOfDay found for this employee.  Only one allowed.");
						//return;
					}
					beforeTimeRule=TimeCardRules.Listt[i];
				}
			}
			//loop through all ClockEvents in this grid.
			TimeSpan dailyTotal=TimeSpan.Zero;
			TimeSpan pairTotal=TimeSpan.Zero;
			previousDate=DateTime.MinValue;
			for(int i=0;i<ClockEventList.Count;i++) {
				if(ClockEventList[i].TimeDisplayed2.Year<1880) {
					throw new Exception("Error. Employee not clocked out.");
					//return;
				}
				if(ClockEventList[i].TimeDisplayed1.Date != ClockEventList[i].TimeDisplayed2.Date) {
					throw new Exception("Error. One clock pair spans multiple dates.");
					//return;
				}
				pairTotal=ClockEventList[i].TimeDisplayed2-ClockEventList[i].TimeDisplayed1;
				//add any adjustments, manual or overrides.
				if(ClockEventList[i].AdjustIsOverridden) {
					pairTotal+=ClockEventList[i].Adjust;
				}
				else {
					pairTotal+=ClockEventList[i].AdjustAuto;
				}
				//calc daily total
				if(previousDate.Date != ClockEventList[i].TimeDisplayed1.Date) { //if date changed
					dailyTotal=TimeSpan.Zero;//new day
					previousDate=ClockEventList[i].TimeDisplayed1.Date;//for the next loop
				}
				dailyTotal+=pairTotal;
				//handle OT
				ClockEventList[i].OTimeAuto=TimeSpan.Zero;//set auto OT to zero.
				if(ClockEventList[i].OTimeHours != TimeSpan.FromHours(-1)) {//if OT is overridden
					//don't try to calc a time.
					ClockEvents.Update(ClockEventList[i]);//just to possibly clear autoOT, even though it doesn't count.
					//but still need to subtract OT from dailyTotal
					dailyTotal-=ClockEventList[i].OTimeHours;
					continue;
				}
				if(afterTimeRule != null) {
					//test to see if this span is after specified time
					TimeSpan afterTime=TimeSpan.Zero;
					if(ClockEventList[i].TimeDisplayed1.TimeOfDay > afterTimeRule.AfterTimeOfDay) {//the start time is after time, so the whole pairTotal is OT
						afterTime=pairTotal;
					}
					else if(ClockEventList[i].TimeDisplayed2.TimeOfDay > afterTimeRule.AfterTimeOfDay) {//only the second time is after time
						afterTime=ClockEventList[i].TimeDisplayed2.TimeOfDay-afterTimeRule.AfterTimeOfDay;//only a portion of the pairTotal is OT
					}
					ClockEventList[i].OTimeAuto=afterTime;
				}
				if(beforeTimeRule != null) {
					//test to see if this span is after specified time
					TimeSpan beforeTime=TimeSpan.Zero;
					if(ClockEventList[i].TimeDisplayed2.TimeOfDay < beforeTimeRule.BeforeTimeOfDay) {//the end time is before time, so the whole pairTotal is OT
						beforeTime+=pairTotal;
					}
					else if(ClockEventList[i].TimeDisplayed1.TimeOfDay < beforeTimeRule.BeforeTimeOfDay) {//only the first time is before time
						beforeTime+=beforeTimeRule.BeforeTimeOfDay-ClockEventList[i].TimeDisplayed1.TimeOfDay;//only a portion of the pairTotal is OT
					} 
					ClockEventList[i].OTimeAuto+=beforeTime;
				}
				if(overHoursRule != null) {
					//test dailyTotal
					TimeSpan overHours=TimeSpan.Zero;
					if(dailyTotal > overHoursRule.OverHoursPerDay) {
						overHours=dailyTotal-overHoursRule.OverHoursPerDay;
						dailyTotal=overHoursRule.OverHoursPerDay;//e.g. reset to 8.  Any further pairs on this date will be wholly OT
						ClockEventList[i].OTimeAuto+=overHours;
					}
				}
				ClockEvents.Update(ClockEventList[i]);
			}
			AdjustBreaksHelper(EmployeeCur,StartDate,StopDate);
		}
Ejemplo n.º 15
0
		///<summary>Validates list and throws exceptions.  Gets a list of time card rules for a given employee.</summary>
		public static List<TimeCardRule> GetValidList(Employee employeeCur) {
			if(RemotingClient.RemotingRole==RemotingRole.ClientWeb) {
				return Meth.GetObject<List<TimeCardRule>>(MethodBase.GetCurrentMethod(),employeeCur);
			}
			List<TimeCardRule> retVal = new List<TimeCardRule>();
			List<TimeSpan> listTimeSpansAM=new List<TimeSpan>();
			List<TimeSpan> listTimeSpansPM=new List<TimeSpan>();
			List<TimeSpan> listTimeSpansOver=new List<TimeSpan>();
			RefreshCache();
			string errors="";
			//Fill Rules list and time span list-------------------------------------------------------------------------------------------
			for(int i=0;i<listt.Count;i++) {
				if(listt[i].EmployeeNum==employeeCur.EmployeeNum || listt[i].EmployeeNum==0) {//specific rule for employee or rules that apply to all employees.
					retVal.Add(listt[i]);
					if(listt[i].BeforeTimeOfDay>TimeSpan.FromHours(0)) {
						listTimeSpansAM.Add(listt[i].BeforeTimeOfDay);
					}
					if(listt[i].AfterTimeOfDay>TimeSpan.FromHours(0)) {
						listTimeSpansPM.Add(listt[i].AfterTimeOfDay);
					}
					if(listt[i].OverHoursPerDay>TimeSpan.FromHours(0)) {
						listTimeSpansOver.Add(listt[i].OverHoursPerDay);
					}
				}
			}
			//Validate Rules---------------------------------------------------------------------------------------------------------------
			if(listTimeSpansAM.Count>1) {
				errors+="Multiple matches of BeforeTimeOfDay found, only one allowed.\r\n";
			}
			if(listTimeSpansPM.Count>1) {
				errors+="Multiple matches of AfterTimeOfDay found, only one allowed.\r\n";
			}
			if(listTimeSpansOver.Count>1) {
				errors+="Multiple matches of OverHoursPerDay found, only one allowed.\r\n";
			}
			if(listTimeSpansAM.Count+listTimeSpansPM.Count>0 && listTimeSpansOver.Count>0) {
				errors+="Both OverHoursPerDay and Rate2 rules found.\r\n";
			}
			if(errors!=""){
				throw new Exception("Time card rule errors:\r\n"+errors);
			}
			return retVal;
		}
Ejemplo n.º 16
0
		///<summary>will be deprecated with overhaul 9/13/2013. Validates pay period before making any adjustments.</summary>
		public static string ValidatePayPeriod(Employee EmployeeCur, DateTime StartDate,DateTime StopDate) {
			List<ClockEvent> breakList=ClockEvents.Refresh(EmployeeCur.EmployeeNum,StartDate,StopDate,true);
			List<ClockEvent> ClockEventList=ClockEvents.Refresh(EmployeeCur.EmployeeNum,StartDate,StopDate,false);
			bool errorFound=false;
			string retVal="Timecard errors for employee : "+Employees.GetNameFL(EmployeeCur)+"\r\n";
			//Validate clock events
			foreach(ClockEvent cCur in ClockEventList){
				if(cCur.TimeDisplayed2.Year < 1880){
					retVal+="  "+cCur.TimeDisplayed1.ToShortDateString()+" : Employee not clocked out.\r\n";
					errorFound=true;
				}
				else if(cCur.TimeDisplayed1.Date != cCur.TimeDisplayed2.Date){
					retVal+="  "+cCur.TimeDisplayed1.ToShortDateString()+" : Clock entry spans multiple days.\r\n";
					errorFound=true;
				}
			}
			//Validate Breaks
			foreach(ClockEvent bCur in breakList) {
				if(bCur.TimeDisplayed2.Year<1880) {
					retVal+="  "+bCur.TimeDisplayed1.ToShortDateString()+" : Employee not clocked in from break.\r\n";
					errorFound=true;
				}
				if(bCur.TimeDisplayed1.Date != bCur.TimeDisplayed2.Date) {
					retVal+="  "+bCur.TimeDisplayed1.ToShortDateString()+" : One break spans multiple days.\r\n";
					errorFound=true;
				}
				for(int c=ClockEventList.Count-1;c>=0;c--) {
					if(ClockEventList[c].TimeDisplayed1.Date==bCur.TimeDisplayed1.Date) {
						break;
					}
					if(c==0) {//we never found a match
						retVal+="  "+bCur.TimeDisplayed1.ToShortDateString()+" : Break found during non-working day.\r\n";
						errorFound=true;
					}
				}
			}
			//Validate OT Rules
			bool amRuleFound=false;
			bool pmRuleFound=false;
			bool hourRuleFound=false;
			TimeCardRules.RefreshCache();
			foreach(TimeCardRule tcrCur in TimeCardRules.listt){
				if(tcrCur.EmployeeNum!=EmployeeCur.EmployeeNum){
					continue;//Does not apply to this employee.
				}
				if(tcrCur.AfterTimeOfDay > TimeSpan.Zero){
					if(pmRuleFound){
						retVal+="  Multiple timecard rules for after time of day found. Only one allowed.\r\n";
						errorFound=true;
					}
					pmRuleFound=true;
				}
				if(tcrCur.BeforeTimeOfDay > TimeSpan.Zero){
					if(amRuleFound){
						retVal+="  Multiple timecard rules for before time of day found. Only one allowed.\r\n";
						errorFound=true;
					}
					amRuleFound=true;
				}
				if(tcrCur.OverHoursPerDay > TimeSpan.Zero){
					if(hourRuleFound){
						retVal+="  Multiple timecard rules for hours per day found. Only one allowed.\r\n";
						errorFound=true;
					}
					hourRuleFound=true;
				}
				if(pmRuleFound&&hourRuleFound){
					retVal+="  Both an OverHoursPerDay and an AfterTimeOfDay found for this employee.  Only one or the other is allowed.\r\n";
					errorFound=true;
				}
				if(amRuleFound&&hourRuleFound){
					retVal+="  Both an OverHoursPerDay and an BeforeTimeOfDay found for this employee.  Only one or the other is allowed.\r\n";
					errorFound=true;
				}
			}
			retVal+="\r\n";
			return (errorFound?retVal:"");
		}
Ejemplo n.º 17
0
		///<summary>-1 is also valid.</summary>
		private void SelectEmpI(int index){
			gridEmp.SetSelected(false);
			if(index==-1){
				butClockIn.Enabled=false;
				butClockOut.Enabled=false;
				butTimeCard.Enabled=false;
				butBreaks.Enabled=false;
				listStatus.Enabled=false;
				return;
			}
			gridEmp.SetSelected(index,true);
			EmployeeCur=_listEmployees[index];
			ClockEvent clockEvent=ClockEvents.GetLastEvent(EmployeeCur.EmployeeNum);
			if(clockEvent==null) {//new employee.  They need to clock in.
				butClockIn.Enabled=true;
				butClockOut.Enabled=false;
				butTimeCard.Enabled=true;
				butBreaks.Enabled=true;
				listStatus.SelectedIndex=(int)TimeClockStatus.Home;
				listStatus.Enabled=false;
			}
			else if(clockEvent.ClockStatus==TimeClockStatus.Break) {//only incomplete breaks will have been returned.
				//clocked out for break, but not clocked back in
				butClockIn.Enabled=true;
				butClockOut.Enabled=false;
				butTimeCard.Enabled=true;
				butBreaks.Enabled=true;
				listStatus.SelectedIndex=(int)TimeClockStatus.Break;
				listStatus.Enabled=false;
			}
			else {//normal clock in/out
				if(clockEvent.TimeDisplayed2.Year<1880) {//clocked in to work, but not clocked back out.
					butClockIn.Enabled=false;
					butClockOut.Enabled=true;
					butTimeCard.Enabled=true;
					butBreaks.Enabled=true;
					listStatus.Enabled=true;
				}
				else {//clocked out for home or lunch.  Need to clock back in.
					butClockIn.Enabled=true;
					butClockOut.Enabled=false;
					butTimeCard.Enabled=true;
					butBreaks.Enabled=true;
					listStatus.SelectedIndex=(int)clockEvent.ClockStatus;
					listStatus.Enabled=false;
				}
			}
		}
Ejemplo n.º 18
0
		private void butBrowseEmp_Click(object sender,EventArgs e) {
			int empIndex=0;
			for(int i=0;i<_listEmp.Count;i++) {
				//find current employee index by Employeenum
				if(EmployeeCur.EmployeeNum==_listEmp[i].EmployeeNum) {
					if(sender.Equals(butPrevEmp)) {
						empIndex=i-1;//go to previous employee in list
					}
					else {
						empIndex=i+1;//go to next employee in list
					}
					empIndex=(empIndex+_listEmp.Count)%(_listEmp.Count);//allows wrapping at end of employee list.
					break;
				}
			}
			EmployeeCur=_listEmp[empIndex];
			Text=Lan.g(this,"Time Card for")+" "+EmployeeCur.FName+" "+EmployeeCur.LName
				+(cannotEdit?" - You cannot modify your timecard":"");
			FillPayPeriod();
			FillMain(true);
		}