public Arbeitswoche CreateArbeitswoche(int jahr, int woche) { var aw = new Arbeitswoche(jahr, woche); var montag = DateTimeExtensions.FirstDateOfWeekIso8601(jahr, woche); aw.Arbeitstage.Add(new Arbeitstag(montag)); aw.Arbeitstage.Add(new Arbeitstag(montag.AddDays(1))); aw.Arbeitstage.Add(new Arbeitstag(montag.AddDays(2))); aw.Arbeitstage.Add(new Arbeitstag(montag.AddDays(3))); aw.Arbeitstage.Add(new Arbeitstag(montag.AddDays(4))); aw.Arbeitstage.Add(new Arbeitstag(montag.AddDays(5))); aw.Arbeitstage.Add(new Arbeitstag(montag.AddDays(6))); return(aw); }
public static AuswertungViewmodel ValidateArbeitswoche(this Arbeitswoche woche) { //frei nicht weniger als tagessatz //Nicht weniger als 4h //1 Frühdienst //1 8Uhr Dienst //2 Spätdienst //16Uhr Dienst //Kernzeit 1MA 8:30-15:30 //Kernzeit 2MA 9:00-13:00 var result = new AuswertungViewmodel(); foreach (var arbeitstag in woche.Arbeitstage) { //Samstag und Sontag ignorieren bei Planung if (arbeitstag.Datum.DayOfWeek == DayOfWeek.Saturday || arbeitstag.Datum.DayOfWeek == DayOfWeek.Sunday) { continue; } var aa = new ArbeitstagAuswertung { Wochentag = arbeitstag.Wochentag }; if (!arbeitstag.IsFeiertag) { #region Frühdienst var obGenauEinFrühdienst = arbeitstag.Planzeiten.Where(x => x.Dienst == DienstTyp.Frühdienst && x.Zeitraum.Start == x.Arbeitstag.Frühdienst).ToList(); if (obGenauEinFrühdienst.Count != 1) { var keinMehr = obGenauEinFrühdienst.Count == 0 ? "Kein" : "Mehr als ein"; var msg = $"{keinMehr} {DienstTyp.Frühdienst.GetDisplayname()} geplant für {arbeitstag.Frühdienst.ToString("HH:mm")}Uhr."; var v = new ValidationMessage() { Message = msg }; aa.Messages.Add(v); } #endregion #region Spätdienst var obGenauZweiSpätdienste = arbeitstag.Planzeiten.Where(x => x.Dienst == DienstTyp.SpätdienstEnde && x.Zeitraum.End == x.Arbeitstag.SpätdienstEnde).ToList(); if (obGenauZweiSpätdienste.Count != 2) { var keinMehr = obGenauEinFrühdienst.Count == 0 ? "Kein" : obGenauEinFrühdienst.Count == 1 ? "Nur ein" : "Mehr als ein"; var msg = $"{keinMehr} {DienstTyp.SpätdienstEnde.GetDisplayname()} geplant bis {arbeitstag.SpätdienstEnde.ToString("HH:mm")}Uhr."; var v = new ValidationMessage() { Message = msg }; aa.Messages.Add(v); } #endregion #region 8Uhr Dienst var obGenauEin8Uhrdienst = arbeitstag.Planzeiten.Where(x => x.Dienst == DienstTyp.AchtUhrDienst && x.Zeitraum.HasInside(x.Arbeitstag.AchtUhrDienst)).ToList(); if (obGenauEin8Uhrdienst.Count == 0) { var msg = $"Kein {DienstTyp.AchtUhrDienst.GetDisplayname()} geplant für {arbeitstag.AchtUhrDienst.ToString("HH:mm")}Uhr."; var v = new ValidationMessage() { Message = msg }; aa.Messages.Add(v); } #endregion #region 16Uhr Dienst var obGenauEin16Uhrdienst = arbeitstag.Planzeiten.Where(x => x.Dienst == DienstTyp.SechszehnUhrDienst && x.Zeitraum.End == x.Arbeitstag.SechzehnUhrDienst).ToList(); if (!arbeitstag.HasGrossteam && obGenauEin16Uhrdienst.Count == 0) { var msg = $"Kein {DienstTyp.SechszehnUhrDienst.GetDisplayname()} geplant bis {arbeitstag.SechzehnUhrDienst.ToString("HH:mm")}Uhr."; var v = new ValidationMessage() { Message = msg }; aa.Messages.Add(v); } #endregion #region Kernzeit var gruppen = arbeitstag.Planzeiten.Where(x => x.Gruppe != GruppenTyp.None) .GroupBy(x => x.Gruppe) .ToList(); foreach (var gruppe in gruppen) { if (!arbeitstag.CheckKernzeitAbgedeckt(gruppe.Key)) { var zeitraum = $"{arbeitstag.KernzeitBasisRange.Start.ToString("HH:mm")}-{arbeitstag.KernzeitBasisRange.End.ToString("HH:mm")}"; var msg = $"Gruppe: {gruppe.Key.GetDisplayname()} Kernzeit ({zeitraum}) nicht abgedeckt"; var v = new ValidationMessage() { Message = msg }; aa.Messages.Add(v); } else if (!arbeitstag.CheckKernzeitDoppelBesetzungAbgedeckt(gruppe.Key)) { var doppelzeitraum = $"{arbeitstag.KernzeitDoppelBesetzungRange.Start.ToString("HH:mm")}-{arbeitstag.KernzeitDoppelBesetzungRange.End.ToString("HH:mm")}"; var msgDoppel = $"Gruppe: {gruppe.Key.GetDisplayname()} Doppelbesetzung ({doppelzeitraum}) nicht abgedeckt."; var vDoppel = new ValidationMessage() { Message = msgDoppel }; aa.Messages.Add(vDoppel); } } #endregion #region Check Mindestarbeitszeit var mindestArbeitszeiten = arbeitstag.Planzeiten.Where( x => x.Dienst != DienstTyp.Frei && !x.Zeitraum.Duration.IsMindestzeitAbgedeckt()).ToList(); foreach (var planItem in mindestArbeitszeiten) { var planstunden = (planItem.GetArbeitsminutenAmKindOhnePause() / 60).ToString("#.##"); var msg = $"{planItem.ErledigtDurch?.Name}: Mindestarbeitzeit nicht abgedeckt {planItem.GetArbeitsminutenAmKindOhnePause()}Minuten ({planstunden}h)."; var v = new ValidationMessage() { Message = msg }; aa.Messages.Add(v); } #endregion } #region Check Frei Tagessollsatz var wenigerZeitAlsFreiTagessatz = arbeitstag.Planzeiten.Where( x => x.Dienst == DienstTyp.Frei && x.GetArbeitsminutenAmKindOhnePause() < x.ErledigtDurch.TagesSollMinuten).ToList(); foreach (var planItem in wenigerZeitAlsFreiTagessatz) { var planstunden = (planItem.GetArbeitsminutenAmKindOhnePause() / 60).ToString("#.##"); var msg = $"{planItem.ErledigtDurch.Name}: Dienst Frei geplant mit {planItem.GetArbeitsminutenAmKindOhnePause()}Minuten ({planstunden}h). Tagessatz: {planItem.ErledigtDurch.TagesSollMinuten}Minuten"; var v = new ValidationMessage() { Message = msg }; aa.Messages.Add(v); } #endregion if (aa.Messages.Count > 0) { result.Auswertungen.Add(aa); } else { aa.Messages.Add(new ValidationMessage() { Message = "Alles Prima :)" }); result.Auswertungen.Add(aa); } } return(result); }
private static void NichtVerplanteZeitenPlanen(Arbeitswoche woche) { var mitarbeiterPlanzeiten = woche.Arbeitstage .SelectMany(x => x.Planzeiten) .GroupBy(x => x.ErledigtDurch) .ToDictionary(x => x.Key, x => x.ToList()); foreach (var mapl in mitarbeiterPlanzeiten) { var kfz = (int)(mapl.Key.KindFreieZeit * 60); var grossteam = mapl.Value.Where(x => x.HatGrossteam).Select(x => x.Arbeitstag.Grossteam).Sum(s => (int)s.Duration.TotalMinutes); var wochenstundenAngeordnet = (int)(mapl.Key.WochenStunden * 60); var geplant = mapl.Value.Sum(x => (int)x.GetArbeitsminutenAmKindOhnePause()); var saldo = geplant + kfz + grossteam - wochenstundenAngeordnet; if (saldo < 15 && saldo > -15) { continue; } if (saldo >= 15) { var aufzuteilenMin = (int)(saldo); if (aufzuteilenMin < 15) { continue; } aufzuteilenMin = ((int)aufzuteilenMin / 15) * 15; var tage = mapl.Value.Count(x => (x.Dienst & DienstTyp.Frei) != DienstTyp.Frei); if (tage == 0) { continue; } var tagAufteilung = ((int)((int)(aufzuteilenMin / tage)) / 15) * 15; //1. Kleine Zeiten auf alle Teile foreach (var planItem in mapl.Value) { if ((planItem.Dienst & DienstTyp.Frei) == DienstTyp.Frei) { continue; } var aufteilen = 15; while (aufteilen <= tagAufteilung) { if (PlanzeitReduzierenOhneKernzeitVerletzung(planItem, 15)) { aufzuteilenMin -= 15; } else { break; } aufteilen += 15; } } //2. Rest irgendwie foreach (var planItem in mapl.Value) { if ((planItem.Dienst & DienstTyp.Frei) == DienstTyp.Frei) { continue; } var aufteilen = aufzuteilenMin; while (aufteilen > 0) { if (PlanzeitReduzierenOhneKernzeitVerletzung(planItem, 15)) { aufzuteilenMin -= 15; break; } aufteilen -= 15; } } } } }
private static void CheckKernzeitAbgedecktMitMitarbeiternVomTag(Arbeitswoche woche) { var gruppen = woche.Mitarbeiter.Select(x => x.DefaultGruppe).Distinct().ToList(); //prüfen ob alle Gruppen in der Kernzeit besetzt sind foreach (var arbeitstag in woche.Arbeitstage) { //Samstag und Sontag ignorieren bei Planung if (arbeitstag.Datum.DayOfWeek == DayOfWeek.Saturday || arbeitstag.Datum.DayOfWeek == DayOfWeek.Sunday || arbeitstag.IsFeiertag) { continue; } foreach (var gruppe in gruppen) { if (gruppe == GruppenTyp.None) { continue; } DateTime startzeit; short ticks; if (!CheckKernzeitAbgedeckt(arbeitstag, gruppe, out startzeit, out ticks)) { //beim Tag schauen in andern Gruppen var wirHabenvlltZeit = arbeitstag.Planzeiten.Where(x => (x.ErledigtDurch.DefaultGruppe & gruppe) != gruppe && !x.ErledigtDurch.IsHelfer && !x.Dienst.HasFlag(DienstTyp.Frei)) .GroupBy(g => g.Gruppe) .OrderByDescending(o => o.Count()) .ToList(); foreach (var vllt in wirHabenvlltZeit) { if (vllt.Count() < 2) { continue; } var mitarbeiterDieInDerEigentlichenGruppeGebrauchtWerden = new List <Mitarbeiter>(); var nachDienstbegin = vllt.OrderBy(x => x.Zeitraum.Start); var erster = nachDienstbegin.FirstOrDefault(); if (erster == null) { continue; } mitarbeiterDieInDerEigentlichenGruppeGebrauchtWerden.Add(erster.ErledigtDurch); var bisAbgedeckt = erster.Zeitraum.End; //gucken ohne Zeiten zu ändern while (bisAbgedeckt < arbeitstag.KernzeitGruppeEnde) { var nächster = vllt.FirstOrDefault(x => !mitarbeiterDieInDerEigentlichenGruppeGebrauchtWerden.Contains(x.ErledigtDurch) && x.Zeitraum.End >= arbeitstag.KernzeitGruppeEnde); if (nächster == null) { var alle = vllt.Where(x => !mitarbeiterDieInDerEigentlichenGruppeGebrauchtWerden.Contains(x.ErledigtDurch)) .Select(x => x.ErledigtDurch); mitarbeiterDieInDerEigentlichenGruppeGebrauchtWerden.AddRange(alle); break; } mitarbeiterDieInDerEigentlichenGruppeGebrauchtWerden.Add(nächster.ErledigtDurch); bisAbgedeckt = nächster.Zeitraum.End; } var kanditaten = vllt.Where(x => !mitarbeiterDieInDerEigentlichenGruppeGebrauchtWerden.Contains(x.ErledigtDurch)).ToList(); if (kanditaten.Count == 0) { continue; } var mindauer = (int)(startzeit.AddMinutes(ticks) - startzeit).TotalMinutes; var erstbesten = kanditaten.Where(x => x.Zeitraum.Duration.TotalMinutes >= mindauer && !x.Dienst.IstRandDienst()).OrderBy(x => x.Zeitraum.Start).FirstOrDefault() ?? kanditaten.Where(x => x.Zeitraum.Duration.TotalMinutes >= mindauer).OrderBy(x => x.Zeitraum.Start).FirstOrDefault(); if (erstbesten == null) { continue; } //Wenn nur randdienstler gefunden, dann darf der nicht "verschoben" werden in der Zeit if (erstbesten.Dienst.IstRandDienst()) { if (erstbesten.Zeitraum.Start > startzeit || erstbesten.Zeitraum.End < arbeitstag.KernzeitGruppeEnde) { continue; } } //einen Gefunden var dauer = (int)(erstbesten.Zeitraum.Duration).TotalMinutes; erstbesten.Gruppe = gruppe; //wenn die Zeiten nicht passen, dann anpassen if (erstbesten.Zeitraum.Start > startzeit) { erstbesten.Zeitraum.Start = startzeit; erstbesten.Zeitraum.End = startzeit.AddMinutes(dauer); } if (erstbesten.Zeitraum.End < arbeitstag.KernzeitGruppeEnde) { erstbesten.Zeitraum.End = arbeitstag.KernzeitGruppeEnde; erstbesten.Zeitraum.Start = arbeitstag.KernzeitGruppeEnde.AddMinutes(-1 * dauer); } break; } } } } }
private static Mitarbeiter NextMitarbeiter(IList <Mitarbeiter> alleDieDaSind, IList <Mitarbeiter> schonEingeteilt, Arbeitstag arbeitstag, Arbeitswoche woche = null, DienstTyp ma4Diensttyp = DienstTyp.None, GruppenTyp etage = GruppenTyp.Gelb | GruppenTyp.Gruen | GruppenTyp.Nest | GruppenTyp.Rot) { var arbeitstagPlanzeiten = arbeitstag.Planzeiten.ToList(); var topf = alleDieDaSind.Except(schonEingeteilt).Where(x => x.DefaultGruppe.IstFarbGruppe()).ToList(); if (topf.Count == 0) { return(null); } //alle die nicht allein sind in der gruppe var sonderTopf = topf.ToList(); var mitarbeiter = new List <Mitarbeiter>(); //Wenn RandDienst dann gilt erstmal die Wunschdienst REgel zwingend if (ma4Diensttyp.IstRandDienst()) { mitarbeiter = sonderTopf = topf.Where(x => (x.Wunschdienste & ma4Diensttyp) == ma4Diensttyp).ToList(); } //erstma gucken für die ganz RandRand Dienste //alle verfügbaren wo mehr als einer noch in der Gruppe ist //und in der Gruppe darf noch keiner einen RandRandDienst haben if (sonderTopf.Count == 0 && ma4Diensttyp.IstRandRandDienst()) { sonderTopf = topf.GroupBy(x => x.DefaultGruppe).Where(x => x.Count() > 1) .SelectMany(x => x.Where(ma => !arbeitstagPlanzeiten.Any(y => y.Gruppe == ma.DefaultGruppe && y.Dienst.IstRandRandDienst()))).ToList(); } //dann gucken für die ganz Rand Dienste if (sonderTopf.Count == 0 && ma4Diensttyp.IstRandDienst()) { sonderTopf = topf.GroupBy(x => x.DefaultGruppe).Where(x => x.Count() > 1) .SelectMany(x => x.Where(ma => !arbeitstagPlanzeiten.Any(y => y.Gruppe == ma.DefaultGruppe && y.Dienst.IstRandDienst()))).ToList(); } //Probieren einen zu Finden aus einer Gruppen die noch keinen Randdienst hat if (sonderTopf.Count == 0 && ma4Diensttyp.IstRandDienst()) { sonderTopf = topf.GroupBy(x => x.DefaultGruppe) .SelectMany(x => x.Where(ma => !arbeitstagPlanzeiten.Any(y => y.Gruppe == ma.DefaultGruppe && y.Dienst.IstRandDienst()))).ToList(); } //die mit Wunschdienst aus Etage if (mitarbeiter.Count == 0) { mitarbeiter = sonderTopf.Where(x => (x.Wunschdienste & ma4Diensttyp) == ma4Diensttyp && (etage & x.DefaultGruppe) == x.DefaultGruppe).ToList(); } //die von Etage if (mitarbeiter.Count == 0) { mitarbeiter = sonderTopf.Where(x => (etage & x.DefaultGruppe) == x.DefaultGruppe).ToList(); } //Wunschdienst if (mitarbeiter.Count == 0) { mitarbeiter = sonderTopf.Where(x => (x.Wunschdienste & ma4Diensttyp) == ma4Diensttyp).ToList(); } //Wenn mit der RandDienstlogik niemand gefunden wurde, dann vllt vorher nochmal schauen ob ein Wunschdienstler Lust hat if (mitarbeiter.Count == 0 && ma4Diensttyp.IstRandDienst()) { sonderTopf = topf.Where(x => (x.Wunschdienste & ma4Diensttyp) == ma4Diensttyp).ToList(); } if (mitarbeiter.Count == 0) { mitarbeiter = sonderTopf; } if (mitarbeiter.Count == 0)//bei allen gucken wenn keiner will { mitarbeiter = topf; } //RandDienste Gleichverteilen über die Woche if (woche != null && ma4Diensttyp.IstRandDienst()) { var geplanteRanddienste = woche.Arbeitstage.SelectMany(x => x.Planzeiten.Where(p => p.Dienst == ma4Diensttyp)).ToList(); var mitarbeiterMitRanddiensten = geplanteRanddienste.Select(x => x.ErledigtDurch).Distinct().ToList(); //irgendein Mitarbeiter da, der noch gar nix hat if (mitarbeiter.Except(mitarbeiterMitRanddiensten).Any()) { mitarbeiter = mitarbeiter.Except(mitarbeiterMitRanddiensten).ToList(); } else { var mitarbeiterMitAnzahlRanddienstInderWoche = geplanteRanddienste.GroupBy(g => g.ErledigtDurch).ToDictionary(x => x.Key, c => c.Count()); var minCount = mitarbeiterMitAnzahlRanddienstInderWoche.Min(x => x.Value); var mitarbeiterMitWenigstenCounts = mitarbeiterMitAnzahlRanddienstInderWoche.Where(x => x.Value == minCount).Select(x => x.Key).ToList(); var mitarbeiterMitMehrcounts = mitarbeiterMitAnzahlRanddienstInderWoche.Where(x => x.Value != minCount).Select(x => x.Key).ToList(); if (mitarbeiter.Intersect(mitarbeiterMitWenigstenCounts).Any()) { mitarbeiter = mitarbeiter.Intersect(mitarbeiterMitWenigstenCounts).ToList(); } else if (mitarbeiter.Except(mitarbeiterMitRanddiensten.Except(mitarbeiterMitMehrcounts)).Any()) { mitarbeiter = mitarbeiter.Except(mitarbeiterMitRanddiensten.Except(mitarbeiterMitMehrcounts)).ToList(); } //sofern noch einer übrig bleibt soll derjenige der am Vortag das gemacht, nicht nochmal dran sein var vortag = woche.Arbeitstage.Single(x => x.Datum == arbeitstag.Datum.AddDays(-1)); var letzte = vortag?.Planzeiten?.Where(x => x.Dienst == ma4Diensttyp).Select(x => x.ErledigtDurch).ToList() ?? new List <Mitarbeiter>(); if (mitarbeiter.Except(letzte).Any()) { mitarbeiter = mitarbeiter.Except(letzte).ToList(); } } //am gleichen Tag vllt nicht unbedingt auch noch aus der gleichen gruppe var ma4Gruppencheck = arbeitstag.Planzeiten.Where(x => x.Dienst == ma4Diensttyp).Select(x => x.ErledigtDurch).ToList(); var maGleicherGruppe = mitarbeiter.Where(x => ma4Gruppencheck.Any(m => m.DefaultGruppe == x.DefaultGruppe)).ToList(); if (mitarbeiter.Except(maGleicherGruppe).Any()) { mitarbeiter = mitarbeiter.Except(maGleicherGruppe).ToList(); } } int ichBinDran = Zufall.Next(0, mitarbeiter.Count); #if DEBUG Console.WriteLine($"{ma4Diensttyp}: {ichBinDran} von {mitarbeiter.Count}"); #endif return(mitarbeiter[ichBinDran]); }
public static void ErstelleWochenplan(Arbeitswoche woche, IList <Mitarbeiter> maList) { foreach (var item in woche.Arbeitstage) { item.Planzeiten.Clear(); } foreach (var arbeitstag in woche.Arbeitstage) { //Samstag und Sontag ignorieren bei Planung if (arbeitstag.Datum.DayOfWeek == DayOfWeek.Saturday || arbeitstag.Datum.DayOfWeek == DayOfWeek.Sunday) { continue; } if (arbeitstag.IsFeiertag) { //Wenn Feiertag, dann seinen Tagessatz minutengenau foreach (var mitarbeiter in maList) { arbeitstag.Planzeiten.Add(CreatePlanItem(arbeitstag, mitarbeiter, GruppenTyp.None, DienstTyp.Frei)); } continue; } //Wenn wer nicht da ist, dann seinen Tagessatz minutengenau var mitarbeiterNichtDa = maList.Where(x => x.NichtDaZeiten.Any(dt => dt == arbeitstag.Datum)).ToList(); foreach (var mitarbeiter in mitarbeiterNichtDa) { arbeitstag.Planzeiten.Add(CreatePlanItem(arbeitstag, mitarbeiter, GruppenTyp.None, DienstTyp.Frei)); } //Nur richtige Mitarbeiter die auch da sind var alledieDaSind = maList.Where(x => !x.NichtDaZeiten.Any(dt => dt == arbeitstag.Datum) && !x.IsHelfer).ToList(); var schonEingeteilt = new List <Mitarbeiter>(); #region Frühdienst var maFrüh = NextMitarbeiter(alledieDaSind, schonEingeteilt, arbeitstag, woche, DienstTyp.Frühdienst); if (maFrüh != null) { schonEingeteilt.Add(maFrüh); var istFrüh = CreatePlanItem(arbeitstag, maFrüh, maFrüh.DefaultGruppe, DienstTyp.Frühdienst); arbeitstag.Planzeiten.Add(istFrüh); } #endregion #region Spätdienst 2Mitarbeiter var maSpät1 = NextMitarbeiter(alledieDaSind, schonEingeteilt, arbeitstag, woche, DienstTyp.SpätdienstEnde); if (maSpät1 != null) { schonEingeteilt.Add(maSpät1); var istSpät1 = CreatePlanItem(arbeitstag, maSpät1, maSpät1.DefaultGruppe, DienstTyp.SpätdienstEnde); arbeitstag.Planzeiten.Add(istSpät1); } var maSpät2 = NextMitarbeiter(alledieDaSind, schonEingeteilt, arbeitstag, woche, DienstTyp.SpätdienstEnde, GibAndereEtage(maSpät1)); if (maSpät2 != null) { schonEingeteilt.Add(maSpät2); var istSpät2 = CreatePlanItem(arbeitstag, maSpät2, maSpät2.DefaultGruppe, DienstTyp.SpätdienstEnde); arbeitstag.Planzeiten.Add(istSpät2); } #endregion #region 8 uhr Dienst var ma8UhrErster = NextMitarbeiter(alledieDaSind, schonEingeteilt, arbeitstag, woche, DienstTyp.AchtUhrDienst, GibAndereEtage(maFrüh)); if (ma8UhrErster != null) { schonEingeteilt.Add(ma8UhrErster); var ist8UhrErster = CreatePlanItem(arbeitstag, ma8UhrErster, ma8UhrErster.DefaultGruppe, DienstTyp.AchtUhrDienst); arbeitstag.Planzeiten.Add(ist8UhrErster); } #endregion #region 16 Uhr Dienst if (!arbeitstag.HasGrossteam) { var ma16Uhr = NextMitarbeiter(alledieDaSind, schonEingeteilt, arbeitstag, woche, DienstTyp.SechszehnUhrDienst); if (ma16Uhr != null) { schonEingeteilt.Add(ma16Uhr); var ist16Uhr = CreatePlanItem(arbeitstag, ma16Uhr, ma16Uhr.DefaultGruppe, DienstTyp.SechszehnUhrDienst); arbeitstag.Planzeiten.Add(ist16Uhr); } } #endregion #region Gruppendienste var restMas = alledieDaSind.Where(x => !schonEingeteilt.Contains(x)).ToList(); var nestMas = restMas.Where(x => x.DefaultGruppe.HasFlag(GruppenTyp.Nest)).ToList(); FillGruppenDiensteMitKernzeitPrio(nestMas, arbeitstag, GruppenTyp.Nest, schonEingeteilt); var blauMas = restMas.Where(x => x.DefaultGruppe.HasFlag(GruppenTyp.Gelb)).ToList(); FillGruppenDiensteMitKernzeitPrio(blauMas, arbeitstag, GruppenTyp.Gelb, schonEingeteilt); var gruenMas = restMas.Where(x => x.DefaultGruppe.HasFlag(GruppenTyp.Gruen)).ToList(); FillGruppenDiensteMitKernzeitPrio(gruenMas, arbeitstag, GruppenTyp.Gruen, schonEingeteilt); var rotMas = restMas.Where(x => x.DefaultGruppe.HasFlag(GruppenTyp.Rot)).ToList(); FillGruppenDiensteMitKernzeitPrio(rotMas, arbeitstag, GruppenTyp.Rot, schonEingeteilt); var rest = alledieDaSind.Where(x => !schonEingeteilt.Contains(x)).ToList(); foreach (var mitarbeiter in rest) { arbeitstag.Planzeiten.Add(CreatePlanItem(arbeitstag, mitarbeiter, GruppenTyp.None, DienstTyp.KernzeitStartDienst)); } #endregion #region FSJ Dienste var helferleins = maList.Where(x => !x.NichtDaZeiten.Any(dt => dt == arbeitstag.Datum) && x.IsHelfer).ToList(); //Frühdienst if (!arbeitstag.HasGrossteam) { var h1 = NextMitarbeiter(helferleins, schonEingeteilt, arbeitstag, woche, DienstTyp.FsjFrühdienst); if (h1 != null) { schonEingeteilt.Add(h1); var h1Früh = CreatePlanItem(arbeitstag, h1, h1.DefaultGruppe, DienstTyp.FsjFrühdienst); arbeitstag.Planzeiten.Add(h1Früh); } var h2 = NextMitarbeiter(helferleins, schonEingeteilt, arbeitstag, woche, DienstTyp.FsjSpätdienst); if (h2 != null) { schonEingeteilt.Add(h2); var h2Früh = CreatePlanItem(arbeitstag, h2, h2.DefaultGruppe, DienstTyp.FsjSpätdienst); arbeitstag.Planzeiten.Add(h2Früh); } foreach (var helferlein in helferleins.Except(schonEingeteilt).ToList()) { schonEingeteilt.Add(helferlein); var h = CreatePlanItem(arbeitstag, helferlein, helferlein.DefaultGruppe, DienstTyp.FsjKernzeitdienst); arbeitstag.Planzeiten.Add(h); } } else { foreach (var helferlein in helferleins.Except(schonEingeteilt).ToList()) { schonEingeteilt.Add(helferlein); var hSpät = CreatePlanItem(arbeitstag, helferlein, helferlein.DefaultGruppe, DienstTyp.FsjSpätdienst); arbeitstag.Planzeiten.Add(hSpät); } } #endregion } CheckKernzeitAbgedecktMitMitarbeiternVomTag(woche); NichtVerplanteZeitenPlanen(woche); }
public MemoryStream SchreibeIstZeiten(Arbeitswoche woche, IList <Mitarbeiter> mitarbeiters, bool showThemen = false) { ExcelPackage.LicenseContext = LicenseContext.NonCommercial; using (var xls = new ExcelPackage()) { var ws = xls.Workbook.Worksheets.Add($"Woche {woche.KalenderWoche}"); ws.Workbook.CalcMode = ExcelCalcMode.Automatic; ws.Cells["A:XFD"].Style.Font.Name = "Consolas"; var row = 1; ws.Cells[row, 1, 1, 9].Merge = true; ws.Cells[row, 1].Value = $"Arbeitswoche: {woche.KalenderWoche} vom {woche.Arbeitstage.First().Datum.ToString("dd.MM.yyyy")} bis {woche.Arbeitstage.Last().Datum.ToString("dd.MM.yyyy")}"; ws.Cells[row, 1, 1, 13].Style.Font.Bold = true; row++; row++; for (int i = 0; i < woche.Arbeitstage.Count; i++) { var datum = woche.Arbeitstage[i].Datum; if (datum.DayOfWeek == DayOfWeek.Saturday || datum.DayOfWeek == DayOfWeek.Sunday) { continue; } int col = i + 2; ws.Cells[row, col].Value = datum.GetWochentagName(); } var colAngeordneteStunden = 7; ws.Cells[row, colAngeordneteStunden].Value = "ang. Std."; ws.Cells[row, colAngeordneteStunden].Style.HorizontalAlignment = ExcelHorizontalAlignment.Center; var colKfz = 8; ws.Cells[row, colKfz].Value = "KFZ"; ws.Cells[row, colKfz].Style.HorizontalAlignment = ExcelHorizontalAlignment.Center; var sortedMa = mitarbeiters.OrderBy(x => x.DefaultGruppe).ThenBy(x => x.IsHelfer).ThenBy(x => x.Name).ToList(); for (int i = 0; i < mitarbeiters.Count; i++) { row++; var obThemenRow = false; var ma = sortedMa[i]; ws.Cells[row, 1].Value = ma.Name; var color = ma.DefaultGruppe.GetFarbeFromResources(); ws.Cells[row, 1].Style.Fill.PatternType = ExcelFillStyle.Solid; ws.Cells[row, 1].Style.Fill.BackgroundColor.SetColor(System.Drawing.Color.FromArgb(color.Color.A, color.Color.R, color.Color.G, color.Color.B)); if (showThemen && woche.Arbeitstage.Any(a => a.Planzeiten.Any(x => x.ErledigtDurch.Name == ma.Name && x.Thema != Themen.None))) { ws.Cells[row + 1, 1].Style.Fill.PatternType = ExcelFillStyle.Solid; ws.Cells[row + 1, 1].Style.Fill.BackgroundColor.SetColor(System.Drawing.Color.FromArgb(color.Color.A, color.Color.R, color.Color.G, color.Color.B)); } for (int j = 0; j < woche.Arbeitstage.Count; j++) { var tag = woche.Arbeitstage[j]; //var tmp =mitarbeiters.SingleOrDefault(x => x.Name == "Robert"); //if (tag.Datum == new DateTime(2020, 7, 3) && tag.Planzeiten.Any(x=>x.ErledigtDurch==null)) //{ // var pp = tag.Planzeiten.Where(x => x.ErledigtDurch == null); // pp.First().ErledigtDurch = tmp; //} foreach (var zeiten in tag.Planzeiten.Where(x => x.ErledigtDurch.Name == ma.Name)) { if (zeiten.Dienst == DienstTyp.Frei) { continue; } ws.Cells[row, j + 2].Value = zeiten.GetInfoPlanzeitInfo(true); var c = zeiten.Gruppe != zeiten.ErledigtDurch.DefaultGruppe ? zeiten.Gruppe.GetFarbeFromResources() : zeiten.Dienst.GetFarbeFromResources(); ws.Cells[row, j + 2].Style.Fill.PatternType = ExcelFillStyle.Solid; ws.Cells[row, j + 2].Style.Fill.BackgroundColor.SetColor(System.Drawing.Color.FromArgb(c.Color.A, c.Color.R, c.Color.G, c.Color.B)); //if ((zeiten.Dienst & DienstTyp.Frühdienst)== DienstTyp.Frühdienst // || (zeiten.Dienst & DienstTyp.SpätdienstEnde) == DienstTyp.SpätdienstEnde) // ws.Cells[row, j + 2].Style.Font.Bold = true; if (showThemen && zeiten.Thema != Themen.None) { ws.Cells[row + 1, j + 2].Value = zeiten.Thema.GetDisplayname(); obThemenRow = true; } } } ws.Cells[row, colAngeordneteStunden].Value = ma.WochenStunden; ws.Cells[row, colAngeordneteStunden].Style.HorizontalAlignment = ExcelHorizontalAlignment.Center; ws.Cells[row, colKfz].Value = ma.KindFreieZeit; ws.Cells[row, colKfz].Style.HorizontalAlignment = ExcelHorizontalAlignment.Center; var oben = ws.Cells[row, 1, row, 8]; oben.Style.Border.Top.Style = ExcelBorderStyle.Thin; oben.Style.Border.Left.Style = ExcelBorderStyle.Thin; oben.Style.Border.Right.Style = ExcelBorderStyle.Thin; if (obThemenRow) { row++; } var unten = ws.Cells[row, 1, row, 8]; unten.Style.Border.Left.Style = ExcelBorderStyle.Thin; unten.Style.Border.Right.Style = ExcelBorderStyle.Thin; unten.Style.Border.Bottom.Style = ExcelBorderStyle.Thin; } if (woche.Arbeitstage.Any(x => x.HasGrossteam)) { row++; row++; var gts = woche.Arbeitstage.Where(x => x.HasGrossteam).ToList(); foreach (var at in gts) { var index = woche.Arbeitstage.IndexOf(at); ws.Cells[row, index + 2].Value = $"Großteam {Environment.NewLine}{at.Grossteam.Start.ToString("HH:mm")}-{at.Grossteam.End.ToString("HH:mm")}"; ws.Cells[row, index + 2].Style.Font.Bold = true; ws.Cells[row, index + 2].Style.WrapText = true; var border = ws.Cells[row, index + 2]; border.Style.Border.Top.Style = ExcelBorderStyle.Thin; border.Style.Border.Left.Style = ExcelBorderStyle.Thin; border.Style.Border.Right.Style = ExcelBorderStyle.Thin; border.Style.Border.Bottom.Style = ExcelBorderStyle.Thin; } } ws.Cells.AutoFitColumns(); ws.View.ShowGridLines = false; var ms = new MemoryStream(); xls.SaveAs(ms); return(ms); } }
public static ArbeitswocheViewmodel MapArbeitswocheToViewmodel(this Arbeitswoche aw) { var msgService = new WpfMessageBoxService(); var vm = new ArbeitswocheViewmodel(aw.Jahr, aw.KalenderWoche); vm.Mitarbeiter = new List <MitarbeiterViewmodel>(aw.Mitarbeiter.Select(x => x.MapMitarbeiterToViewmodel())); vm.Montag = new ArbeitstagWrapper(msgService) { Arbeitstag = aw.Arbeitstage.Single(x => x.Datum.DayOfWeek == DayOfWeek.Monday) }; vm.Dienstag = new ArbeitstagWrapper(msgService) { Arbeitstag = aw.Arbeitstage.Single(x => x.Datum.DayOfWeek == DayOfWeek.Tuesday) }; vm.Mittwoch = new ArbeitstagWrapper(msgService) { Arbeitstag = aw.Arbeitstage.Single(x => x.Datum.DayOfWeek == DayOfWeek.Wednesday) }; vm.Donnerstag = new ArbeitstagWrapper(msgService) { Arbeitstag = aw.Arbeitstage.Single(x => x.Datum.DayOfWeek == DayOfWeek.Thursday) }; vm.Freitag = new ArbeitstagWrapper(msgService) { Arbeitstag = aw.Arbeitstage.Single(x => x.Datum.DayOfWeek == DayOfWeek.Friday) }; vm.IsMontagFeiertag = vm.Montag.Arbeitstag.IsFeiertag; vm.IsDienstagFeiertag = vm.Dienstag.Arbeitstag.IsFeiertag; vm.IsMittwochFeiertag = vm.Mittwoch.Arbeitstag.IsFeiertag; vm.IsDonnerstagFeiertag = vm.Donnerstag.Arbeitstag.IsFeiertag; vm.IsFreitagFeiertag = vm.Freitag.Arbeitstag.IsFeiertag; vm.HasMontagGrossteam = vm.Montag.Arbeitstag.HasGrossteam; vm.HasDienstagGrossteam = vm.Dienstag.Arbeitstag.HasGrossteam; vm.HasMittwochGrossteam = vm.Mittwoch.Arbeitstag.HasGrossteam; vm.HasDonnerstagGrossteam = vm.Donnerstag.Arbeitstag.HasGrossteam; vm.HasFreitagGrossteam = vm.Freitag.Arbeitstag.HasGrossteam; var pwmvms = new List <PlanungswocheMitarbeiterViewmodel>(); foreach (var ma in vm.Mitarbeiter) { var pwmvm = new PlanungswocheMitarbeiterViewmodel() { Mitarbeiter = ma }; foreach (var arbeitstag in aw.Arbeitstage) { var dow = arbeitstag.Datum.DayOfWeek; var ptvm = new PlanungstagViewmodel(ma, msgService, new Action(() => pwmvm.Refresh())) { Datum = arbeitstag.Datum, Planzeit = arbeitstag.Planzeiten.SingleOrDefault(x => x.ErledigtDurch?.Name == ma.Name) ?? arbeitstag.EmptyPlanzeitOhneMitarbeiter, IsFeiertag = arbeitstag.IsFeiertag, HasGrossteam = arbeitstag.HasGrossteam }; switch (dow) { case DayOfWeek.Monday: pwmvm.Montag = ptvm; break; case DayOfWeek.Tuesday: pwmvm.Dienstag = ptvm; break; case DayOfWeek.Wednesday: pwmvm.Mittwoch = ptvm; break; case DayOfWeek.Thursday: pwmvm.Donnerstag = ptvm; break; case DayOfWeek.Friday: pwmvm.Freitag = ptvm; break; case DayOfWeek.Saturday: break; case DayOfWeek.Sunday: break; default: throw new ArgumentOutOfRangeException(); } } pwmvms.Add(pwmvm); } vm.PlanungProMitarbeiterListe = new List <PlanungswocheMitarbeiterViewmodel>(pwmvms); return(vm); }