diff --git a/Controller/ApiController.php b/Controller/ApiController.php index d559c11..bef1a66 100755 --- a/Controller/ApiController.php +++ b/Controller/ApiController.php @@ -38,6 +38,7 @@ use phpOMS\Message\Http\RequestStatusCode; use phpOMS\Message\NotificationLevel; use phpOMS\Message\RequestAbstract; use phpOMS\Message\ResponseAbstract; +use phpOMS\Model\Message\FormValidation; use phpOMS\System\MimeType; use phpOMS\Utils\Parser\Markdown\Markdown; use phpOMS\Utils\StringUtils; @@ -68,29 +69,29 @@ final class ApiController extends Controller */ public function apiHelperExport(HttpRequest $request, HttpResponse $response, $data = null) : void { + if (!empty($val = $this->validateExport($request))) { + $response->set('export', new FormValidation($val)); + $response->header->status = RequestStatusCode::R_400; + + return; + } + /** @var Template $template */ $template = TemplateMapper::get((int) $request->getData('id')); $accountId = $request->header->account; + $isExport = \in_array($request->getData('type'), ['xlsx', 'pdf', 'docx', 'pptx', 'csv', 'json']); + // is allowed to read - if (!$this->app->accountManager->get($accountId)->hasPermission( - PermissionType::READ, $this->app->orgId, null, self::NAME, PermissionState::REPORT, $template->getId()) + if (!$this->app->accountManager->get($accountId)->hasPermission(PermissionType::READ, $this->app->orgId, null, self::NAME, PermissionState::REPORT, $template->getId()) + || ($isExport && !$this->app->accountManager->get($accountId)->hasPermission(PermissionType::READ, $this->app->orgId, $this->app->appName, self::NAME, PermissionState::EXPORT)) ) { $response->header->status = RequestStatusCode::R_403; return; } - if (\in_array($request->getData('type'), ['xlsx', 'pdf', 'docx', 'pptx', 'csv'])) { - // is allowed to export - if (!$this->app->accountManager->get($accountId)->hasPermission( - PermissionType::READ, $this->app->orgId, $this->app->appName, self::NAME, PermissionState::EXPORT - )) { - $response->header->status = RequestStatusCode::R_403; - - return; - } - + if ($isExport) { Autoloader::addPath(__DIR__ . '/../../../Resources/'); $response->header->setDownloadable($template->name, (string) $request->getData('type')); } @@ -102,6 +103,25 @@ final class ApiController extends Controller $response->set('export', $view); } + /** + * Validate export request + * + * @param RequestAbstract $request Request + * + * @return array + * + * @since 1.0.0 + */ + private function validateExport(RequestAbstract $request) : array + { + $val = []; + if (($val['id'] = empty($request->getData('id')))) { + return $val; + } + + return []; + } + /** * Set header for report/template * @@ -127,7 +147,7 @@ final class ApiController extends Controller . '"' , true); $response->header->set('Content-Type', MimeType::M_PDF, true); - $view->setTemplate('/' . \substr($view->getData('tcoll')['pdf']->getPath(), 0, -8), 'pdf.php'); + $view->setTemplate('/' . \substr($view->getData('tcoll')['pdf']?->getPath(), 0, -8), 'pdf.php'); break; case 'csv': $response->header->set( @@ -137,7 +157,7 @@ final class ApiController extends Controller . '"' , true); $response->header->set('Content-Type', MimeType::M_CONF, true); - $view->setTemplate('/' . \substr($view->getData('tcoll')['csv']->getPath(), 0, -8), 'csv.php'); + $view->setTemplate('/' . \substr($view->getData('tcoll')['csv']?->getPath(), 0, -8), 'csv.php'); break; case 'xls': case 'xlsx': @@ -148,7 +168,7 @@ final class ApiController extends Controller . '"' , true); $response->header->set('Content-Type', MimeType::M_XLSX, true); - $view->setTemplate('/' . \substr($view->getData('tcoll')['excel']->getPath(), 0, -8), 'xls.php'); + $view->setTemplate('/' . \substr($view->getData('tcoll')['excel']?->getPath(), 0, -8), 'xls.php'); break; case 'doc': case 'docx': @@ -159,7 +179,7 @@ final class ApiController extends Controller . '"' , true); $response->header->set('Content-Type', MimeType::M_XLSX, true); - $view->setTemplate('/' . \substr($view->getData('tcoll')['word']->getPath(), 0, -8), 'doc.php'); + $view->setTemplate('/' . \substr($view->getData('tcoll')['word']?->getPath(), 0, -8), 'doc.php'); break; case 'ppt': case 'pptx': @@ -170,15 +190,15 @@ final class ApiController extends Controller . '"' , true); $response->header->set('Content-Type', MimeType::M_XLSX, true); - $view->setTemplate('/' . \substr($view->getData('tcoll')['powerpoint']->getPath(), 0, -8), 'ppt.php'); + $view->setTemplate('/' . \substr($view->getData('tcoll')['powerpoint']?->getPath(), 0, -8), 'ppt.php'); break; case 'json': $response->header->set('Content-Type', MimeType::M_JSON, true); - $view->setTemplate('/' . \substr($view->getData('tcoll')['json']->getPath(), 0, -9), 'json.php'); + $view->setTemplate('/' . \substr($view->getData('tcoll')['json']?->getPath(), 0, -9), 'json.php'); break; default: $response->header->set('Content-Type', 'text/html; charset=utf-8'); - $view->setTemplate('/' . \substr($view->getData('tcoll')['template']->getPath(), 0, -8)); + $view->setTemplate('/' . \substr($view->getData('tcoll')['template']?->getPath(), 0, -8)); } } @@ -199,7 +219,7 @@ final class ApiController extends Controller { /** @var array $tcoll */ $tcoll = []; - $files = $template->getSource()->getSources(); + $files = $template->source->getSources(); /** @var \Modules\Media\Models\Media $tMedia */ foreach ($files as $tMedia) { @@ -264,7 +284,7 @@ final class ApiController extends Controller } $view = new View($this->app->l11nManager, $request, $response); - if (!$template->isStandalone()) { + if (!$template->isStandalone) { /** @var Report[] $report */ $report = ReportMapper::getNewest(1, (new Builder($this->app->dbPool->get()))->where('helper_report.helper_report_template', '=', $template->getId()) @@ -275,7 +295,7 @@ final class ApiController extends Controller $report = $report === false ? new NullReport() : $report; if (!($report instanceof NullReport)) { - $files = $report->getSource()->getSources(); + $files = $report->source->getSources(); foreach ($files as $media) { $rcoll[$media->name . '.' . $media->extension] = $media; @@ -313,17 +333,30 @@ final class ApiController extends Controller $uploadedFiles = $request->getFiles() ?? []; $files = []; - if (!empty($uploadedFiles)) { - $uploaded = $this->app->moduleManager->get('Media')->uploadFiles( - [$request->getData('name') ?? ''], - $uploadedFiles, - $request->header->account, - __DIR__ . '/../../../Modules/Media/Files' - ); + if (!empty($val = $this->validateTemplateCreate($request))) { + $response->set('template_create', new FormValidation($val)); + $response->header->status = RequestStatusCode::R_400; - foreach ($uploaded as $upload) { - $files[] = new NullMedia($upload->getId()); - } + return; + } + + // is allowed to create + if (!$this->app->accountManager->get($request->header->account)->hasPermission(PermissionType::CREATE, $this->app->orgId, null, self::NAME, PermissionState::TEMPLATE)) { + $response->header->status = RequestStatusCode::R_403; + + return; + } + + $uploaded = $this->app->moduleManager->get('Media')->uploadFiles( + $request->getDataList('names') ?? [], + $request->getDataList('filenames') ?? [], + $uploadedFiles, + $request->header->account, + __DIR__ . '/../../../Modules/Media/Files' + ); + + foreach ($uploaded as $upload) { + $files[] = new NullMedia($upload->getId()); } foreach ($dbFiles as $db) { @@ -338,9 +371,6 @@ final class ApiController extends Controller $request->header->account ); - $collection->setPath('/Modules/Media/Files/Modules/Helper/' . ((string) ($request->getData('name') ?? ''))); - $collection->setVirtualPath('/Modules/Helper'); - if ($collection instanceof NullCollection) { $response->header->status = RequestStatusCode::R_403; $this->fillJsonResponse($request, $response, NotificationLevel::ERROR, 'Template', 'Couldn\'t create collection for template', null); @@ -348,6 +378,9 @@ final class ApiController extends Controller return; } + $collection->setPath('/Modules/Media/Files/Modules/Helper/' . ((string) ($request->getData('name') ?? ''))); + $collection->setVirtualPath('/Modules/Helper'); + CollectionMapper::create($collection); $template = $this->createTemplateFromRequest($request, $collection->getId()); @@ -372,6 +405,27 @@ final class ApiController extends Controller $this->fillJsonResponse($request, $response, NotificationLevel::OK, 'Template', 'Template successfully created', $template); } + /** + * Validate template create request + * + * @param RequestAbstract $request Request + * + * @return array + * + * @since 1.0.0 + */ + private function validateTemplateCreate(RequestAbstract $request) : array + { + $val = []; + if (($val['name'] = empty($request->getData('name'))) + || ($val['files'] = empty($request->getFiles() ?? [])) + ) { + return $val; + } + + return []; + } + /** * Method to create template from request. * @@ -391,14 +445,14 @@ final class ApiController extends Controller $helperTemplate->descriptionRaw = (string) ($request->getData('description') ?? ''); if ($collectionId > 0) { - $helperTemplate->setSource(new NullCollection($collectionId)); + $helperTemplate->source = new NullCollection($collectionId); } - $helperTemplate->setStandalone((bool) ($request->getData('standalone') ?? false)); + $helperTemplate->isStandalone = (bool) ($request->getData('standalone') ?? false); $helperTemplate->setExpected(!empty($expected) ? \json_decode($expected, true) : []); $helperTemplate->createdBy = new NullAccount($request->header->account); $helperTemplate->setDatatype((int) ($request->getData('datatype') ?? TemplateDataType::OTHER)); - $helperTemplate->setVirtualPath((string) ($request->getData('virtualpath') ?? '/')); + $helperTemplate->virtualPath = (string) ($request->getData('virtualpath') ?? '/'); if (!empty($tags = $request->getDataJson('tags'))) { foreach ($tags as $tag) { @@ -435,8 +489,23 @@ final class ApiController extends Controller */ public function apiReportCreate(RequestAbstract $request, ResponseAbstract $response, $data = null) : void { + if (!empty($val = $this->validateReportCreate($request))) { + $response->set('report_create', new FormValidation($val)); + $response->header->status = RequestStatusCode::R_400; + + return; + } + + // is allowed to create + if (!$this->app->accountManager->get($request->header->account)->hasPermission(PermissionType::CREATE, $this->app->orgId, null, self::NAME, PermissionState::REPORT)) { + $response->header->status = RequestStatusCode::R_403; + + return; + } + $files = $this->app->moduleManager->get('Media')->uploadFiles( - [$request->getData('name') ?? ''], + $request->getDataList('names') ?? [], + $request->getDataList('filenames') ?? [], $request->getFiles(), $request->header->account, __DIR__ . '/../../../Modules/Media/Files' @@ -483,6 +552,26 @@ final class ApiController extends Controller $this->fillJsonResponse($request, $response, NotificationLevel::OK, 'Report', 'Report successfully created', $report); } + /** + * Validate template create request + * + * @param RequestAbstract $request Request + * + * @return array + * + * @since 1.0.0 + */ + private function validateReportCreate(RequestAbstract $request) : array + { + $val = []; + if (($val['template'] = empty($request->getData('template'))) + ) { + return $val; + } + + return []; + } + /** * Method to create report from request. * @@ -496,10 +585,10 @@ final class ApiController extends Controller */ private function createReportFromRequest(RequestAbstract $request, ResponseAbstract $response, int $collectionId) : Report { - $helperReport = new Report(); - $helperReport->title = (string) ($request->getData('name')); - $helperReport->setSource(new NullCollection($collectionId)); - $helperReport->setTemplate(new NullTemplate((int) $request->getData('template'))); + $helperReport = new Report(); + $helperReport->title = (string) ($request->getData('name')); + $helperReport->source = new NullCollection($collectionId); + $helperReport->template = new NullTemplate((int) $request->getData('template')); $helperReport->createdBy = new NullAccount($request->header->account); return $helperReport; diff --git a/Models/Report.php b/Models/Report.php index 0d98ef1..44821d2 100755 --- a/Models/Report.php +++ b/Models/Report.php @@ -16,7 +16,6 @@ namespace Modules\Helper\Models; use Modules\Admin\Models\Account; use Modules\Admin\Models\NullAccount; -use Modules\Helper\Admin\Install\Media; use Modules\Media\Models\Collection; use Modules\Media\Models\NullCollection; @@ -92,7 +91,7 @@ class Report implements \JsonSerializable * @var Template * @since 1.0.0 */ - private Template $template; + public Template $template; /** * Report source. @@ -100,7 +99,7 @@ class Report implements \JsonSerializable * @var Collection * @since 1.0.0 */ - private Collection $source; + public Collection $source; /** * Constructor. @@ -153,58 +152,6 @@ class Report implements \JsonSerializable $this->status = $status; } - /** - * Get template this report belongs to - * - * @return Template - * - * @since 1.0.0 - */ - public function getTemplate() : Template - { - return $this->template; - } - - /** - * Set template this report belongs to - * - * @param Template $template Report template - * - * @return void - * - * @since 1.0.0 - */ - public function setTemplate(Template $template) : void - { - $this->template = $template; - } - - /** - * Set source media for the report - * - * @param Collection $source Report source - * - * @return void - * - * @since 1.0.0 - */ - public function setSource(Collection $source) : void - { - $this->source = $source; - } - - /** - * Get source media for the report - * - * @return Collection - * - * @since 1.0.0 - */ - public function getSource() : Collection - { - return $this->source; - } - /** * {@inheritdoc} */ diff --git a/Models/Template.php b/Models/Template.php index acbbc29..88f47de 100755 --- a/Models/Template.php +++ b/Models/Template.php @@ -46,7 +46,7 @@ class Template implements \JsonSerializable * @var Unit * @since 1.0.0 */ - private Unit $unit; + public Unit $unit; /** * Template status. @@ -70,7 +70,7 @@ class Template implements \JsonSerializable * @var bool * @since 1.0.0 */ - private bool $isStandalone = false; + public bool $isStandalone = false; /** * Template name. @@ -118,7 +118,7 @@ class Template implements \JsonSerializable * @var Collection * @since 1.0.0 */ - private Collection $source; + public Collection $source; /** * Expected files. @@ -149,8 +149,10 @@ class Template implements \JsonSerializable * * @var string * @since 1.0.0 + * + * @todo maybe never used, check */ - private string $virtualPath = '/'; + public string $virtualPath = '/'; /** * Constructor @@ -177,34 +179,6 @@ class Template implements \JsonSerializable return $this->id; } - /** - * Get unit this template belogns to - * - * @return Unit - * - * @since 1.0.0 - */ - public function getUnit() : Unit - { - return $this->unit; - } - - /** - * Set unit this model belongs to - * - * Set the unit - * - * @param Unit $unit Unit - * - * @return void - * - * @since 1.0.0 - */ - public function setUnit(Unit $unit) : void - { - $this->unit = $unit; - } - /** * Get newest report for template. * @@ -221,58 +195,6 @@ class Template implements \JsonSerializable return new NullReport(); } - /** - * Get the path - * - * @return string - * - * @since 1.0.0 - */ - public function getVirtualPath() : string - { - return $this->virtualPath; - } - - /** - * Set the path if file - * - * @param string $path Path to file - * - * @return mixed - * - * @since 1.0.0 - */ - public function setVirtualPath(string $path) - { - $this->virtualPath = $path; - } - - /** - * Set source media - * - * @param Collection $source Source - * - * @return void - * - * @since 1.0.0 - */ - public function setSource(Collection $source) : void - { - $this->source = $source; - } - - /** - * Get source media - * - * @return Collection - * - * @since 1.0.0 - */ - public function getSource() : Collection - { - return $this->source; - } - /** * Get expected files from report * @@ -365,32 +287,6 @@ class Template implements \JsonSerializable return $this->datatype; } - /** - * Set if the template needs report data - * - * @param bool $isStandalone Is template standalone - * - * @return void - * - * @since 1.0.0 - */ - public function setStandalone(bool $isStandalone) : void - { - $this->isStandalone = $isStandalone; - } - - /** - * Does the template need report data? - * - * @return bool - * - * @since 1.0.0 - */ - public function isStandalone() : bool - { - return $this->isStandalone; - } - /** * Get tags * diff --git a/tests/Bootstrap.php b/tests/Bootstrap.php index 051ac7e..f5fc99c 100755 --- a/tests/Bootstrap.php +++ b/tests/Bootstrap.php @@ -392,4 +392,4 @@ function phpServe() : void }); } -phpServe(); +\phpServe(); diff --git a/tests/Controller/ApiControllerTest.php b/tests/Controller/ApiControllerTest.php new file mode 100644 index 0000000..b6489ea --- /dev/null +++ b/tests/Controller/ApiControllerTest.php @@ -0,0 +1,440 @@ +app = new class() extends ApplicationAbstract + { + protected string $appName = 'Api'; + }; + + $this->app->dbPool = $GLOBALS['dbpool']; + $this->app->orgId = 1; + $this->app->accountManager = new AccountManager($GLOBALS['session']); + $this->app->appSettings = new CoreSettings(); + $this->app->moduleManager = new ModuleManager($this->app, __DIR__ . '/../../../../Modules/'); + $this->app->dispatcher = new Dispatcher($this->app); + $this->app->eventManager = new EventManager($this->app->dispatcher); + $this->app->eventManager->importFromFile(__DIR__ . '/../../../../Web/Api/Hooks.php'); + $this->app->sessionManager = new HttpSession(36000); + + $account = new Account(); + TestUtils::setMember($account, 'id', 1); + + $permission = new AccountPermission(); + $permission->setUnit(1); + $permission->setApp('api'); + $permission->setPermission( + PermissionType::READ + | PermissionType::CREATE + | PermissionType::MODIFY + | PermissionType::DELETE + | PermissionType::PERMISSION + ); + + $account->addPermission($permission); + + $this->app->accountManager->add($account); + $this->app->router = new WebRouter(); + + $this->module = $this->app->moduleManager->get('Helper'); + + TestUtils::setMember($this->module, 'app', $this->app); + } + + /** + * @covers Modules\Helper\Controller\ApiController + * @group module + */ + public function testStandaloneTemplateCreate() : void + { + $response = new HttpResponse(); + $request = new HttpRequest(new HttpUri('')); + + $request->header->account = 1; + $request->setData('name', \ucfirst('depreciation')); + $request->setData('standalone', true); + $request->setData('tags', '[{"title": "TestTitle", "color": "#f0f", "language": "en"}, {"id": 1}]'); + + $files = []; + + if (!\is_dir(__DIR__ . '/temp')) { + \mkdir(__DIR__ . '/temp'); + } + + $helperFiles = \scandir(__DIR__ . '/../depreciation'); + foreach ($helperFiles as $filePath) { + if (!\is_file(__DIR__ . '/../depreciation/' . $filePath) + || $filePath === '..' || $filePath === '.' + ) { + continue; + } + + \copy(__DIR__ . '/../depreciation/' . $filePath, __DIR__ . '/temp/' . $filePath); + + $files[] = [ + 'error' => \UPLOAD_ERR_OK, + 'type' => \substr($filePath, \strrpos($filePath, '.') + 1), + 'name' => $filePath, + 'tmp_name' => __DIR__ . '/temp/' . $filePath, + 'size' => \filesize(__DIR__ . '/temp/' . $filePath), + ]; + } + + TestUtils::setMember($request, 'files', $files); + + $this->module->apiTemplateCreate($request, $response); + self::assertGreaterThan(0, self::$depreciationHelper = $response->get('')['response']->getId()); + + \rmdir(__DIR__ . '/temp'); + } + + /** + * @covers Modules\Helper\Controller\ApiController + * @group module + */ + public function testTemplateCreate() : void + { + $response = new HttpResponse(); + $request = new HttpRequest(new HttpUri('')); + + $request->header->account = 1; + $request->setData('name', \ucfirst('depreciation')); + $request->setData('standalone', false); + $request->setData('tags', '[{"title": "TestTitle", "color": "#f0f", "language": "en"}, {"id": 1}]'); + + $files = []; + + if (!\is_dir(__DIR__ . '/temp')) { + \mkdir(__DIR__ . '/temp'); + } + + $helperFiles = \scandir(__DIR__ . '/../depreciation'); + foreach ($helperFiles as $filePath) { + if (!\is_file(__DIR__ . '/../depreciation/' . $filePath) + || $filePath === '..' || $filePath === '.' + ) { + continue; + } + + \copy(__DIR__ . '/../depreciation/' . $filePath, __DIR__ . '/temp/' . $filePath); + + $files[] = [ + 'error' => \UPLOAD_ERR_OK, + 'type' => \substr($filePath, \strrpos($filePath, '.') + 1), + 'name' => $filePath, + 'tmp_name' => __DIR__ . '/temp/' . $filePath, + 'size' => \filesize(__DIR__ . '/temp/' . $filePath), + ]; + } + + TestUtils::setMember($request, 'files', $files); + + $this->module->apiTemplateCreate($request, $response); + self::assertGreaterThan(0, self::$depreciationHelper2 = $response->get('')['response']->getId()); + + \rmdir(__DIR__ . '/temp'); + } + + /** + * @covers Modules\Helper\Controller\ApiController + * @group module + */ + public function testExportPdf() : void + { + $response = new HttpResponse(); + $request = new HttpRequest(new HttpUri('')); + + $request->header->account = 1; + $request->setData('id', self::$depreciationHelper); + $request->setData('type', 'pdf'); + + $this->module->apiHelperExport($request, $response); + self::assertTrue(\stripos($response->header->get('Content-disposition')[0], 'pdf') !== false); + } + + /** + * @covers Modules\Helper\Controller\ApiController + * @group module + */ + public function testExportXlsx() : void + { + $response = new HttpResponse(); + $request = new HttpRequest(new HttpUri('')); + + $request->header->account = 1; + $request->setData('id', self::$depreciationHelper); + $request->setData('type', 'xlsx'); + + $this->module->apiHelperExport($request, $response); + self::assertTrue(\stripos($response->header->get('Content-disposition')[0], 'xlsx') !== false); + } + + /** + * @covers Modules\Helper\Controller\ApiController + * @group module + */ + public function testExportDocx() : void + { + $response = new HttpResponse(); + $request = new HttpRequest(new HttpUri('')); + + $request->header->account = 1; + $request->setData('id', self::$depreciationHelper); + $request->setData('type', 'docx'); + + $this->module->apiHelperExport($request, $response); + self::assertTrue(\stripos($response->header->get('Content-disposition')[0], 'docx') !== false); + } + + /** + * @covers Modules\Helper\Controller\ApiController + * @group module + */ + public function testExportPptx() : void + { + $response = new HttpResponse(); + $request = new HttpRequest(new HttpUri('')); + + $request->header->account = 1; + $request->setData('id', self::$depreciationHelper); + $request->setData('type', 'pptx'); + + $this->module->apiHelperExport($request, $response); + self::assertTrue(\stripos($response->header->get('Content-disposition')[0], 'pptx') !== false); + } + + /** + * @covers Modules\Helper\Controller\ApiController + * @group module + */ + public function testExportCsv() : void + { + $response = new HttpResponse(); + $request = new HttpRequest(new HttpUri('')); + + $request->header->account = 1; + $request->setData('id', self::$depreciationHelper); + $request->setData('type', 'csv'); + + $this->module->apiHelperExport($request, $response); + self::assertTrue(\stripos($response->header->get('Content-disposition')[0], 'csv') !== false); + } + + /** + * @covers Modules\Helper\Controller\ApiController + * @group module + */ + public function testExportJson() : void + { + $response = new HttpResponse(); + $request = new HttpRequest(new HttpUri('')); + + $request->header->account = 1; + $request->setData('id', self::$depreciationHelper); + $request->setData('type', 'json'); + + $this->module->apiHelperExport($request, $response); + self::assertTrue(\stripos($response->header->get('Content-disposition')[0], 'json') !== false); + } + + /** + * @covers Modules\Helper\Controller\ApiController + * @group module + */ + public function testExportInvalidPermission() : void + { + $response = new HttpResponse(); + $request = new HttpRequest(new HttpUri('')); + + $request->header->account = 99999; + $request->setData('id', self::$depreciationHelper); + $request->setData('type', 'csv'); + + $this->module->apiHelperExport($request, $response); + self::assertEquals(RequestStatusCode::R_403, $response->header->status); + } + + /** + * @covers Modules\Helper\Controller\ApiController + * @group module + */ + public function testExportOtherType() : void + { + $response = new HttpResponse(); + $request = new HttpRequest(new HttpUri('')); + + $request->header->account = 1; + $request->setData('id', self::$depreciationHelper); + $request->setData('type', 'invalid'); + + $this->module->apiHelperExport($request, $response); + self::assertEquals(RequestStatusCode::R_200, $response->header->status); // is html "export"/render + } + + /** + * @covers Modules\Helper\Controller\ApiController + * @group module + */ + public function testExportInvalidData() : void + { + $response = new HttpResponse(); + $request = new HttpRequest(new HttpUri('')); + + $request->header->account = 1; + $request->setData('invalid', '1'); + + $this->module->apiHelperExport($request, $response); + self::assertEquals(RequestStatusCode::R_400, $response->header->status); + } + + /** + * @covers Modules\Helper\Controller\ApiController + * @group module + */ + public function testApiTemplateCreateInvalidData() : void + { + $response = new HttpResponse(); + $request = new HttpRequest(new HttpUri('')); + + $request->header->account = 1; + $request->setData('invalid', '1'); + + $this->module->apiTemplateCreate($request, $response); + self::assertEquals(RequestStatusCode::R_400, $response->header->status); + } + + /** + * @depends testTemplateCreate + * @covers Modules\Helper\Controller\ApiController + * @group module + */ + public function testReportCreate() : void + { + $response = new HttpResponse(); + $request = new HttpRequest(new HttpUri('')); + + $request->header->account = 1; + $request->setData('name', \ucfirst('depreciation-report')); + $request->setData('template', self::$depreciationHelper2); + + if (!\is_file(__DIR__ . '/reportData_tmp.csv')) { + \copy(__DIR__ . '/../depreciation/reportData.csv', __DIR__ . '/reportData_tmp.csv'); + } + + TestUtils::setMember($request, 'files', [ + [ + 'name' => 'reportData.csv', + 'type' => 'csv', + 'error' => \UPLOAD_ERR_OK, + 'tmp_name' => __DIR__ . '/reportData_tmp.csv', + 'size' => \filesize(__DIR__ . '/reportData_tmp.csv'), + ], + ]); + + $this->module->apiReportCreate($request, $response); + } + + /** + * @covers Modules\Helper\Controller\ApiController + * @group module + */ + public function testReportCreateInvalidPermission() : void + { + $response = new HttpResponse(); + $request = new HttpRequest(new HttpUri('')); + + $request->header->account = 9999; + $request->setData('name', \ucfirst('depreciation-report')); + $request->setData('template', self::$depreciationHelper2); + + if (!\is_file(__DIR__ . '/reportData_tmp.csv')) { + \copy(__DIR__ . '/../depreciation/reportData.csv', __DIR__ . '/reportData_tmp.csv'); + } + + TestUtils::setMember($request, 'files', [ + [ + 'name' => 'reportData.csv', + 'type' => 'csv', + 'error' => \UPLOAD_ERR_OK, + 'tmp_name' => __DIR__ . '/reportData_tmp.csv', + 'size' => \filesize(__DIR__ . '/reportData_tmp.csv'), + ], + ]); + + $this->module->apiReportCreate($request, $response); + self::assertEquals(RequestStatusCode::R_403, $response->header->status); + + if (\is_file(__DIR__ . '/reportData_tmp.csv')) { + \unlink(__DIR__ . '/reportData_tmp.csv'); + } + } + + /** + * @covers Modules\Helper\Controller\ApiController + * @group module + */ + public function testApiReportCreateInvalidData() : void + { + $response = new HttpResponse(); + $request = new HttpRequest(new HttpUri('')); + + $request->header->account = 1; + $request->setData('invalid', '1'); + + $this->module->apiReportCreate($request, $response); + self::assertEquals(RequestStatusCode::R_400, $response->header->status); + } +} diff --git a/tests/Models/ReportMapperTest.php b/tests/Models/ReportMapperTest.php index 0c3c8f1..1dd8dd4 100755 --- a/tests/Models/ReportMapperTest.php +++ b/tests/Models/ReportMapperTest.php @@ -39,7 +39,7 @@ final class ReportMapperTest extends \PHPUnit\Framework\TestCase $template->setStatus(HelperStatus::ACTIVE); $template->description = 'Description'; $template->setDatatype(TemplateDataType::OTHER); - $template->setStandalone(false); + $template->isStandalone = false; $template->setExpected(['source1.csv', 'source2.csv']); $collection = new Collection(); @@ -94,7 +94,7 @@ final class ReportMapperTest extends \PHPUnit\Framework\TestCase $collection->addSource($media); } - $template->setSource($collection); + $template->source = $collection; return $template; } @@ -112,7 +112,7 @@ final class ReportMapperTest extends \PHPUnit\Framework\TestCase $report->title = 'Title'; $report->setStatus(HelperStatus::ACTIVE); $report->description = 'Description'; - $report->setTemplate($this->createTemplate()); + $report->template = $this->createTemplate(); $collection = new Collection(); $collection->createdBy = new NullAccount(1); @@ -166,7 +166,7 @@ final class ReportMapperTest extends \PHPUnit\Framework\TestCase $collection->addSource($media); } - $report->setSource($collection); + $report->source = $collection; $id = ReportMapper::create($report); self::assertGreaterThan(0, $report->getId()); @@ -178,6 +178,6 @@ final class ReportMapperTest extends \PHPUnit\Framework\TestCase self::assertEquals($report->description, $reportR->description); self::assertEquals($report->title, $reportR->title); self::assertEquals($report->getStatus(), $reportR->getStatus()); - self::assertEquals($report->getTemplate()->name, $reportR->getTemplate()->name); + self::assertEquals($report->template->name, $reportR->template->name); } } diff --git a/tests/Models/ReportTest.php b/tests/Models/ReportTest.php index f3eb9cb..41435e0 100755 --- a/tests/Models/ReportTest.php +++ b/tests/Models/ReportTest.php @@ -51,8 +51,8 @@ final class ReportTest extends \PHPUnit\Framework\TestCase self::assertEquals(HelperStatus::INACTIVE, $this->report->getStatus()); self::assertEquals('', $this->report->description); self::assertEquals('', $this->report->descriptionRaw); - self::assertEquals(0, $this->report->getTemplate()->getId()); - self::assertEquals(0, $this->report->getSource()->getId()); + self::assertEquals(0, $this->report->template->getId()); + self::assertEquals(0, $this->report->source->getId()); } /** @@ -117,8 +117,8 @@ final class ReportTest extends \PHPUnit\Framework\TestCase */ public function testTemplateInputOutput() : void { - $this->report->setTemplate(new NullTemplate(11)); - self::assertEquals(11, $this->report->getTemplate()->getId()); + $this->report->template = new NullTemplate(11); + self::assertEquals(11, $this->report->template->getId()); } /** @@ -128,8 +128,8 @@ final class ReportTest extends \PHPUnit\Framework\TestCase */ public function testSourceInputOutput() : void { - $this->report->setSource(new NullCollection(4)); - self::assertEquals(4, $this->report->getSource()->getId()); + $this->report->source = new NullCollection(4); + self::assertEquals(4, $this->report->source->getId()); } /** @@ -139,7 +139,7 @@ final class ReportTest extends \PHPUnit\Framework\TestCase */ public function testToArray() : void { - $this->report->setTemplate(new NullTemplate(11)); + $this->report->template = new NullTemplate(11); $this->report->title = 'testTitle'; $this->report->description = 'testDescription'; $this->report->descriptionRaw = 'testDescriptionRaw'; @@ -169,7 +169,7 @@ final class ReportTest extends \PHPUnit\Framework\TestCase */ public function testJsonSerialize() : void { - $this->report->setTemplate(new NullTemplate(11)); + $this->report->template = new NullTemplate(11); $this->report->title = 'testTitle'; $this->report->description = 'testDescription'; $this->report->descriptionRaw = 'testDescriptionRaw'; diff --git a/tests/Models/TemplateMapperTest.php b/tests/Models/TemplateMapperTest.php index 6416d5a..b4f47b0 100755 --- a/tests/Models/TemplateMapperTest.php +++ b/tests/Models/TemplateMapperTest.php @@ -44,7 +44,7 @@ final class TemplateMapperTest extends \PHPUnit\Framework\TestCase $template->description = 'Description'; $template->descriptionRaw = 'DescriptionRaw'; $template->setDatatype(TemplateDataType::OTHER); - $template->setStandalone(false); + $template->isStandalone = false; $template->setExpected(['source1.csv', 'source2.csv']); $collection = new Collection(); @@ -99,7 +99,7 @@ final class TemplateMapperTest extends \PHPUnit\Framework\TestCase $collection->addSource($media); } - $template->setSource($collection); + $template->source = $collection; $id = TemplateMapper::create($template); self::assertGreaterThan(0, $template->getId()); @@ -112,7 +112,7 @@ final class TemplateMapperTest extends \PHPUnit\Framework\TestCase self::assertEquals($template->descriptionRaw, $templateR->descriptionRaw); self::assertEquals($template->name, $templateR->name); self::assertEquals($template->getStatus(), $templateR->getStatus()); - self::assertEquals($template->isStandalone(), $templateR->isStandalone()); + self::assertEquals($template->isStandalone, $templateR->isStandalone); self::assertEquals($template->getDatatype(), $templateR->getDatatype()); self::assertEquals($template->getExpected(), $templateR->getExpected()); } @@ -128,4 +128,15 @@ final class TemplateMapperTest extends \PHPUnit\Framework\TestCase self::assertCount(1, $newest); } + + /** + * @covers Modules\Helper\Models\TemplateMapper + * @group module + */ + public function testVirtualPath() : void + { + $virtualPath = TemplateMapper::getByVirtualPath('/'); + + self::assertGreaterThan(0, \count($virtualPath)); + } } diff --git a/tests/Models/TemplateTest.php b/tests/Models/TemplateTest.php index 0c36d83..6396e0f 100755 --- a/tests/Models/TemplateTest.php +++ b/tests/Models/TemplateTest.php @@ -21,6 +21,8 @@ use Modules\Helper\Models\Template; use Modules\Helper\Models\TemplateDataType; use Modules\Media\Models\NullCollection; use Modules\Organization\Models\NullUnit; +use Modules\Tag\Models\Tag; +use phpOMS\Utils\TestUtils; /** * @testdox Modules\tests\Helper\Models\TemplateTest: Template model @@ -47,7 +49,7 @@ final class TemplateTest extends \PHPUnit\Framework\TestCase public function testDefault() : void { self::assertEquals(0, $this->template->getId()); - self::assertEquals(0, $this->template->getUnit()->getId()); + self::assertEquals(0, $this->template->unit->getId()); self::assertEquals(0, $this->template->createdBy->getId()); self::assertEquals((new \DateTime('now'))->format('Y-m-d'), $this->template->createdAt->format('Y-m-d')); self::assertEquals('', $this->template->name); @@ -55,8 +57,8 @@ final class TemplateTest extends \PHPUnit\Framework\TestCase self::assertEquals('', $this->template->description); self::assertEquals('', $this->template->descriptionRaw); self::assertEquals([], $this->template->getExpected()); - self::assertEquals(0, $this->template->getSource()->getId()); - self::assertFalse($this->template->isStandalone()); + self::assertEquals(0, $this->template->source->getId()); + self::assertFalse($this->template->isStandalone); self::assertEquals(TemplateDataType::OTHER, $this->template->getDatatype()); self::assertInstanceOf(NullReport::class, $this->template->getNewestReport()); } @@ -68,8 +70,8 @@ final class TemplateTest extends \PHPUnit\Framework\TestCase */ public function testUnitInputOutput() : void { - $this->template->setUnit(new NullUnit(1)); - self::assertEquals(1, $this->template->getUnit()->getId()); + $this->template->unit = new NullUnit(1); + self::assertEquals(1, $this->template->unit->getId()); } /** @@ -112,8 +114,8 @@ final class TemplateTest extends \PHPUnit\Framework\TestCase */ public function testStandalonInputOutput() : void { - $this->template->setStandalone(true); - self::assertTrue($this->template->isStandalone()); + $this->template->isStandalone = true; + self::assertTrue($this->template->isStandalone); } /** @@ -157,8 +159,8 @@ final class TemplateTest extends \PHPUnit\Framework\TestCase */ public function testSourceInputOutput() : void { - $this->template->setSource(new NullCollection(4)); - self::assertEquals(4, $this->template->getSource()->getId()); + $this->template->source = new NullCollection(4); + self::assertEquals(4, $this->template->source->getId()); } /** @@ -172,6 +174,33 @@ final class TemplateTest extends \PHPUnit\Framework\TestCase self::assertEquals(TemplateDataType::GLOBAL_DB, $this->template->getDatatype()); } + /** + * @covers Modules\Helper\Models\Template + * @group module + */ + public function testTagInputOutput() : void + { + $tag = new Tag(); + $tag->setL11n('Tag'); + + $this->template->addTag($tag); + self::assertCount(1, $this->template->getTags()); + } + + /** + * @covers Modules\Helper\Models\Template + * @group module + */ + public function testNewestReportOutput() : void + { + TestUtils::setMember($this->template, 'reports', [ + $a = new NullReport(1), + $b = new NullReport(2), + ]); + + self::assertEquals($b, $this->template->getNewestReport()); + } + /** * @testdox Template data can be turned into an array * @covers Modules\Helper\Models\Template @@ -179,10 +208,10 @@ final class TemplateTest extends \PHPUnit\Framework\TestCase */ public function testToArray() : void { - $this->template->name = 'testName'; - $this->template->description = 'testDescription'; - $this->template->descriptionRaw = 'testDescriptionRaw'; - $this->template->setStandalone(true); + $this->template->name = 'testName'; + $this->template->description = 'testDescription'; + $this->template->descriptionRaw = 'testDescriptionRaw'; + $this->template->isStandalone = true; $array = $this->template->toArray(); $expected = [ @@ -211,10 +240,10 @@ final class TemplateTest extends \PHPUnit\Framework\TestCase */ public function testJsonSerialize() : void { - $this->template->name = 'testName'; - $this->template->description = 'testDescription'; - $this->template->descriptionRaw = 'testDescriptionRaw'; - $this->template->setStandalone(true); + $this->template->name = 'testName'; + $this->template->description = 'testDescription'; + $this->template->descriptionRaw = 'testDescriptionRaw'; + $this->template->isStandalone = true; $array = $this->template->jsonSerialize(); $expected = [ diff --git a/tests/depreciation/depreciation.cfg.json b/tests/depreciation/depreciation.cfg.json new file mode 100644 index 0000000..3505b5d --- /dev/null +++ b/tests/depreciation/depreciation.cfg.json @@ -0,0 +1,44 @@ +[ + { + "type": "label", + "attributes": { + "for": "amount" + }, + "default": { + "value": "Amount" + } + }, + { + "type": "input", + "subtype": "text", + "attributes": { + "id": "amount", + "name": "amount", + "type": "text" + }, + "default": { + "value": "10000" + } + }, + { + "type": "label", + "attributes": { + "for": "duration" + }, + "default": { + "value": "Duration" + } + }, + { + "type": "input", + "subtype": "text", + "attributes": { + "id": "duration", + "name": "duration", + "type": "text" + }, + "default": { + "value": "10" + } + } +] \ No newline at end of file diff --git a/tests/depreciation/depreciation.lang.php b/tests/depreciation/depreciation.lang.php new file mode 100644 index 0000000..f742733 --- /dev/null +++ b/tests/depreciation/depreciation.lang.php @@ -0,0 +1,27 @@ + [ + ':language' => 'English', + 'Depreciation' => 'Depreciation', + 'Period' => 'Period', + 'StraightLine' => 'Straight Line', + 'ArithmeticDegressive' => 'Arithmetic Degressive', + 'ArithmeticProgressive' => 'Arithmetic Progressive', + 'GeometricDegressive' => 'Geometric Degressive', + 'GeometricProgressive' => 'Geometric Progressive', + 'info' => 'The depreciation calculator shows the residual value at the end of the respective period (after depreciation). The geometric depreciation is calculated with a residual value of 10%.', + ], + 'de' => [ + ':language' => 'Deutsch', + 'Depreciation' => 'Abschreibung', + 'Period' => 'Periode', + 'StraightLine' => 'Linear', + 'ArithmeticDegressive' => 'Arithmetisch Degressiv', + 'ArithmeticProgressive' => 'Arithmetisch Progressiv', + 'GeometricDegressive' => 'Geometrisch Degressive', + 'GeometricProgressive' => 'Geometrisch Progressiv', + 'info' => 'Der Abschreibungsrechner zeigt den Restwert in der jeweiligen Periode (nach Abschreibung). Die geometrische Abschreibung ist mit einem Restwert von 10% berechnet.', + ], +]; diff --git a/tests/depreciation/logo.png b/tests/depreciation/logo.png new file mode 100644 index 0000000..27d7f3c Binary files /dev/null and b/tests/depreciation/logo.png differ diff --git a/tests/depreciation/reportData.csv b/tests/depreciation/reportData.csv new file mode 100644 index 0000000..94ddf2f --- /dev/null +++ b/tests/depreciation/reportData.csv @@ -0,0 +1 @@ +Test data \ No newline at end of file diff --git a/tests/depreciation/styles.css b/tests/depreciation/styles.css new file mode 100644 index 0000000..3497c08 --- /dev/null +++ b/tests/depreciation/styles.css @@ -0,0 +1,163 @@ +:root { + --color-main: rgba(54, 151, 219, 1); + --color-main-font: #fff; + --color-transparent: rgba(54, 151, 219, .25); + --color-subtotal: rgba(54, 151, 219, .5); + --color-border: #d6d6d6; + --font-family: 'Roboto', sans-serif; +} + +body { + width: 100%; + height: 100%; + min-width: 100%; + max-width: 100%; + overflow-x: hidden; + font-family: var(--font-family); + color: #000; + font-size: .8rem; +} + +.clear { + clear: both; +} + +pre { + background: #fff; + -webkit-border-radius: 3px; + -moz-border-radius: 3px; + -ms-border-radius: 3px; + border-radius: 3px; + background-clip: padding-box; + border: 1px solid var(--color-border); + padding: 5px; + overflow-x: scroll; + counter-reset: line; + width: 100%; + -moz-box-sizing: border-box; + -webkit-box-sizing: border-box; + box-sizing: border-box; + white-space:pre-wrap; +} + +pre span { + display: block; +} + +pre span:before { + counter-increment: line; + content: counter(line); + display: inline-block; + border-right: 1px solid var(--color-border); + padding: 0 .5em; + margin-right: .5em; + color: #888; + width: 30px; +} + +iframe { + padding: 0; + margin: 0; + border: none; + width: 100%; + height: 100%; +} + +h1, h2 { + font-weight: normal; + padding: 0; + margin: 0 auto; + text-align: center; +} + +h1 { + font-size: 1.5em; +} + +h2 { + font-size: 1.3em; +} + +h1+table, h2+table { + margin-top: 1em; +} + +table { + border-collapse: collapse; + width: 100%; + background: #fff; +} + +table caption { + background: var(--color-main); + color: var(--color-main-font); + padding: 10px; +} + +tbody tr:not(.subtotal):nth-child(n+1) td { + border-top: 1px solid #ddd; +} + +tbody tr:not(.subtotal):last-child td { + border-bottom: 1px solid #ddd; +} + +tbody tr.subtotal+tr td, tbody tr.total td { + border-top: none !important; + border-bottom: none !important; +} + +tbody tr.total { + background: var(--color-main); + color: var(--color-main-font); +} + +tr.subtotal { + background: var(--color-subtotal); +} + +td { + padding: .6em; +} + +tfoot { + font-size: 0.7em; +} + +blockquote { + background: #fff; + border: 1px solid #d5d5d5; + padding: 10px; +} + +blockquote i { + color: #d5d5d5; + margin-right: 5px; +} + +#header { + display: none; +} + +@media print { + :root { + --color-main: rgba(255, 210, 4, 1); + --color-main-font: #000; + --color-transparent: rgba(255, 210, 4, .25); + --color-subtotal: rgba(255, 210, 4, .5); + } + + body { + font-size: 0.6rem; + } + + #header { + display: block; + text-align: center; + margin-bottom: 1em; + } + + #header img { + height: 50px; + } +} diff --git a/tests/depreciation/test.js b/tests/depreciation/test.js new file mode 100644 index 0000000..e69de29 diff --git a/tests/depreciation/test.json b/tests/depreciation/test.json new file mode 100644 index 0000000..e69de29 diff --git a/tests/depreciation/test.sqlite b/tests/depreciation/test.sqlite new file mode 100644 index 0000000..e69de29 diff --git a/tests/depreciation/view.csv.php b/tests/depreciation/view.csv.php new file mode 100644 index 0000000..feef538 --- /dev/null +++ b/tests/depreciation/view.csv.php @@ -0,0 +1,48 @@ +getData('tcoll'); +$rcoll = $this->getData('rcoll'); +$cLang = $this->getData('lang'); +$template = $this->getData('template'); +$report = $this->getData('report'); +$basepath = \rtrim($this->getData('basepath') ?? '', '/'); + +/** @noinspection PhpIncludeInspection */ +$reportLanguage = include $basepath . '/' . \ltrim($tcoll['lang']->getPath(), '/'); +$lang = $reportLanguage[$cLang]; + +$amount = (float) ($this->request->getData('amount') ?? 10000.0); +$duration = (int) ($this->request->getData('duration') ?? 10); + +$depreciation = [ + [ + $lang['Period'], + $lang['StraightLine'], + $lang['ArithmeticDegressive'], + $lang['ArithmeticProgressive'], + $lang['GeometricDegressive'], + $lang['GeometricProgressive'], + ], +]; + +for ($i = 1; $i <= $duration; ++$i) { + $depreciation[] = [ + $i, + $this->getCurrency(Depreciation::getStraightLineResidualInT($amount, $duration, $i), 'medium', ''), + $this->getCurrency(Depreciation::getArithmeticDegressiveDepreciationResidualInT($amount, 0.0, $duration, $i), 'medium', ''), + $this->getCurrency(Depreciation::getArithmeticProgressiveDepreciationResidualInT($amount, 0.0, $duration, $i), 'medium', ''), + $this->getCurrency(Depreciation::getGeometicProgressiveDepreciationResidualInT($amount, 0.0, $duration, $i), 'medium', ''), + $this->getCurrency(Depreciation::getGeometicDegressiveDepreciationResidualInT($amount, $amount * 0.1, $duration, $i), 'medium', ''), + ]; +} + +$out = \fopen('php://output', 'w'); +foreach ($depreciation as $d) { + \fputcsv($out, $d); +} +\fclose($out); diff --git a/tests/depreciation/view.doc.php b/tests/depreciation/view.doc.php new file mode 100644 index 0000000..d5d9e8f --- /dev/null +++ b/tests/depreciation/view.doc.php @@ -0,0 +1,190 @@ +getData('tcoll'); +$rcoll = $this->getData('rcoll'); +$cLang = $this->getData('lang'); +$template = $this->getData('template'); +$report = $this->getData('report'); +$basepath = \rtrim($this->getData('basepath') ?? '', '/'); + +/** @noinspection PhpIncludeInspection */ +$reportLanguage = include $basepath . '/' . \ltrim($tcoll['lang']->getPath(), '/'); +$lang = $reportLanguage[$cLang]; + +$date = new \phpOMS\Stdlib\Base\SmartDateTime($this->request->getData('date') ?? 'Y-m-d'); + +$languageEnGb = new Language(Language::EN_GB); + +$phpWord = new PhpWord(); +$phpWord->getSettings()->setThemeFontLang($languageEnGb); + +$section = $phpWord->addSection([ + 'marginTop' => 0, + 'marginRight' => 0, + 'marginBottom' => 0, + 'marginLeft' => 0, +]); + +$section->addImage( + __DIR__ . '/logo.png', + [ + 'width' => (int) Converter::cmToPixel(5), + 'height' => (int) Converter::cmToPixel(5), + 'wrappingStyle' => 'square', + 'positioning' => Image::POSITION_ABSOLUTE, + 'posHorizontal' => Image::POSITION_HORIZONTAL_CENTER, + 'posHorizontalRel' => Image::POSITION_RELATIVE_TO_PAGE, + 'posVerticalRel' => Image::POSITION_RELATIVE_TO_PAGE, + 'posVertical' => Image::POSITION_VERTICAL_CENTER, + ] +); + +$fontStyleName = 'splashStyleF'; +$phpWord->addFontStyle($fontStyleName, [ + 'size' => 32, 'color' => '3697db', +]); + +$paragraphStyleName = 'splashStyleP'; +$phpWord->addParagraphStyle($paragraphStyleName, [ + 'alignment' => Jc::CENTER, + 'spaceBefore' => 6000, +]); + +$section->addTextBox( + [ + 'width' => (int) Converter::cmToPoint(20), + 'height' => (int) Converter::cmToPixel(5) + 200, + 'borderSize' => -1, + 'size' => 32, 'color' => '3697db', + 'positioning' => Image::POSITION_ABSOLUTE, + 'posHorizontal' => Image::POSITION_HORIZONTAL_CENTER, + 'posHorizontalRel' => Image::POSITION_RELATIVE_TO_PAGE, + 'posVerticalRel' => Image::POSITION_RELATIVE_TO_PAGE, + 'posVertical' => Image::POSITION_VERTICAL_CENTER, + ] +)->addText('Demo Report', $fontStyleName, $paragraphStyleName); + +$paragraphStyleName = 'pStyle'; +$phpWord->addParagraphStyle($paragraphStyleName, [ + 'alignment' => Jc::CENTER, 'spaceAfter' => 100, +]); + +$phpWord->addTitleStyle(1, ['bold' => true], ['spaceAfter' => 240]); + +$section = $phpWord->addSection([ + 'marginTop' => 1000, + 'marginRight' => 1000, + 'marginBottom' => 1000, + 'marginLeft' => 1000, +]); + +$titleFontStyleName = 'titleStyleF'; +$phpWord->addFontStyle($titleFontStyleName, [ + 'size' => 24, 'color' => '000000', +]); + +$titleParagraphStyleName = 'titleStyleP'; +$phpWord->addParagraphStyle($titleParagraphStyleName, [ + 'spaceAfter' => 100, +]); + +$section->addText('Demo Report - ' . $date->format('Y-m-d'), $titleFontStyleName, $titleParagraphStyleName); +$section->addShape('line', [ + 'points' => '0,0 ' . ((int) Converter::cmToPoint(19)) . ',0', + 'outline' => [ + 'color' => '#3697db', + 'line' => 'thickThin', + 'weight' => 1, + 'startArrow' => '', + 'endArrow' => '', + ], +]); + +$section->addTextBreak(1); + +$listFontStyleName = 'listStyleF'; +$phpWord->addFontStyle($listFontStyleName, [ + 'size' => 16, 'color' => '000000', +]); + +$listParagraphStyleName = 'listStyleP'; +$phpWord->addParagraphStyle($listParagraphStyleName, [ + 'spaceAfter' => 300, +]); + +$section->addListItem('Create custom localized reports', 0, $listFontStyleName, null, $listParagraphStyleName); +$section->addListItem('They are 100% customizable in terms of style, layout and content', 0, $listFontStyleName, null, $listParagraphStyleName); +$section->addListItem('You can export them as:', 0, $listFontStyleName, null, $listParagraphStyleName); +$section->addListItem('Excel', 1, $listFontStyleName, null, $listParagraphStyleName); +$section->addListItem('PDF', 1, $listFontStyleName, null, $listParagraphStyleName); +$section->addListItem('Print', 1, $listFontStyleName, null, $listParagraphStyleName); +$section->addListItem('PowerPoint', 1, $listFontStyleName, null, $listParagraphStyleName); +$section->addListItem('CSV', 1, $listFontStyleName, null, $listParagraphStyleName); +$section->addListItem('Word', 1, $listFontStyleName, null, $listParagraphStyleName); + +$section = $phpWord->addSection([ + 'marginTop' => 1000, + 'marginRight' => 1000, + 'marginBottom' => 1000, + 'marginLeft' => 1000, +]); + +$section->addText('Ideas for helpers', $titleFontStyleName, $titleParagraphStyleName); +$section->addShape('line', [ + 'points' => '0,0 ' . ((int) Converter::cmToPoint(19)) . ',0', + 'outline' => [ + 'color' => '#3697db', + 'line' => 'thickThin', + 'weight' => 1, + 'startArrow' => '', + 'endArrow' => '', + ], +]); + +$section->addTextBreak(1); + +$section->addListItem('Reports (e.g. sales, finance, marketing)', 0, $listFontStyleName, null, $listParagraphStyleName); +$section->addListItem('Mailing generator based on pre-defined layouts', 0, $listFontStyleName, null, $listParagraphStyleName); +$section->addListItem('Document generator based on pre-defined layouts', 0, $listFontStyleName, null, $listParagraphStyleName); +$section->addListItem('Calculators (e.g. margin and price calculators)', 0, $listFontStyleName, null, $listParagraphStyleName); + +$section = $phpWord->addSection([ + 'marginTop' => 1000, + 'marginRight' => 1000, + 'marginBottom' => 1000, + 'marginLeft' => 1000, +]); + +$section->addText('Data Source', $titleFontStyleName, $titleParagraphStyleName); +$section->addShape('line', [ + 'points' => '0,0 ' . ((int) Converter::cmToPoint(19)) . ',0', + 'outline' => [ + 'color' => '#3697db', + 'line' => 'thickThin', + 'weight' => 1, + 'startArrow' => '', + 'endArrow' => '', + ], +]); + +$section->addTextBreak(1); + +$section->addListItem('You can provide data for the helpers in many different ways', 0, $listFontStyleName, null, $listParagraphStyleName); +$section->addListItem('Manual user input', 1, $listFontStyleName, null, $listParagraphStyleName); +$section->addListItem('File upload (e.g. excel, csv)', 1, $listFontStyleName, null, $listParagraphStyleName); +$section->addListItem('Database upload (e.g. sqlite)', 1, $listFontStyleName, null, $listParagraphStyleName); +$section->addListItem('Database connection to local or remote database', 1, $listFontStyleName, null, $listParagraphStyleName); +$section->addListItem('External APIs', 1, $listFontStyleName, null, $listParagraphStyleName); +$section->addListItem('Internal APIs (everything from the Orange Management backend)', 1, $listFontStyleName, null, $listParagraphStyleName); + +$writer = IOFactory::createWriter($phpWord, 'Word2007'); +$writer->save('php://output'); diff --git a/tests/depreciation/view.json.php b/tests/depreciation/view.json.php new file mode 100644 index 0000000..8dbae95 --- /dev/null +++ b/tests/depreciation/view.json.php @@ -0,0 +1,3 @@ +getData('lang'); +/** @noinspection PhpIncludeInspection */ +$reportLanguage = include $basepath . '/' . \ltrim($tcoll['lang']->getPath(), '/'); +$lang = $reportLanguage[$cLang]; + +$amount = (float) ($this->request->getData('amount') ?? 10000.0); +$duration = (int) ($this->request->getData('duration') ?? 10); + +$pdf = new TCPDF(PDF_PAGE_ORIENTATION, PDF_UNIT, PDF_PAGE_FORMAT, true, 'UTF-8', false); + +$pdf->SetCreator('Dennis Eichhorn'); +$pdf->SetAuthor('Dennis Eichhorn'); +$pdf->SetTitle('Demo Mailing'); +$pdf->SetSubject('Mailing'); +$pdf->SetKeywords('demo helper mailing'); + +$pdf->SetDefaultMonospacedFont(PDF_FONT_MONOSPACED); + +$pdf->SetMargins(PDF_MARGIN_LEFT, 15, PDF_MARGIN_RIGHT); +$pdf->SetAutoPageBreak(false, 0); +$pdf->setImageScale(PDF_IMAGE_SCALE_RATIO); + +$pdf->setPrintHeader(false); +$pdf->setPrintFooter(false); + +$pdf->AddPage(); + +$pdf->SetFillColor(52, 58, 64); +$pdf->Rect(0, 0, $pdf->getPageWidth(), $pdf->getPageHeight(), 'F'); + +$pdf->SetFillColor(54, 151, 219); +$pdf->Rect(0, 0, $pdf->getPageWidth(), 5, 'F'); + +$pdf->SetFont('helvetica', '', 32); +$pdf->SetTextColor(54, 151, 219); +$pdf->Write(0, 'Demo Mailing - ' . $this->request->getData('date') ?? 'Y-m-d', '', 0, 'C', true, 0, false, false, 0); + +$pdf->Image(__DIR__ . '/logo.png', $pdf->getPageWidth() / 2 - 60 / 2, 40, 60, 60, 'PNG', '', 'C', true, 300, '', false, false, 0, false, false, false); + +$pdf->SetFillColor(67, 74, 81); +$pdf->Rect(0, 110, $pdf->getPageWidth(), 145, 'F'); + +$html = ' + + + + + + + + '; + +for ($i = 1; $i <= $duration; ++$i) { + $html .= ''; + $thml .= ''; + $thml .= ''; + $thml .= ''; + $thml .= ''; + $thml .= ''; + $thml .= ''; + $thml .= ''; +} + +$html = '
' . $lang['Period'] . '' . $lang['StraightLine'] . '' . $lang['ArithmeticDegressive'] . '' . $lang['ArithmeticProgressive'] . '' . $lang['GeometricDegressive'] . '' . $lang['GeometricProgressive'] . '
' . $i . '' . $this->getCurrency(Depreciation::getStraightLineResidualInT($amount, $duration, $i), 'medium', '') . '' . $this->getCurrency(Depreciation::getArithmeticDegressiveDepreciationResidualInT($amount, 0.0, $duration, $i), 'medium', '') . '' . $this->getCurrency(Depreciation::getArithmeticProgressiveDepreciationResidualInT($amount, 0.0, $duration, $i), 'medium', '') . '' . $this->getCurrency(Depreciation::getGeometicProgressiveDepreciationResidualInT($amount, $amount * 0.1, $duration, $i), 'medium', '') . '' . $this->getCurrency(Depreciation::getGeometicDegressiveDepreciationResidualInT($amount, $amount * 0.1, $duration, $i), 'medium', '') . '
'; + +$pdf->SetXY(15, 125); +$pdf->SetFont('helvetica', '', 14); +$pdf->SetTextColor(255, 255, 255); +$pdf->writeHTML($html, true, false, true, false, ''); + +$pdf->SetFont('helvetica', '', 12); +$pdf->SetXY(15, 262); +$pdf->SetTextColor(54, 151, 219); + +$text = <<Write(0, $text, '', 0, 'L', true, 0, false, false, 0); + +$pdf->Output('mailing.pdf', 'I'); diff --git a/tests/depreciation/view.ppt.php b/tests/depreciation/view.ppt.php new file mode 100644 index 0000000..e96c477 --- /dev/null +++ b/tests/depreciation/view.ppt.php @@ -0,0 +1,333 @@ +getData('tcoll'); +$rcoll = $this->getData('rcoll'); +$cLang = $this->getData('lang'); +$template = $this->getData('template'); +$report = $this->getData('report'); +$basepath = \rtrim($this->getData('basepath') ?? '', '/'); + +/** @noinspection PhpIncludeInspection */ +$reportLanguage = include $basepath . '/' . \ltrim($tcoll['lang']->getPath(), '/'); +$lang = $reportLanguage[$cLang]; + +$date = new \phpOMS\Stdlib\Base\SmartDateTime($this->request->getData('date') ?? 'Y-m-d'); + +$objPHPPresentation = new PhpPresentation(); + +$objPHPPresentation->getDocumentProperties()->setCreator('Orange Management') + ->setLastModifiedBy('Orange Management') + ->setTitle('Orange Management - Demo Report') + ->setSubject('Orange Management - Demo Report') + ->setDescription('Demo') + ->setKeywords('demo helper report') + ->setCategory('demo'); + +$colorBlack = new StyleColor('FF000000'); +$colorBlue = new StyleColor('FF3697db'); +$colorDark = new StyleColor('FF434a51'); + +// start screen +$oSlide1 = $objPHPPresentation->getActiveSlide(); +$oBkgColor = new Color(); +$oBkgColor->setColor($colorDark); +$oSlide1->setBackground($oBkgColor); + +$shape = new File(); +$shape->setName('Company Logo') + ->setDescription('Company Logo') + ->setPath(__DIR__ . '/logo.png') + ->setHeight(300) + ->setOffsetX(320) + ->setOffsetY(120); +$oSlide1->addShape($shape); + +$shape = $oSlide1->createRichTextShape() + ->setHeight(300) + ->setWidth(600) + ->setOffsetX(180) + ->setOffsetY(450); +$shape->getActiveParagraph()->getAlignment()->setHorizontal(Alignment::HORIZONTAL_CENTER); +$textRun = $shape->createTextRun('Demo Report'); +$textRun->getFont()->setBold(true)->setSize(35)->setColor($colorBlue); + +// first slide +$oSlide2 = $objPHPPresentation->createSlide(); + +$shape = $oSlide2->createRichTextShape() + ->setHeight(25) + ->setWidth(960) + ->setOffsetX(0) + ->setOffsetY(0); + +$shape->getFill() + ->setFillType(Fill::FILL_SOLID) + ->setStartColor($colorBlue) + ->setEndColor($colorBlue); + +$shape = $oSlide2->createRichTextShape() + ->setHeight(75) + ->setWidth(860) + ->setOffsetX(50) + ->setOffsetY(65); + +$shape->getActiveParagraph()->getAlignment()->setHorizontal(Alignment::HORIZONTAL_LEFT); +$textRun = $shape->createTextRun('Demo Report - ' . $date->format('Y-m-d')); +$textRun->getFont()->setBold(false)->setSize(35)->setColor($colorBlack); + +$line = new Line(50, 130, 910, 130); +$line->getBorder()->setColor($colorBlue); +$oSlide2->addShape($line); + +$shape = $oSlide2->createRichTextShape(); +$shape->setHeight(600) + ->setWidth(930) + ->setOffsetX(10) + ->setOffsetY(170); + +$shape->getActiveParagraph() + ->getAlignment() + ->setHorizontal(Alignment::HORIZONTAL_LEFT) + ->setMarginLeft(50) + ->setIndent(-25); + +$shape->getActiveParagraph()->getFont()->setSize(21)->setColor($colorBlack); +$shape->getActiveParagraph()->getBulletStyle()->setBulletType(Bullet::TYPE_BULLET)->setBulletChar('•'); + +$shape->createTextRun('Create custom localized reports'); +$shape->createParagraph() + ->getAlignment() + ->setLevel(1) + ->setMarginLeft(150) + ->setIndent(-25); + +$shape->createParagraph()->getAlignment()->setLevel(0)->setMarginLeft(50)->setIndent(-25); +$shape->createParagraph()->getAlignment()->setLevel(0)->setMarginLeft(50)->setIndent(-25); + +$shape->createTextRun('They are 100% customizable in terms of style, layout and content'); +$shape->createParagraph() + ->getAlignment() + ->setLevel(1) + ->setMarginLeft(150) + ->setIndent(-25); + +$shape->createParagraph()->getAlignment()->setLevel(0)->setMarginLeft(50)->setIndent(-25); +$shape->createParagraph()->getAlignment()->setLevel(0)->setMarginLeft(50)->setIndent(-25); + +$shape->createTextRun('You can export them as:'); +$shape->createParagraph() + ->getAlignment() + ->setLevel(1) + ->setMarginLeft(150) + ->setIndent(-25); + +$shape->getActiveParagraph()->getBulletStyle()->setBulletType(Bullet::TYPE_BULLET)->setBulletChar('◦'); +$shape->createTextRun('Excel'); +$shape->createParagraph()->createTextRun('PDF'); +$shape->createParagraph()->createTextRun('Print'); +$shape->createParagraph()->createTextRun('PowerPoint'); +$shape->createParagraph()->createTextRun('CSV'); +$shape->createParagraph()->createTextRun('Word'); + +$shape = new File(); +$shape->setName('Company Logo') + ->setDescription('Company Logo') + ->setPath(__DIR__ . '/logo.png') + ->setHeight(50) + ->setOffsetX(880) + ->setOffsetY(650); +$oSlide2->addShape($shape); + +// second slide +$oSlide3 = $objPHPPresentation->createSlide(); + +$shape = $oSlide3->createRichTextShape() + ->setHeight(25) + ->setWidth(960) + ->setOffsetX(0) + ->setOffsetY(0); + +$shape->getFill() + ->setFillType(Fill::FILL_SOLID) + ->setStartColor($colorBlue) + ->setEndColor($colorBlue); + +$shape = $oSlide3->createRichTextShape() + ->setHeight(75) + ->setWidth(860) + ->setOffsetX(50) + ->setOffsetY(65); + +$shape->getActiveParagraph()->getAlignment()->setHorizontal(Alignment::HORIZONTAL_LEFT); +$textRun = $shape->createTextRun('Ideas for helpers'); +$textRun->getFont()->setBold(false)->setSize(35)->setColor($colorBlack); + +$line = new Line(50, 130, 910, 130); +$line->getBorder()->setColor($colorBlue); +$oSlide3->addShape($line); + +$shape = $oSlide3->createRichTextShape(); +$shape->setHeight(600) + ->setWidth(930) + ->setOffsetX(10) + ->setOffsetY(170); + +$shape->getActiveParagraph() + ->getAlignment() + ->setHorizontal(Alignment::HORIZONTAL_LEFT) + ->setMarginLeft(50) + ->setIndent(-25); + +$shape->getActiveParagraph()->getFont()->setSize(21)->setColor($colorBlack); +$shape->getActiveParagraph()->getBulletStyle()->setBulletType(Bullet::TYPE_BULLET)->setBulletChar('•'); + +$shape->createTextRun('Reports (e.g. sales, finance marketing)'); +$shape->createParagraph() + ->getAlignment() + ->setLevel(1) + ->setMarginLeft(150) + ->setIndent(-25); + +$shape->createParagraph()->getAlignment()->setLevel(0)->setMarginLeft(50)->setIndent(-25); +$shape->createParagraph()->getAlignment()->setLevel(0)->setMarginLeft(50)->setIndent(-25); + +$shape->createTextRun('Mailing generator based on pre-defined layouts'); +$shape->createParagraph() + ->getAlignment() + ->setLevel(1) + ->setMarginLeft(150) + ->setIndent(-25); + +$shape->createParagraph()->getAlignment()->setLevel(0)->setMarginLeft(50)->setIndent(-25); +$shape->createParagraph()->getAlignment()->setLevel(0)->setMarginLeft(50)->setIndent(-25); + +$shape->createTextRun('Document generator based on pre-defined layouts'); +$shape->createParagraph() + ->getAlignment() + ->setLevel(1) + ->setMarginLeft(150) + ->setIndent(-25); + +$shape->createParagraph()->getAlignment()->setLevel(0)->setMarginLeft(50)->setIndent(-25); +$shape->createParagraph()->getAlignment()->setLevel(0)->setMarginLeft(50)->setIndent(-25); + +$shape->createTextRun('Calculators (e.g. margin calculator)'); +$shape->createParagraph() + ->getAlignment() + ->setLevel(1) + ->setMarginLeft(150) + ->setIndent(-25); + +$shape = new File(); +$shape->setName('Company Logo') + ->setDescription('Company Logo') + ->setPath(__DIR__ . '/logo.png') + ->setHeight(50) + ->setOffsetX(880) + ->setOffsetY(650); +$oSlide3->addShape($shape); + +// third slide +$oSlide4 = $objPHPPresentation->createSlide(); + +$shape = $oSlide4->createRichTextShape() + ->setHeight(25) + ->setWidth(960) + ->setOffsetX(0) + ->setOffsetY(0); + +$shape->getFill() + ->setFillType(Fill::FILL_SOLID) + ->setStartColor($colorBlue) + ->setEndColor($colorBlue); + +$shape = $oSlide4->createRichTextShape() + ->setHeight(75) + ->setWidth(860) + ->setOffsetX(50) + ->setOffsetY(65); + +$shape->getActiveParagraph()->getAlignment()->setHorizontal(Alignment::HORIZONTAL_LEFT); +$textRun = $shape->createTextRun('Data Source'); +$textRun->getFont()->setBold(false)->setSize(35)->setColor($colorBlack); + +$line = new Line(50, 130, 910, 130); +$line->getBorder()->setColor($colorBlue); +$oSlide4->addShape($line); + +$shape = $oSlide4->createRichTextShape(); +$shape->setHeight(600) + ->setWidth(930) + ->setOffsetX(10) + ->setOffsetY(170); + +$shape->getActiveParagraph() + ->getAlignment() + ->setHorizontal(Alignment::HORIZONTAL_LEFT) + ->setMarginLeft(50) + ->setIndent(-25); + +$shape->getActiveParagraph()->getFont()->setSize(21)->setColor($colorBlack); +$shape->getActiveParagraph()->getBulletStyle()->setBulletType(Bullet::TYPE_BULLET)->setBulletChar('•'); + +$shape->createTextRun('You can provide data for the helpers in many different ways'); +$shape->createParagraph() + ->getAlignment() + ->setLevel(1) + ->setMarginLeft(150) + ->setIndent(-25); + +$shape->getActiveParagraph()->getBulletStyle()->setBulletType(Bullet::TYPE_BULLET)->setBulletChar('◦'); +$shape->createTextRun('Manual user input'); +$shape->createParagraph()->createTextRun('File upload (e.g. excel, csv)'); +$shape->createParagraph()->createTextRun('Database upload (e.g. sqlite)'); +$shape->createParagraph()->createTextRun('Database connection to local or remote database'); +$shape->createParagraph()->createTextRun('External APIs'); +$shape->createParagraph()->createTextRun('Internal APIs (everything from the Orange Management backend)'); + +$shape = new File(); +$shape->setName('Company Logo') + ->setDescription('Company Logo') + ->setPath(__DIR__ . '/logo.png') + ->setHeight(50) + ->setOffsetX(880) + ->setOffsetY(650); +$oSlide4->addShape($shape); + +// end screen +$oSlide5 = $objPHPPresentation->createSlide(); +$oSlide5->setBackground($oBkgColor); + +$shape = new File(); +$shape->setName('Company Logo') + ->setDescription('Company Logo') + ->setPath(__DIR__ . '/logo.png') + ->setHeight(300) + ->setOffsetX(320) + ->setOffsetY(120); +$oSlide5->addShape($shape); + +$shape = $oSlide5->createRichTextShape() + ->setHeight(300) + ->setWidth(600) + ->setOffsetX(180) + ->setOffsetY(450); +$shape->getActiveParagraph()->getAlignment()->setHorizontal(Alignment::HORIZONTAL_CENTER); +$textRun = $shape->createTextRun('Thank You!'); +$textRun->getFont()->setBold(true)->setSize(42)->setColor($colorBlue); + +$writer = IOFactory::createWriter($objPHPPresentation, 'PowerPoint2007'); +$writer->save('php://output'); diff --git a/tests/depreciation/view.tpl.php b/tests/depreciation/view.tpl.php new file mode 100644 index 0000000..c87a77f --- /dev/null +++ b/tests/depreciation/view.tpl.php @@ -0,0 +1,58 @@ +getData('tcoll'); +$rcoll = $this->getData('rcoll'); +$cLang = $this->getData('lang'); +$template = $this->getData('template'); +$report = $this->getData('report'); +$basepath = \rtrim($this->getData('basepath') ?? '', '/'); + +/** @noinspection PhpIncludeInspection */ +$reportLanguage = include $basepath . '/' . \ltrim($tcoll['lang']->getPath(), '/'); +$lang = $reportLanguage[$cLang]; + +$amount = (float) ($this->request->getData('amount') ?? 10000.0); +$duration = (int) ($this->request->getData('duration') ?? 10); + +?> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
getCurrency(Depreciation::getStraightLineResidualInT($amount, $duration, $i), 'medium', ''); ?>getCurrency(Depreciation::getArithmeticDegressiveDepreciationResidualInT($amount, 0.0, $duration, $i), 'medium', ''); ?>getCurrency(Depreciation::getArithmeticProgressiveDepreciationResidualInT($amount, 0.0, $duration, $i), 'medium', ''); ?>getCurrency(Depreciation::getGeometicProgressiveDepreciationResidualInT($amount, $amount * 0.1, $duration, $i), 'medium', ''); ?>getCurrency(Depreciation::getGeometicDegressiveDepreciationResidualInT($amount, $amount * 0.1, $duration, $i), 'medium', ''); ?>
+ +
diff --git a/tests/depreciation/view.xls.php b/tests/depreciation/view.xls.php new file mode 100644 index 0000000..0b73dcb --- /dev/null +++ b/tests/depreciation/view.xls.php @@ -0,0 +1,56 @@ +getData('tcoll'); +$rcoll = $this->getData('rcoll'); +$cLang = $this->getData('lang'); +$template = $this->getData('template'); +$report = $this->getData('report'); +$basepath = \rtrim($this->getData('basepath') ?? '', '/'); + +/** @noinspection PhpIncludeInspection */ +$reportLanguage = include $basepath . '/' . \ltrim($tcoll['lang']->getPath(), '/'); +$lang = $reportLanguage[$cLang]; + +$amount = (float) ($this->request->getData('amount') ?? 10000.0); +$duration = (int) ($this->request->getData('duration') ?? 10); + +$spreadsheet = new Spreadsheet(); + +$spreadsheet->getProperties()->setCreator('Orange Management') + ->setLastModifiedBy('Orange Management') + ->setTitle('Orange Management - Depreciation Demo') + ->setSubject('Orange Management - Depreciation Demo') + ->setDescription('Demo') + ->setKeywords('demo helper depreciation') + ->setCategory('demo'); + +$spreadsheet->setActiveSheetIndex(0) + ->setCellValue('A1', $lang['Period']) + ->setCellValue('B1', $lang['StraightLine']) + ->setCellValue('C1', $lang['ArithmeticDegressive']) + ->setCellValue('D1', $lang['ArithmeticProgressive']) + ->setCellValue('E1', $lang['GeometricDegressive']) + ->setCellValue('F1', $lang['GeometricProgressive']); + +for ($i = 1; $i <= $duration; ++$i) { + $spreadsheet->setActiveSheetIndex(0) + ->setCellValue('A' . ($i + 1), $i) + ->setCellValue('B' . ($i + 1), $this->getCurrency(Depreciation::getStraightLineResidualInT($amount, $duration, $i), 'medium', '')) + ->setCellValue('C' . ($i + 1), $this->getCurrency(Depreciation::getArithmeticDegressiveDepreciationResidualInT($amount, 0.0, $duration, $i), 'medium', '')) + ->setCellValue('D' . ($i + 1), $this->getCurrency(Depreciation::getArithmeticProgressiveDepreciationResidualInT($amount, 0.0, $duration, $i), 'medium', '')) + ->setCellValue('E' . ($i + 1), $this->getCurrency(Depreciation::getGeometicProgressiveDepreciationResidualInT($amount, $amount * 0.1, $duration, $i), 'medium', '')) + ->setCellValue('F' . ($i + 1), $this->getCurrency(Depreciation::getGeometicDegressiveDepreciationResidualInT($amount, $amount * 0.1, $duration, $i), 'medium', '')); +} + +$spreadsheet->getActiveSheet()->setTitle($lang['Depreciation']); +$spreadsheet->setActiveSheetIndex(0); + +$writer = IOFactory::createWriter($spreadsheet, 'Xlsx'); +$writer->save('php://output');