From 98aa7d32173db278c8b3167cfc54e3226a501a73 Mon Sep 17 00:00:00 2001 From: Skylar Ittner Date: Tue, 26 Dec 2017 16:54:20 -0700 Subject: [PATCH] Add reports (close #7) --- composer.json | 4 +- composer.lock | 111 +++++++++++++- database.mwb | Bin 10268 -> 11031 bytes database.sql | 14 +- database_upgrade/v1.0.1_1.1.sql | 13 ++ lang/en_us.php | 14 +- lib/reports.php | 261 ++++++++++++++++++++++++++++++++ pages.php | 8 + pages/export.php | 40 +++++ static/js/export.js | 9 ++ 10 files changed, 468 insertions(+), 6 deletions(-) create mode 100644 database_upgrade/v1.0.1_1.1.sql create mode 100644 lib/reports.php create mode 100644 pages/export.php create mode 100644 static/js/export.js diff --git a/composer.json b/composer.json index 6b3633d..36cd777 100644 --- a/composer.json +++ b/composer.json @@ -4,7 +4,9 @@ "type": "project", "require": { "catfan/medoo": "^1.2", - "guzzlehttp/guzzle": "^6.2" + "guzzlehttp/guzzle": "^6.2", + "league/csv": "^9.0", + "lapinator/ods-php-generator": "^0.0.3" }, "license": "MPL-2.0", "authors": [ diff --git a/composer.lock b/composer.lock index e9fdb12..c8066f7 100644 --- a/composer.lock +++ b/composer.lock @@ -4,8 +4,8 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "hash": "67e95c250946f032648f9527831ec71a", - "content-hash": "36bca807ff9018548a5ce6c686d131dc", + "hash": "0476ce3c9f1be7b4a13d6533df71433d", + "content-hash": "9ff412188d3e72a7961ecf9b9e966404", "packages": [ { "name": "catfan/medoo", @@ -247,6 +247,113 @@ ], "time": "2017-03-20 17:10:46" }, + { + "name": "lapinator/ods-php-generator", + "version": "v0.0.3", + "source": { + "type": "git", + "url": "https://github.com/Lapinator/odsPhpGenerator.git", + "reference": "575314c003c2ec3032813bedcc1d27032b7b7ab2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Lapinator/odsPhpGenerator/zipball/575314c003c2ec3032813bedcc1d27032b7b7ab2", + "reference": "575314c003c2ec3032813bedcc1d27032b7b7ab2", + "shasum": "" + }, + "require": { + "php": ">=5.3" + }, + "type": "library", + "autoload": { + "classmap": [ + "src/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "LGPL-3.0" + ], + "authors": [ + { + "name": "Laurent VUIBERT", + "email": "lapinator@gmx.fr", + "homepage": "http://lapinator.net", + "role": "Developer" + } + ], + "description": "Open Document Spreadsheet (.ods) generator ", + "homepage": "https://odsphpgenerator.lapinator.net/", + "keywords": [ + "LibreOffice", + "ods" + ], + "time": "2016-04-14 21:51:27" + }, + { + "name": "league/csv", + "version": "9.1.1", + "source": { + "type": "git", + "url": "https://github.com/thephpleague/csv.git", + "reference": "66118f5c2a7e4da77e743e69f74773c63b73e8f9" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/thephpleague/csv/zipball/66118f5c2a7e4da77e743e69f74773c63b73e8f9", + "reference": "66118f5c2a7e4da77e743e69f74773c63b73e8f9", + "shasum": "" + }, + "require": { + "ext-mbstring": "*", + "php": ">=7.0.10" + }, + "require-dev": { + "ext-curl": "*", + "friendsofphp/php-cs-fixer": "^2.0", + "phpunit/phpunit": "^6.0" + }, + "suggest": { + "ext-iconv": "Needed to ease transcoding CSV using iconv stream filters" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "9.x-dev" + } + }, + "autoload": { + "psr-4": { + "League\\Csv\\": "src" + }, + "files": [ + "src/functions_include.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Ignace Nyamagana Butera", + "email": "nyamsprod@gmail.com", + "homepage": "https://github.com/nyamsprod/", + "role": "Developer" + } + ], + "description": "Csv data manipulation made easy in PHP", + "homepage": "http://csv.thephpleague.com", + "keywords": [ + "csv", + "export", + "filter", + "import", + "read", + "write" + ], + "time": "2017-11-28 08:29:49" + }, { "name": "psr/http-message", "version": "1.0.1", diff --git a/database.mwb b/database.mwb index bcb3d74df6ef98822483dcae8b03f3d2e33c1841..1496b948e5acbc6ed91ad6d76f6c49a2caf37d46 100644 GIT binary patch literal 11031 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 diff --git a/database.sql b/database.sql index 709c4d7..b4bf013 100644 --- a/database.sql +++ b/database.sql @@ -1,5 +1,5 @@ -- MySQL Script generated by MySQL Workbench --- Tue 17 Oct 2017 03:17:47 AM MDT +-- Tue 26 Dec 2017 04:44:44 PM MST -- Model: New Model Version: 1.0 -- MySQL Workbench Forward Engineering @@ -102,6 +102,18 @@ CREATE TABLE IF NOT EXISTS `inventory`.`permissions` ( ENGINE = InnoDB; +-- ----------------------------------------------------- +-- Table `inventory`.`report_access_codes` +-- ----------------------------------------------------- +CREATE TABLE IF NOT EXISTS `inventory`.`report_access_codes` ( + `id` INT NOT NULL AUTO_INCREMENT, + `code` VARCHAR(45) NULL, + `expires` DATETIME NULL, + PRIMARY KEY (`id`), + UNIQUE INDEX `id_UNIQUE` (`id` ASC)) +ENGINE = InnoDB; + + SET SQL_MODE=@OLD_SQL_MODE; SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS; SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS; diff --git a/database_upgrade/v1.0.1_1.1.sql b/database_upgrade/v1.0.1_1.1.sql new file mode 100644 index 0000000..8f3d3af --- /dev/null +++ b/database_upgrade/v1.0.1_1.1.sql @@ -0,0 +1,13 @@ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +CREATE TABLE IF NOT EXISTS `report_access_codes` ( + `id` INT(11) NOT NULL AUTO_INCREMENT, + `code` VARCHAR(45) NULL DEFAULT NULL, + `expires` DATETIME NULL DEFAULT NULL, + PRIMARY KEY (`id`), + UNIQUE INDEX `id_UNIQUE` (`id` ASC)) +ENGINE = InnoDB +DEFAULT CHARACTER SET = utf8 diff --git a/lang/en_us.php b/lang/en_us.php index 3214dc4..ed35671 100644 --- a/lang/en_us.php +++ b/lang/en_us.php @@ -95,5 +95,15 @@ define("STRINGS", [ "missing name" => "You need to enter a name.", "use the dropdowns" => "Whoops, you need to use the category and location autocomplete boxes.", "make categories and locations" => "Please create at least one category and location before adding an item.", - "search" => "Search Items" -]); \ No newline at end of file + "search" => "Search Items", + "report export" => "Reports/Export", + "report type" => "Report type", + "format" => "Format", + "generate report" => "Generate report", + "choose an option" => "Choose an option", + "csv file" => "CSV text file", + "ods file" => "ODS spreadsheet", + "html file" => "HTML web page", + "itemid" => "Item ID", + "id" => "ID" +]); diff --git a/lib/reports.php b/lib/reports.php new file mode 100644 index 0000000..432f15d --- /dev/null +++ b/lib/reports.php @@ -0,0 +1,261 @@ +has('report_access_codes', ["AND" => ['code' => $VARS['code'], 'expires[>]' => $date]])) { + dieifnotloggedin(); + } +} else { + dieifnotloggedin(); +} + +// Delete old DB entries +$database->delete('report_access_codes', ['expires[<=]' => $date]); + +if (LOADED) { + if (isset($VARS['type']) && isset($VARS['format'])) { + generateReport($VARS['type'], $VARS['format']); + die(); + } else { + lang("invalid parameters"); + die(); + } +} + +/** + * Get a 2d array of the items in the database. + * @global type $database + * @param array $filter Medoo WHERE clause. + * @return string + */ +function getItemReport($filter = []) { + global $database; + $items = $database->select( + "items", [ + "[>]locations" => ["locid"], + "[>]categories" => ["catid"] + ], [ + "itemid", + "name", + "catname", + "locname", + "code1", + "code2", + "qty", + "want", + "userid", + "text1", + "text2", + "text3" + ], $filter + ); + $header = [ + lang("itemid", false), + lang("name", false), + lang("category", false), + lang("location", false), + lang("code 1", false), + lang("code 2", false), + lang("quantity", false), + lang("want", false), + lang("assigned to", false), + lang("description", false), + lang("notes", false), + lang("comments", false) + ]; + $out = [$header]; + for ($i = 0; $i < count($items); $i++) { + $user = ""; + if (!is_null($items[$i]["userid"])) { + require_once __DIR__ . "/userinfo.php"; + $u = getUserByID($items[$i]["userid"]); + $user = $u['name'] . " (" . $u['username'] . ')'; + } + $out[] = [ + $items[$i]["itemid"], + $items[$i]["name"], + $items[$i]["catname"], + $items[$i]["locname"], + $items[$i]["code1"], + $items[$i]["code2"], + $items[$i]["qty"], + $items[$i]["want"], + $user, + $items[$i]["text1"], + $items[$i]["text2"], + $items[$i]["text3"] + ]; + } + return $out; +} + +function getCategoryReport() { + global $database; + $cats = $database->select('categories', [ + 'catid', + 'catname' + ]); + $header = [lang("id", false), lang("category", false), lang("item count", false)]; + $out = [$header]; + for ($i = 0; $i < count($cats); $i++) { + $itemcount = $database->count('items', ['catid' => $cats[$i]['catid']]); + $out[] = [ + $cats[$i]["catid"], + $cats[$i]["catname"], + $itemcount . "" + ]; + } + return $out; +} + +function getLocationReport() { + global $database; + $locs = $database->select('locations', [ + 'locid', + 'locname', + 'loccode' + ]); + $header = [lang("id", false), lang("location", false), lang("code", false), lang("item count", false)]; + $out = [$header]; + for ($i = 0; $i < count($locs); $i++) { + $itemcount = $database->count('items', ['locid' => $locs[$i]['locid']]); + $out[] = [ + $locs[$i]["locid"], + $locs[$i]["locname"], + $locs[$i]["loccode"], + $itemcount . "" + ]; + } + return $out; +} + +function getReportData($type) { + switch ($type) { + case "item": + return getItemReport(); + break; + case "category": + return getCategoryReport(); + break; + case "location": + return getLocationReport(); + break; + case "itemstock": + return getItemReport(["AND" => ["qty[<]want", "want[>]" => 0]]); + break; + default: + return [["error"]]; + } +} + +function dataToCSV($data, $name = "report") { + $csv = Writer::createFromString(''); + $csv->insertAll($data); + header('Content-type: text/csv'); + header('Content-Disposition: attachment; filename="' . $name . "_" . date("Y-m-d_Hi") . ".csv" . '"'); + echo $csv; + die(); +} + +function dataToODS($data, $name = "report") { + $ods = new ods(); + $styleColumn = new odsStyleTableColumn(); + $styleColumn->setUseOptimalColumnWidth(true); + $headerstyle = new odsStyleTableCell(); + $headerstyle->setFontWeight("bold"); + $table = new odsTable($name); + + for ($i = 0; $i < count($data[0]); $i++) { + $table->addTableColumn(new odsTableColumn($styleColumn)); + } + + $rowid = 0; + foreach ($data as $datarow) { + $row = new odsTableRow(); + foreach ($datarow as $cell) { + if ($rowid == 0) { + $row->addCell(new odsTableCellString($cell, $headerstyle)); + } else { + $row->addCell(new odsTableCellString($cell)); + } + } + $table->addRow($row); + $rowid++; + } + $ods->addTable($table); + $ods->downloadOdsFile($name . "_" . date("Y-m-d_Hi") . ".ods"); +} + +function dataToHTML($data, $name = "report") { + global $SECURE_NONCE; + // HTML exporter doesn't like null values + for ($i = 0; $i < count($data); $i++) { + for ($j = 0; $j < count($data[$i]); $j++) { + if (is_null($data[$i][$j])) { + $data[$i][$j] = ''; + } + } + } + header('Content-type: text/html'); + $converter = new HTMLConverter(); + $out = "\n" + . "\n" + . "\n" + . "" . $name . "_" . date("Y-m-d_Hi") . "\n" + . << +STYLE + . $converter->convert($data); + echo $out; +} + +function generateReport($type, $format) { + $data = getReportData($type); + switch ($format) { + case "ods": + dataToODS($data, $type); + break; + case "html": + dataToHTML($data, $type); + break; + case "csv": + default: + echo dataToCSV($data, $type); + break; + } +} diff --git a/pages.php b/pages.php index eb6daab..2218f0b 100644 --- a/pages.php +++ b/pages.php @@ -75,6 +75,14 @@ define("PAGES", [ "static/js/editloc.js" ], ], + "export" => [ + "title" => "report export", + "navbar" => true, + "icon" => "download", + "scripts" => [ + "static/js/export.js" + ] + ], "404" => [ "title" => "404 error" ] diff --git a/pages/export.php b/pages/export.php new file mode 100644 index 0000000..97f86a9 --- /dev/null +++ b/pages/export.php @@ -0,0 +1,40 @@ + + +
+
+
+ + +
+
+ + +
+
+
+ insert('report_access_codes', ['code' => $code, 'expires' => date("Y-m-d H:i:s", strtotime("+5 minutes"))]); + ?> + + + +
\ No newline at end of file diff --git a/static/js/export.js b/static/js/export.js new file mode 100644 index 0000000..430ba51 --- /dev/null +++ b/static/js/export.js @@ -0,0 +1,9 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +$("#genrptbtn").click(function () { + setTimeout(function () { + window.location.reload(); + }, 1000) +}); \ No newline at end of file