app=$app; if($intern) { return; } $this->app->ActionHandlerInit($this); $this->app->ActionHandler("list","ManagementboardList"); $this->app->ActionHandler("cash","ManagementboardCash"); $this->app->ActionHandler("supergraph","ManagementboardSupergraph"); $this->app->DefaultActionHandler("list"); $this->app->erp->Headlines('Managementboard'); $this->app->ActionHandlerListen($app); } public function ClearCache() { $this->app->erp->ClearSqlCache('mangementboard'); } public function ManagementboardMenu() { $this->app->erp->MenuEintrag("index.php?module=managementboard&action=list","Aufträge"); $this->app->erp->MenuEintrag("index.php?module=managementboard&action=cash","Finanzen / Cashflow"); $this->app->erp->MenuEintrag("index.php?module=managementboard&action=supergraph","Angebote / Aufträge"); $this->app->erp->RunMenuHook('managementboard'); } public function ManagementboardSupergraph() { $this->ManagementboardMenu(); $this->app->erp->Headlines('','Angebote / Aufträge'); // Angebote $offerCount = $this->app->DB->SelectArrCache( "SELECT DATE_FORMAT(an.datum, '%m/%Y') AS `month`, COUNT(an.id) AS `count` FROM angebot AS an WHERE an.status <> 'storniert' AND an.status != 'angelegt' AND DATE_FORMAT(DATE_SUB(NOW(), INTERVAL 12 MONTH), '%Y-%m-01') < an.datum GROUP BY `month`", $this->cashTime, 'mangementboard' ); // Aufträge $orderCount = $this->app->DB->SelectArrCache( "SELECT DATE_FORMAT(ab.datum, '%m/%Y') AS `month`, COUNT(ab.id) AS `count` FROM auftrag AS ab WHERE ab.status <> 'storniert' AND ab.status!='angelegt' AND DATE_FORMAT(DATE_SUB(NOW(), INTERVAL 12 MONTH), '%Y-%m-01') < ab.datum GROUP BY `month`", $this->cashTime, 'mangementboard' ); // Rechnungen $invoiceCount = $this->app->DB->SelectArrCache( "SELECT DATE_FORMAT(re.datum, '%m/%Y') AS `month`, COUNT(re.id) AS `count` FROM rechnung AS re WHERE re.status != 'angelegt' AND DATE_FORMAT(DATE_SUB(NOW(), INTERVAL 12 MONTH), '%Y-%m-01') < re.datum GROUP BY `month`", $this->cashTime, 'mangementboard' ); // Gutschriften $creditNoteCount = $this->app->DB->SelectArrCache( "SELECT DATE_FORMAT(gu.datum, '%m/%Y') AS `month`, COUNT(gu.id) AS `count` FROM gutschrift AS gu WHERE gu.status != 'angelegt' AND DATE_FORMAT(DATE_SUB(NOW(), INTERVAL 12 MONTH), '%Y-%m-01') < gu.datum GROUP BY `month`", $this->cashTime, 'mangementboard' ); // Daten auf Zeitachse matchen; Leere Monate werden aufgefüllt $begin = new DateTime(sprintf('01.01.%s', date('Y'))); $end = new DateTime('last day of this month'); $interval = new DateInterval('P1M'); $period = new PeriodMatcher($begin, $end, $interval, 'm/Y'); $labels = $period->getDates(); $offerCountData = $period->matchData($offerCount, 'month', 'count'); $orderCountData = $period->matchData($orderCount, 'month', 'count'); $invoiceCountData = $period->matchData($invoiceCount, 'month', 'count'); $creditNoteCountData = $period->matchData($creditNoteCount, 'month', 'count'); // Diagramm zusammenbauen $chart = new Chart('line'); $chart->addLabels($labels); $chart->addDataset(new Dataset('{|Angebote|}', $offerCountData)); $chart->addDataset(new Dataset('{|Aufträge|}', $orderCountData)); $chart->addDataset(new Dataset('{|Rechnungen|}', $invoiceCountData)); $chart->addDataset(new Dataset('{|Gutschriften|}', $creditNoteCountData)); $chart->accumulateData(); // Diagramm rendern $renderer = new HtmlRenderer($chart, '{|Kumulierte Angebote / Aufträge / Rechnungen / Gutschriften|}', 400, 120); $this->app->Tpl->Set('TAB1', $renderer->render()); $this->app->Tpl->Parse('PAGE','tabview.tpl'); } /** * @param int|null $seconds * * @return string */ public function getMinYear($seconds = null) { if($seconds === null) { $seconds = $this->cashTime; } $dateY = date('Y'); $minjahr = $this->app->DB->SelectArrCache( "SELECT MIN(un.jahr) AS minjahr FROM ( SELECT DISTINCT YEAR(an.datum) AS jahr FROM angebot AS an WHERE an.datum <> '0000-00-00' UNION ALL SELECT DISTINCT YEAR(au.datum) AS jahr FROM auftrag AS au WHERE au.datum <> '0000-00-00' UNION ALL SELECT DISTINCT YEAR(re.datum) AS jahr FROM rechnung AS re WHERE re.datum <> '0000-00-00' UNION ALL SELECT DISTINCT YEAR(gu.datum) AS jahr FROM gutschrift AS gu WHERE gu.datum <> '0000-00-00' ) AS un GROUP BY un.jahr LIMIT 1", $seconds, 'managementboard' ); if(!empty($minjahr)) { $minjahr = reset($minjahr); $minjahr = reset($minjahr); } if(!$minjahr) { $minjahr = $dateY; } return (String)$minjahr; } /** * @param int|string $col * @param int|null $seconds * * @return float */ public function getCashValues($col, $seconds = null) { if($seconds === null) { $seconds = $this->cashTime; } $sql = ''; switch((int)$col) { case 0: $sql = "SELECT sum(umsatz_netto) as umsatz_netto, sum(erloes_netto) as deckungsbeitrag FROM auftrag WHERE status != 'storniert' AND status!='angelegt' AND date(datum) = date(now())"; break; case 1: $sql = "SELECT sum(umsatz_netto) as umsatz_netto, sum(erloes_netto) as deckungsbeitrag FROM auftrag WHERE status != 'storniert' AND status!='angelegt' AND date(datum) = date(CURDATE()-1)"; break; case 8: $sql = "SELECT SUM(r.soll-r.ist) FROM rechnung AS r INNER JOIN projekt AS p on r.projekt = p.id WHERE r.zahlungsstatus='offen' AND r.mahnwesen!='forderungsverlust' AND r.belegnr!='' AND r.mahnwesen_gesperrt='0' AND r.mahnwesenfestsetzen!=1 AND p.mahnwesen=1"; break; case 9: $sql = "SELECT SUM(v.betrag) FROM `verbindlichkeit` AS `v` WHERE v.status!='bezahlt' AND v.status_beleg!='storniert'"; break; case 10: $sql = "select SUM(ap.menge*ap.preis*(100-ap.rabatt)/100) FROM auftrag_position ap LEFT JOIN auftrag a ON ap.auftrag=a.id LEFT JOIN adresse ad ON ad.id=a.adresse LEFT JOIN projekt p ON p.id=a.projekt WHERE ap.geliefert_menge < ap.menge AND ap.geliefert!=1 AND a.status!='abgeschlossen' AND a.status!='storniert' AND a.status!='angelegt'"; break; case 11: $sql = "SELECT SUM(r.soll-r.ist) FROM rechnung AS r INNER JOIN projekt AS p on r.projekt = p.id WHERE r.zahlungsstatus='offen' AND r.mahnwesen!='forderungsverlust' AND r.belegnr!='' AND r.mahnwesen!='' AND r.mahnwesen_gesperrt='0' AND r.mahnwesenfestsetzen!=1 AND p.mahnwesen=1"; break; case 25: $sql = "SELECT SUM(if(k.saldo_summieren,k.saldo_betrag+IFNULL((SELECT SUM(ka.haben-ka.soll) FROM kontoauszuege ka WHERE ka.konto=k.id AND ka.buchung >= k.saldo_datum AND (ka.importfehler=0 OR ka.importfehler IS NULL)),0),0)) FROM konten k LEFT JOIN projekt p ON p.id=k.projekt WHERE k.geloescht != 1 ".$this->app->erp->ProjektRechte(); break; case 14: case 18: case 22: $intervall = (int)(($col - 13) / 4); $sql = "SELECT SUM(`betrag`) FROM `verbindlichkeit` WHERE DATE_FORMAT(`rechnungsdatum`,'%Y-%m') = DATE_FORMAT(DATE_SUB(NOW(), INTERVAL $intervall MONTH),'%Y-%m') AND `status_beleg` != 'storniert'"; break; case 13: case 17: case 21: $intervall = (int)(($col - 12) / 4); if($col{3} === '1') { $sql = "SELECT sum(umsatz_netto) FROM rechnung WHERE DATE_FORMAT(datum,'%Y-%m')=DATE_FORMAT(DATE_SUB(NOW(),INTERVAL $intervall MONTH),'%Y-%m') AND status!='angelegt'"; } if($col{3} === '2') { $sql = "SELECT sum(umsatz_netto) FROM gutschrift WHERE DATE_FORMAT(datum,'%Y-%m')=DATE_FORMAT(DATE_SUB(NOW(),INTERVAL $intervall MONTH),'%Y-%m') AND status!='angelegt'"; } break; case 15: case 19: case 23: $intervall = (int)(($col - 14) / 4); if($col{3} === '1') { $sql = "SELECT sum(k.haben) FROM kontoauszuege k LEFT JOIN kontorahmen ko ON ko.sachkonto=k.gegenkonto WHERE (k.importfehler!=1 OR k.importfehler IS NULL) AND DATE_FORMAT(k.buchung,'%Y-%m')=DATE_FORMAT(DATE_SUB(NOW(),INTERVAL $intervall MONTH),'%Y-%m') AND ko.art=1 "; } if($col{3} === '2') { $sql = "SELECT sum(k.soll) FROM kontoauszuege k LEFT JOIN kontorahmen ko ON ko.sachkonto=k.gegenkonto WHERE (k.importfehler!=1 OR k.importfehler IS NULL) AND DATE_FORMAT(k.buchung,'%Y-%m')=DATE_FORMAT(DATE_SUB(NOW(),INTERVAL $intervall MONTH),'%Y-%m') AND ko.art=1 "; } break; case 16: case 20: case 24: $intervall = (int)(($col - 15) / 4); if($col{3} === '1') { $sql = "SELECT sum(haben) FROM kontoauszuege WHERE (importfehler!=1 OR importfehler IS NULL) AND DATE_FORMAT(buchung,'%Y-%m')=DATE_FORMAT(DATE_SUB(NOW(),INTERVAL $intervall MONTH),'%Y-%m')"; } if($col{3} === '2') { $sql = "SELECT sum(soll) FROM kontoauszuege WHERE (importfehler!=1 OR importfehler IS NULL) AND DATE_FORMAT(buchung,'%Y-%m')=DATE_FORMAT(DATE_SUB(NOW(),INTERVAL $intervall MONTH),'%Y-%m')"; } break; default: return (float)0; break; } if(empty($sql)) { return (float)0; } $lastTime = null; $ret = $this->app->DB->SelectArrCache($sql, $seconds, 'managementboard', $lastTime); if($lastTime !== null && strtotime($lastTime) > 1) { if($this->lastCacheTime === null || strtotime($this->lastCacheTime) > strtotime($lastTime)){ $this->lastCacheTime = $lastTime; } } if(!empty($ret)) { $ret = reset($ret); $ret = reset($ret); return (float)$ret; } return (float)0; } public function ManagementboardCash() { $this->ManagementboardMenu(); $this->app->erp->Headlines('','Finanzen / Cashflow'); $projekt = $this->app->Secure->GetPOST('projekt'); $this->app->Tpl->Set('PROJEKT',$projekt); $projekt = explode(' ',$projekt); $projekt = reset($projekt); $projekt = (int)$this->app->DB->Select("SELECT id FROM projekt WHERE abkuerzung = '$projekt' LIMIT 1"); $vergleichsjahr = $this->app->Secure->GetPOST('vergleichsjahr'); $jahr = $this->app->Secure->GetPOST('jahr'); $dateY = date('Y'); if(!$jahr) { $jahr = $dateY; } $minjahr = $this->getMinYear(); for($i = $minjahr; $i <= $dateY; $i++) { $this->app->Tpl->Add('SELJAHR',''.$i.''); } for($i = $minjahr; $i <= $dateY - 1; $i++) { $this->app->Tpl->Add('SELVERGLEICHSJAHR',''.$i.''); } $this->app->YUI->AutoComplete('projekt','projektname'); $this->lastCacheTime = $this->app->DB->Select('SELECT NOW()'); $w[0] = $this->getCashValues(0);// $this->app->DB->Select("SELECT sum(umsatz_netto) as umsatz_netto, sum(erloes_netto) as deckungsbeitrag FROM auftrag WHERE status != 'storniert' AND status!='angelegt' AND date(datum) = date(now())"); $w[1] = $this->getCashValues(1);//$this->app->DB->Select("SELECT sum(umsatz_netto) as umsatz_netto, sum(erloes_netto) as deckungsbeitrag FROM auftrag WHERE status != 'storniert' AND status!='angelegt' AND date(datum) = date(CURDATE()-1)"); $w[8] = $this->getCashValues(8);//$this->app->DB->Select("SELECT SUM(r.soll-r.ist) FROM rechnung r LEFT JOIN projekt p on r.projekt = p.id WHERE r.zahlungsstatus='offen' AND r.mahnwesen!='forderungsverlust' AND r.belegnr!='' AND r.mahnwesen_gesperrt='0' AND r.mahnwesenfestsetzen!=1 AND p.mahnwesen=1"); if($w[8] == ""){ $w[8] = "0,00"; } $w[9] = $this->getCashValues(9);//$this->app->DB->Select("SELECT SUM(v.betrag) FROM verbindlichkeit v WHERE v.status!='bezahlt' AND v.status!='storniert'"); if($w[9] == ""){ $w[9] = "0,00"; } $sql = "select SUM(ap.menge*ap.preis*(100-ap.rabatt)/100) FROM auftrag_position ap LEFT JOIN auftrag a ON ap.auftrag=a.id LEFT JOIN adresse ad ON ad.id=a.adresse LEFT JOIN projekt p ON p.id=a.projekt WHERE ap.geliefert_menge < ap.menge AND ap.geliefert!=1 AND a.status!='abgeschlossen' AND a.status!='storniert' AND a.status!='angelegt'"; $w[10] = $this->getCashValues(10);// $this->app->DB->Select($sql); if($w[10] == ""){ $w[10] = "0,00"; } $w[11] = $this->getCashValues(11);//$this->app->DB->Select("SELECT SUM(r.soll-r.ist) FROM rechnung r LEFT JOIN projekt p on r.projekt = p.id WHERE r.zahlungsstatus='offen' AND r.mahnwesen!='forderungsverlust' AND r.belegnr!='' AND r.mahnwesen!='' AND r.mahnwesen_gesperrt='0' AND r.mahnwesenfestsetzen!=1 AND p.mahnwesen=1"); if($w[11] == ""){ $w[11] = "0,00"; } $wi=12; for($intervall=0;$intervall<=2;$intervall++) { $new = true; if($new){ $w[$wi++] = $this->getCashValues($wi . '.1') - $this->getCashValues($wi . '.2'); } else{ $w[$wi++] = $this->app->DB->Select("SELECT sum(umsatz_netto) FROM rechnung WHERE DATE_FORMAT(datum,'%Y-%m')=DATE_FORMAT(DATE_SUB(NOW(),INTERVAL $intervall MONTH),'%Y-%m') AND status!='angelegt'") - $this->app->DB->Select("SELECT sum(umsatz_netto) FROM gutschrift WHERE DATE_FORMAT(datum,'%Y-%m')=DATE_FORMAT(DATE_SUB(NOW(),INTERVAL $intervall MONTH),'%Y-%m') AND status!='angelegt'"); } if($new) { $w[$wi++] = $this->getCashValues($wi); } else{ $w[$wi++] = $this->app->DB->Select( "SELECT SUM(`betrag`) FROM `verbindlichkeit` WHERE DATE_FORMAT(`rechnungsdatum`, '%Y-%m') = DATE_FORMAT(DATE_SUB(NOW(),INTERVAL $intervall MONTH),'%Y-%m') AND `status_beleg` != 'storniert'" ); } if($new){ $w[$wi++] = $this->getCashValues($wi . '.1') - $this->getCashValues($wi . '.2'); } else{ $w[$wi++] = $this->app->DB->Select("SELECT sum(k.haben) FROM kontoauszuege k LEFT JOIN kontorahmen ko ON ko.sachkonto=k.gegenkonto WHERE (k.importfehler!=1 OR k.importfehler IS NULL) AND DATE_FORMAT(k.buchung,'%Y-%m')=DATE_FORMAT(DATE_SUB(NOW(),INTERVAL $intervall MONTH),'%Y-%m') AND ko.art=1 ") - $this->app->DB->Select("SELECT sum(k.soll) FROM kontoauszuege k LEFT JOIN kontorahmen ko ON ko.sachkonto=k.gegenkonto WHERE (k.importfehler!=1 OR k.importfehler IS NULL) AND DATE_FORMAT(k.buchung,'%Y-%m')=DATE_FORMAT(DATE_SUB(NOW(),INTERVAL $intervall MONTH),'%Y-%m') AND ko.art=1 "); } if($new){ $w[$wi++] = $this->getCashValues($wi . '.1') - $this->getCashValues($wi . '.2'); } else{ $w[$wi++] = $this->app->DB->Select("SELECT sum(haben) FROM kontoauszuege WHERE (importfehler!=1 OR importfehler IS NULL) AND DATE_FORMAT(buchung,'%Y-%m')=DATE_FORMAT(DATE_SUB(NOW(),INTERVAL $intervall MONTH),'%Y-%m')") - $this->app->DB->Select("SELECT sum(soll) FROM kontoauszuege WHERE (importfehler!=1 OR importfehler IS NULL) AND DATE_FORMAT(buchung,'%Y-%m')=DATE_FORMAT(DATE_SUB(NOW(),INTERVAL $intervall MONTH),'%Y-%m')"); } } if($w[13] == ""){ $w[13] = "0,00"; } if($w[17] == ""){ $w[17] = "0,00"; } if($w[21] == ""){ $w[21] = "0,00"; } /** @var Rechnungslauf $obj */ $obj = $this->app->erp->LoadModul('rechnungslauf'); if($obj){ $w[24] = $obj->RechnungslaufRechnungslauf(true); } else { $w[24] = 0; } $w[25] = $this->getCashValues(25);//$this->app->DB->Select("SELECT SUM(if(k.saldo_summieren,k.saldo_betrag+IFNULL((SELECT SUM(ka.haben-ka.soll) FROM kontoauszuege ka WHERE ka.konto=k.id AND ka.buchung >= k.saldo_datum AND (ka.importfehler=0 OR ka.importfehler IS NULL)),0),0)) FROM konten k LEFT JOIN projekt p ON p.id=k.projekt WHERE k.geloescht != 1 ".$this->app->erp->ProjektRechte()); $this->app->Tpl->Set('FINANZENBESTELLUNGEN',number_format($w[0],2,',','.')); $this->app->Tpl->Set('FINANZENVERBINDLICHKEITEN',number_format($w[1],2,',','.')); $this->app->Tpl->Set('FINANZENRECHNUNGEN',number_format($w[2],2,',','.')); $this->app->Tpl->Set('FINANZENGUTSCHRIFTEN',number_format($w[3],2,',','.')); $this->app->Tpl->Set('UMSATZBRUTTO',number_format($w[4],2,',','.')); $this->app->Tpl->Set('UMSATZNETTO',number_format($w[5],2,',','.')); $this->app->Tpl->Set('DBINEUR',number_format($w[6],2,',','.')); $this->app->Tpl->Set('DBINPROZENT',number_format($w[7],2,',','.')); $this->app->Tpl->Set('OFFENERECHNUNGEN',number_format($w[8],2,',','.')); $this->app->Tpl->Set('OFFENEVERBINDLICHKEITEN',number_format($w[9],2,',','.')); $this->app->Tpl->Set('OFFENEAUFTRAEGE',number_format($w[10],2,',','.')); $this->app->Tpl->Set('MAHNWESEN',number_format($w[11],2,',','.')); $this->app->Tpl->Set('RECHNUNGGUTSCHRIFT',number_format($w[12],2,',','.')); $this->app->Tpl->Set('VERBINDLICHKEITEN',number_format($w[13],2,',','.')); $this->app->Tpl->Set('BANKEINNAHMEN',number_format($w[14],2,',','.')); $this->app->Tpl->Set('BANKAUSGABEN',number_format($w[15],2,',','.')); $this->app->Tpl->Set('RECHNUNGGUTSCHRIFTLETZTER',number_format($w[16],2,',','.')); $this->app->Tpl->Set('VERBINDLICHKEITENLETZTER',number_format($w[17],2,',','.')); $this->app->Tpl->Set('BANKEINNAHMENLETZTER',number_format($w[18],2,',','.')); $this->app->Tpl->Set('BANKAUSGABENLETZTER',number_format($w[19],2,',','.')); $this->app->Tpl->Set('RECHNUNGGUTSCHRIFTVORLETZTER',number_format($w[20],2,',','.')); $this->app->Tpl->Set('VERBINDLICHKEITENVORLETZTER',number_format($w[21],2,',','.')); $this->app->Tpl->Set('BANKEINNAHMENVORLETZTER',number_format($w[22],2,',','.')); $this->app->Tpl->Set('BANKAUSGABENVORLETZTER',number_format($w[23],2,',','.')); $this->app->Tpl->Set('ABOLAUF',number_format($w[24],2,',','.')); $this->app->Tpl->Set('BANKKONTENGESAMT',number_format($w[25],2,',','.')); $heute = $this->app->DB->SelectArrCache( "SELECT count(id) as co, sum(umsatz_netto) as umsatz_netto, sum(erloes_netto) as deckungsbeitrag FROM auftrag WHERE status != 'storniert' AND status!='angelegt' AND DATE_FORMAT(datum,'%m-%Y') = DATE_FORMAT(NOW(),'%m-%Y')", $this->cashTime, 'managementboard' ); // HINWEIS heute = dieser Monat :-) $paketeheute = 0; $umsatzheute = 0; $deckungsbeitragheute = 0; $dbprozentheute = 0; $deckungsbeitraggestern = 0; $dbprozentgestern = 0; if($heute) { $paketeheute = $heute[0]['co']; $umsatzheute = $heute[0]['umsatz_netto']; $deckungsbeitragheute = $heute[0]['deckungsbeitrag']; } if($umsatzheute > 0) { $dbprozentheute = 100* $deckungsbeitragheute / $umsatzheute; } if($umsatzgestern > 0) { $dbprozentgestern = 100* $deckungsbeitraggestern / $umsatzgestern; } $this->app->Tpl->Set('PAKETEHEUTE',(int)$paketeheute); $this->app->Tpl->Set('UMSATZHEUTE',number_format($umsatzheute,2,',','.')); $this->app->Tpl->Set('DECKUNGSBEITRAGHEUTE',number_format($deckungsbeitragheute,2,',','.')); $this->app->Tpl->Set('DBPROZENTHEUTE',number_format($dbprozentheute,2,',','.')); $this->app->Tpl->Set('PAKETEGESTERN',(int)$paketegestern); $this->app->Tpl->Set('UMSATZGESTERN',number_format($umsatzgestern,2,',','.')); $this->app->Tpl->Set('DECKUNGSBEITRAGGESTERN',number_format($deckungsbeitraggestern,2,',','.')); $this->app->Tpl->Set('DBPROZENTGESTERN',number_format($dbprozentgestern,2,',','.')); $zeitaktuell = (float)$this->app->DB->Select("SELECT sum(TIMESTAMPDIFF(HOUR,von,bis)) FROM zeiterfassung WHERE DATE_FORMAT(von,'%m-%Y') = DATE_FORMAT(NOW(),'%m-%Y') "); $zeitletzte = (float)$this->app->DB->Select("SELECT sum(TIMESTAMPDIFF(HOUR,von,bis)) FROM zeiterfassung WHERE DATE_FORMAT(von,'%m-%Y') = DATE_FORMAT(DATE_SUB(NOW(),INTERVAL 1 MONTH),'%m-%Y') "); $abraktuell = (float)$this->app->DB->Select("SELECT sum(TIMESTAMPDIFF(HOUR,von,bis)) FROM zeiterfassung WHERE DATE_FORMAT(von,'%m-%Y') = DATE_FORMAT(NOW(),'%m-%Y') and abrechnen = 1 "); $abrletzte = (float)$this->app->DB->Select("SELECT sum(TIMESTAMPDIFF(HOUR,von,bis)) FROM zeiterfassung WHERE DATE_FORMAT(von,'%m-%Y') = DATE_FORMAT(DATE_SUB(NOW(),INTERVAL 1 MONTH),'%m-%Y') and abrechnen = 1 "); $this->app->Tpl->Set('ZEITHEUTE',number_format($zeitaktuell,2,',','.')); $this->app->Tpl->Set('ZEITWOCHE',number_format($zeitletzte,2,',','.')); $this->app->Tpl->Set('ABRHEUTE',number_format($abraktuell,2,',','.')); $this->app->Tpl->Set('ABRWOCHE',number_format($abrletzte,2,',','.')); $this->DrawDiagramsCash($jahr, $vergleichsjahr, $projekt); $this->app->Tpl->Set('LASTCALC', 'letzte Berechnung: '.date('d.m.Y H:i:s', strtotime($this->lastCacheTime)).''); $this->app->Tpl->Parse('PAGE','managementboard_cash.tpl'); } /** * @param $jahr * @param $vergleichsjahr * @param $projekt */ public function DrawDiagramsCash($jahr, $vergleichsjahr, $projekt) { // Diagramm: Umsatz Netto $salesChart = $this->GetSalesChart($jahr, $vergleichsjahr, $projekt); $salesChartRenderer = new HtmlRenderer($salesChart, '{|Umsatz Netto|}', 400, 160); // Diagramm: Kumulierter Umsatz Netto $accumulatedSalesChart = clone $salesChart; $accumulatedSalesChart->accumulateData(); $accumulatedSalesChartRenderer = new HtmlRenderer($accumulatedSalesChart, '{|Kumulierter Umsatz Netto|}', 400, 120); $this->app->Tpl->Set('DIAGRAMM1', $salesChartRenderer->render()); $this->app->Tpl->Set('DIAGRAMM2', $accumulatedSalesChartRenderer->render()); /* $chart = new \Chart($this->app,'line'); $chart->Query("SELECT date_format(datum,'%d.%m.%Y') as tage, count(id) as anzahl, round(sum(umsatz_netto),2) as Umsatz FROM auftrag where datediff(now(),datum) <= 90 AND status != 'storniert' AND status!='angelegt' GROUP BY datum order by datum",true, array('typ'=>'tage','zeitraum'=>90)); $chart->yAxes = array(1,2); $chart->DisplayWithBox('DIAGRAMM3','auftraegeeingang','Auftragseingänge', 400, 210); */ /* $chart = new \Chart($this->app,'line'); $chart->Query("SELECT date_format(rechnungsdatum,'%d.%m.%Y') as tag, round(sum(betrag),2) as Umsatz FROM verbindlichkeit where datediff(now(),rechnungsdatum) <= 90 AND status != 'storniert' AND status!='angelegt' GROUP BY rechnungsdatum order by rechnungsdatum",true, array('typ'=>'tage','zeitraum'=>90)); $chart->DisplayWithBox('DIAGRAMM4','verbindlichkeiten','Verbindlichkeiten', 400, 175); */ } public function ManagementboardList() { $this->ManagementboardMenu(); $this->app->erp->Headlines('','Aufträge'); // Auftragseingänge $incomingOrdersChart = $this->GetIncomingOrdersChart(); $incomingOrdersRenderer = new HtmlRenderer($incomingOrdersChart, '{|Auftragseingänge|}', 400, 140); $this->app->Tpl->Set('AUFTRAGSEINGANG', $incomingOrdersRenderer->render()); // Bestellungen $purchaseOrdersChart = $this->GetPurchaseOrdersChart(); $purchaseOrdersRenderer = new HtmlRenderer($purchaseOrdersChart, '{|Bestellungen|}', 400, 140); $this->app->Tpl->Set('BESTELLUNGEN', $purchaseOrdersRenderer->render()); // Auftragseingang Projekte im Jahr $projectSalesYearChart = $this->GetIncomingOrdersForCurrentYearGroupedByProjectChart(); $projectSalesYearRenderer = new HtmlRenderer($projectSalesYearChart, '{|Auftragseingang Projekte im Jahr|}', 400, 300); $this->app->Tpl->Set('UMSATZPROJEKTEJAHR', $projectSalesYearRenderer->render()); // Auftragseingang Projekte im Monat $projectSalesMonthChart = $this->GetIncomingOrdersForCurrentMonthGroupedByProjectChart(); $projectSalesMonthRenderer = new HtmlRenderer($projectSalesMonthChart, '{|Auftragseingang Projekte im Monat|}', 400, 300); $this->app->Tpl->Set('UMSATZPROJEKTEMONAT', $projectSalesMonthRenderer->render()); // Mitarbeiter $employeesChart = $this->GetEmployeesChart(); $employeesRenderer = new HtmlRenderer($employeesChart, '{|Mitarbeiter|}', 400, 300); $this->app->Tpl->Set('MITARBEITER', $employeesRenderer->render()); // Top 5 Artikel (90 Tage) $articlesChart = $this->GetArticlesChart(); $articlesRenderer = new HtmlRenderer($articlesChart, '{|Top 5 Artikel (90 Tage)|}', 400, 300); $this->app->Tpl->Set('VERKAUFTEARTIKEL', $articlesRenderer->render()); $this->app->Tpl->Parse('PAGE','managementboard_list.tpl'); } function GetOffersByYearGroupedByMonth($year, $projectId = null) { // Angebote return $this->app->DB->SelectArrCache(sprintf( "SELECT DATE_FORMAT(an.datum, '%%m') AS `month`, SUM(an.umsatz_netto) AS `value` FROM angebot AS an WHERE an.status <> 'storniert' AND an.status != 'angelegt' AND an.datum >= '%s-01-01' AND an.datum <= '%s-12-31' %s GROUP BY `month`", $year, $year, (!empty($projectId) ? 'AND an.projekt = ' . (int)$projectId : '') ),$this->cashTime, 'mangementboard'); } function GetOrdersByYearGroupedByMonth($year, $projectId = null) { // Aufträge return $this->app->DB->SelectArrCache(sprintf( "SELECT DATE_FORMAT(ab.datum, '%%m') AS `month`, SUM(ab.umsatz_netto) AS `value` FROM auftrag AS ab WHERE ab.status <> 'storniert' AND ab.status != 'angelegt' AND ab.datum >= '%s-01-01' AND ab.datum <= '%s-12-31' %s GROUP BY `month`", $year, $year, (!empty($projectId) ? 'AND ab.projekt = ' . (int)$projectId : '') ),$this->cashTime, 'mangementboard'); } function GetInvoicesByYearGroupedByMonth($year, $projectId = null) { // Rechnungen return $this->app->DB->SelectArrCache(sprintf( "SELECT DATE_FORMAT(re.datum, '%%m') AS `month`, SUM(re.umsatz_netto) AS `value` FROM rechnung AS re WHERE re.status != 'angelegt' AND re.datum >= '%s-01-01' AND re.datum <= '%s-12-31' %s GROUP BY `month`", $year, $year, (!empty($projectId) ? 'AND re.projekt = ' . (int)$projectId : '') ),$this->cashTime, 'mangementboard'); } function GetCreditNotesByYearGroupedByMonth($year, $projectId = null) { // Gutschriften return $this->app->DB->SelectArrCache(sprintf( "SELECT DATE_FORMAT(gu.datum, '%%m') AS `month`, SUM(gu.umsatz_netto) AS `value` FROM gutschrift AS gu WHERE gu.status != 'angelegt' AND gu.datum >= '%s-01-01' AND gu.datum <= '%s-12-31' %s GROUP BY `month`", $year, $year, (!empty($projectId) ? 'AND gu.projekt = ' . (int)$projectId : '') ),$this->cashTime, 'mangementboard'); } function GetSalesChart($year, $comparisonYear, $projectId = null) { // Daten holen $offersCurrentYear = $this->GetOffersByYearGroupedByMonth($year, $projectId); $ordersCurrentYear = $this->GetOrdersByYearGroupedByMonth($year, $projectId); $invoicesCurrentYear = $this->GetInvoicesByYearGroupedByMonth($year, $projectId); $creditNotesCurrentYear = $this->GetCreditNotesByYearGroupedByMonth($year, $projectId); if (!empty($comparisonYear)) { $offersComparedYear = $this->GetOffersByYearGroupedByMonth($comparisonYear, $projectId); $ordersComparedYear = $this->GetOrdersByYearGroupedByMonth($comparisonYear, $projectId); $invoicesComparedYear = $this->GetInvoicesByYearGroupedByMonth($comparisonYear, $projectId); $creditNotesComparedYear = $this->GetCreditNotesByYearGroupedByMonth($comparisonYear, $projectId); } // Daten auf Zeitachse matchen; Leere Monate werden aufgefüllt $begin = new DateTime(sprintf('01.01.%s', $year)); $end = new DateTime(sprintf('31.12.%s', $year)); $interval = new DateInterval('P1M'); $period = new PeriodMatcher($begin, $end, $interval, 'm'); $labels = $period->getDates('m/Y'); $offersCurrentYear = $period->matchData($offersCurrentYear, 'month', 'value'); $ordersCurrentYear = $period->matchData($ordersCurrentYear, 'month', 'value'); $invoicesCurrentYear = $period->matchData($invoicesCurrentYear, 'month', 'value'); $creditNotesCurrentYear = $period->matchData($creditNotesCurrentYear, 'month', 'value'); if (!empty($comparisonYear)){ $offersComparedYear = $period->matchData($offersComparedYear, 'month', 'value'); $ordersComparedYear = $period->matchData($ordersComparedYear, 'month', 'value'); $invoicesComparedYear = $period->matchData($invoicesComparedYear, 'month', 'value'); $creditNotesComparedYear = $period->matchData($creditNotesComparedYear, 'month', 'value'); } // Diagramm zusammenbauen $chart = new Chart('line'); $chart->addLabels($labels); $chart->addDataset(new Dataset('{|Angebote|} ' . $year, $offersCurrentYear)); $chart->addDataset(new Dataset('{|Aufträge|} ' . $year, $ordersCurrentYear)); $chart->addDataset(new Dataset('{|Rechnungen|} ' . $year, $invoicesCurrentYear)); $chart->addDataset(new Dataset('{|Gutschriften|} ' . $year, $creditNotesCurrentYear)); if (!empty($comparisonYear)){ $offersComparedYearDataset = new Dataset('{|Angebote|} ' . $comparisonYear, $offersComparedYear); $ordersCurrentYearDataset = new Dataset('{|Aufträge|} ' . $comparisonYear, $ordersComparedYear); $invoicesCurrentYearDataset = new Dataset('{|Rechnungen|} ' . $comparisonYear, $invoicesComparedYear); $creditNotesCurrentYearDataset = new Dataset('{|Gutschriften|} ' . $comparisonYear, $creditNotesComparedYear); $offersComparedYearDataset->setLineStyle(Dataset::LINE_STYLE_DASHED); $ordersCurrentYearDataset->setLineStyle(Dataset::LINE_STYLE_DASHED); $invoicesCurrentYearDataset->setLineStyle(Dataset::LINE_STYLE_DASHED); $creditNotesCurrentYearDataset->setLineStyle(Dataset::LINE_STYLE_DASHED); $chart->addDataset($offersComparedYearDataset); $chart->addDataset($ordersCurrentYearDataset); $chart->addDataset($invoicesCurrentYearDataset); $chart->addDataset($creditNotesCurrentYearDataset); } return $chart; } function GetIncomingOrdersChart() { $incomingOrders = $this->app->DB->SelectArrCache( "SELECT DATE_FORMAT(a.datum, '%d.%m.%Y') AS tag, COUNT(a.id) AS anzahl, ROUND(SUM(a.umsatz_netto), 2) AS umsatz FROM auftrag AS a WHERE DATEDIFF(NOW(), a.datum) <= 90 AND a.status != 'storniert' AND a.status != 'angelegt' GROUP BY a.datum ORDER BY a.datum", $this->cashTime, 'mangementboard' ); $begin = new DateTime('90 days ago'); $end = new DateTime('now'); $interval = new DateInterval('P1D'); $period = new PeriodMatcher($begin, $end, $interval, 'd.m.Y'); $matchedData1 = $period->matchData($incomingOrders, 'tag', 'anzahl'); $matchedData2 = $period->matchData($incomingOrders, 'tag', 'umsatz'); $labels = $period->getDates(); $incomingOrdersChart = new Chart('line', $labels); $incomingOrdersChart->addDatasetAsYAxis(new Dataset('{|Anzahl|}', $matchedData1), 'left', 'linear'); $incomingOrdersChart->addDatasetAsYAxis(new Dataset('{|Umsatz|}', $matchedData2), 'right', 'linear'); return $incomingOrdersChart; } function GetPurchaseOrdersChart() { $purchaseOrders = $this->app->DB->SelectArrCache( "SELECT DATE_FORMAT(b.datum, '%d.%m.%Y') as tag, COUNT(b.id) AS anzahl, ROUND(SUM(b.gesamtsumme), 2) AS umsatz FROM bestellung AS b WHERE DATEDIFF(NOW(), b.datum) <= 90 AND b.status != 'storniert' AND b.status != 'angelegt' GROUP BY b.datum ORDER BY b.datum", $this->cashTime, 'mangementboard' ); $begin = new DateTime('90 days ago'); $end = new DateTime('now'); $interval = new DateInterval('P1D'); $period = new PeriodMatcher($begin, $end, $interval, 'd.m.Y'); $matchedData1 = $period->matchData($purchaseOrders, 'tag', 'anzahl'); $matchedData2 = $period->matchData($purchaseOrders, 'tag', 'umsatz'); $labels = $period->getDates(); $purchaseOrdersChart = new Chart('line', $labels); $purchaseOrdersChart->addDatasetAsYAxis(new Dataset('{|Anzahl|}', $matchedData1), 'left', 'linear'); $purchaseOrdersChart->addDatasetAsYAxis(new Dataset('{|Umsatz|}', $matchedData2), 'right', 'linear'); return $purchaseOrdersChart; } function GetIncomingOrdersForCurrentYearGroupedByProjectChart() { // Auftragseingang Projekte im Jahr $chartData = $this->app->DB->SelectArrCache( "SELECT IFNULL(p.abkuerzung, 'Ohne Projekt') AS name, ROUND(SUM(a.umsatz_netto), 2) AS sales, IFNULL(p.farbe, '') AS color FROM auftrag AS a LEFT JOIN projekt AS p ON a.projekt = p.id WHERE YEAR(a.datum) = YEAR(NOW()) AND a.status != 'storniert' AND a.status != 'angelegt' GROUP BY a.projekt ORDER BY SUM(a.umsatz_netto) DESC LIMIT 5", $this->cashTime, 'mangementboard' ); if ($chartData === null) { $chartData = []; } $colors = array_column($chartData, 'color'); $labels = array_column($chartData, 'name'); $data = array_column($chartData, 'sales'); $data = array_map('floatVal', $data); $dataset = new PieDataset(date('Y'), $data); $dataset->setColors($colors); return new Chart('doughnut', $labels, [$dataset]); } function GetIncomingOrdersForCurrentMonthGroupedByProjectChart() { // Auftragseingang Projekte im Monat $chartData = $this->app->DB->SelectArrCache( "SELECT IFNULL(p.abkuerzung,'Ohne Projekt') AS name, ROUND(SUM(a.umsatz_netto), 2) AS sales, IFNULL(p.farbe, '') AS color FROM auftrag a LEFT JOIN projekt p ON a.projekt = p.id WHERE YEAR(a.datum) = YEAR(NOW()) AND MONTH(a.datum) = MONTH(NOW()) AND a.status != 'storniert' AND a.status!='angelegt' GROUP BY a.projekt ORDER BY SUM(a.umsatz_netto) DESC LIMIT 5", $this->cashTime, 'mangementboard' ); if ($chartData === null) { $chartData = []; } $colors = array_column($chartData, 'color'); $labels = array_column($chartData, 'name'); $data = array_column($chartData, 'sales'); $data = array_map('floatVal', $data); $dataset = new PieDataset(date('Y'), $data); $dataset->setColors($colors); return new Chart('doughnut', $labels, [$dataset]); } function GetEmployeesChart() { $chartData = $this->app->DB->SelectArrCache( "SELECT IFNULL(p.abkuerzung, 'Ohne Projekt') AS name, COUNT(DISTINCT a.id) AS `count`, IFNULL(p.farbe, '') AS color FROM adresse AS a INNER JOIN adresse_rolle AS ar ON a.id = ar.adresse AND ar.subjekt LIKE 'Mitarbeiter' AND (ar.bis = '0000-00-00' OR ar.bis >= CURDATE() OR ISNULL(ar.bis)) LEFT JOIN projekt AS p ON a.projekt = p.id WHERE a.geloescht <> 1 GROUP BY a.projekt ORDER by COUNT(DISTINCT a.id) DESC LIMIT 5", $this->cashTime, 'mangementboard' ); if ($chartData === null) { $chartData = []; } $colors = array_column($chartData, 'color'); $labels = array_column($chartData, 'name'); $data = array_column($chartData, 'count'); $data = array_map('floatVal', $data); $dataset = new PieDataset(date('Y'), $data); $dataset->setColors($colors); return new Chart('doughnut', $labels, [$dataset]); } function GetArticlesChart() { $chartData = $this->app->DB->SelectArrCache( "SELECT CONCAT(art.nummer, ' ', SUBSTRING(art.name_de, 1, 30)) AS artikel, ROUND(SUM(rp.menge * rp.preis), 2) AS menge FROM artikel AS art INNER JOIN rechnung_position AS rp ON art.id = rp.artikel INNER JOIN rechnung AS r ON r.id = rp.rechnung WHERE r.status != 'angelegt' AND r.status <> 'storniert' AND r.status!='angelegt' AND DATEDIFF(NOW(), r.datum) <= 90 GROUP BY art.id ORDER by SUM(rp.menge * rp.preis) DESC LIMIT 5", $this->cashTime, 'mangementboard' ); if ($chartData === null) { $chartData = []; } $labels = array_column($chartData, 'artikel'); $data = array_column($chartData, 'menge'); $data = array_map('floatVal', $data); $dataset = new PieDataset(date('Y'), $data); $dataset->setColorByName(Dataset::COLOR_BLUE); return new Chart('doughnut', $labels, [$dataset]); } }