diff --git a/www/pages/managementboard.php b/www/pages/managementboard.php index c2b82499..b8e5ef87 100644 --- a/www/pages/managementboard.php +++ b/www/pages/managementboard.php @@ -1,821 +1,821 @@ -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]); - } -} +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]); + } +}