This commit is contained in:
Dennis Eichhorn 2024-02-28 05:09:11 +00:00
parent 21f2c576d2
commit b36aa5d7d8
14 changed files with 651 additions and 137 deletions

View File

@ -1,35 +0,0 @@
---
name: Dev Bug Report
about: Create a report to help us improve
title: ''
labels: stat_backlog, type_bug
assignees: ''
---
# Bug Description
A clear and concise description of what the bug is.
# How to Reproduce
Steps to reproduce the behavior:
1. Go to '...'
2. Click on '....'
3. Scroll down to '....'
4. See error
## Minimal Code Example
```
// your code ...
```
# Expected Behavior
A clear and concise description of what you expected to happen.
# Screenshots
If applicable, add screenshots to help explain your problem.
# Additional Information
Add any other context about the problem here.

View File

@ -1,18 +0,0 @@
---
name: Dev Feature Request
about: Suggest an idea for this project
title: ''
labels: stat_backlog, type_feature
assignees: ''
---
# What is the feature you request
* A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
* A clear and concise description of what you want to happen.
# Alternatives
A clear and concise description of any alternative solutions or features you've considered.
# Additional Information
Add any other context or screenshots about the feature request here.

View File

@ -35,6 +35,18 @@
"style": "subtotal",
"children": []
},
{
"name": "GPratio",
"l11n": {
"en": "Gross profit %",
"de": "Rohertragsmarge %"
},
"account": [],
"type": "formula",
"formula": "3/1",
"style": "ratio",
"children": []
},
{
"name": "4",
"l11n": {
@ -267,5 +279,17 @@
"formula": "14+15",
"style": "total",
"children": []
},
{
"name": "ProfitRatio",
"l11n": {
"en": "Net profit %",
"de": "Jahresergebnis %"
},
"account": [],
"type": "formula",
"formula": "(14+15)/1",
"style": "ratio",
"children": []
}
]

View File

@ -99,12 +99,12 @@
{
"name": "GPratio",
"l11n": {
"en": "Gross profit ratio",
"de": "Rohertragsmarge"
"en": "Gross profit %",
"de": "Rohertragsmarge %"
},
"account": [],
"type": "formula",
"formula": "GP/(1+2+3+4)",
"formula": "GP/1",
"style": "ratio",
"children": []
},
@ -201,11 +201,109 @@
"en": "Other operating expenses",
"de": "Sonstige betriebliche Aufwendungen"
},
"account": [2150,2151,2166,2170,2171,2174,2175,2176,2300,2307,2308,2309,2310,2311,2312,2313,2320,2323,2325,2326,2327,2328,2339,2342,2343,2344,2345,2347,2350,2380,2381,2382,2383,2384,2385,2386,2387,2389,2390,2400,2401,2402,2403,2404,2405,2406,2407,2408,2409,2450,2451,2490,2890,2891,2892,2893,2894,2895,2900],
"account": [],
"type": "category",
"formula": "",
"expanded": true,
"style": "category",
"children": []
"children": [
{
"name": "8a",
"l11n": {
"en": "General expenses",
"de": "Allgemeine Aufwendungen"
},
"account": [2010, 2020, 2307, 2309, 4901, 4902, 4903, 4904, 4905, 4909],
"type": "category",
"formula": "",
"style": "category",
"children": []
},
{
"name": "8b",
"l11n": {
"en": "Building and property costs",
"de": "Raum- und Grundstückskosten"
},
"account": [2350, 4200, 4210, 4211, 4212, 4215, 4219, 4220, 4222, 4228, 4229, 4230, 4240, 4250, 4260, 4270, 4280, 4288, 4289, 4290],
"type": "category",
"formula": "",
"style": "category",
"children": []
},
{
"name": "8c",
"l11n": {
"en": "Donations",
"de": "Spenden / Zuwendungen"
},
"account": [2380, 2381, 2382, 2383, 2384, 2387, 2389, 2390],
"type": "category",
"formula": "",
"style": "category",
"children": []
},
{
"name": "8d",
"l11n": {
"en": "Levies",
"de": "Versicherungen / Abgaben"
},
"account": [4360, 4366, 4370, 4380, 4390, 4396, 4397],
"type": "category",
"formula": "",
"style": "category",
"children": []
},
{
"name": "8e",
"l11n": {
"en": "Repair / Maintenance",
"de": "Reparatur / Instandhaltung"
},
"account": [4800, 4801, 4805, 4806, 4809],
"type": "category",
"formula": "",
"style": "category",
"children": []
},
{
"name": "8f",
"l11n": {
"en": "Vehicle costs",
"de": "KFZ-Kosten"
},
"account": [4500, 4520, 4530, 4540, 4550, 4560, 4570, 4575, 4580, 4590],
"type": "category",
"formula": "",
"style": "category",
"children": []
},
{
"name": "8g",
"l11n": {
"en": "Advertising and travel expenses",
"de": "Werbe- und Reisekosten"
},
"account": [4600, 4605, 4630, 4631, 4632, 4635, 4636, 4639, 4640, 4650, 4651, 4652, 4653, 4654, 4655, 4660, 4663, 4664, 4666, 4668, 4670, 4672, 4673, 4674, 4676, 4678, 4679, 4680, 4681],
"type": "category",
"formula": "",
"style": "category",
"children": []
},
{
"name": "8h",
"l11n": {
"en": "Other costs",
"de": "Sonstige Kosten"
},
"account": [2150, 2151, 2166, 2170, 2171, 2176, 2385, 2386, 4139, 4300, 4301, 4306, 4810, 4969, 4970, 4971, 4975, 4976],
"type": "category",
"formula": "",
"style": "category",
"children": []
}
]
},
{
"name": "9",
@ -391,5 +489,17 @@
"formula": "15+16",
"style": "total",
"children": []
},
{
"name": "ProfitRatio",
"l11n": {
"en": "Net profit %",
"de": "Jahresergebnis %"
},
"account": [],
"type": "formula",
"formula": "(15+16)/1",
"style": "ratio",
"children": []
}
]

View File

@ -36,11 +36,26 @@
"type": "VARCHAR(255)",
"null": false
},
"incomestmt_pl_element_formula": {
"name": "incomestmt_pl_element_formula",
"type": "VARCHAR(255)",
"null": false
},
"incomestmt_pl_element_style": {
"name": "incomestmt_pl_element_style",
"type": "VARCHAR(255)",
"null": false
},
"incomestmt_pl_element_order": {
"name": "incomestmt_pl_element_order",
"type": "INT",
"null": false
},
"incomestmt_pl_element_expanded": {
"name": "incomestmt_pl_element_expanded",
"type": "TINYINT(1)",
"null": false
},
"incomestmt_pl_element_parent": {
"name": "incomestmt_pl_element_parent",
"type": "INT",
@ -87,5 +102,36 @@
"foreignKey": "language_639_1"
}
}
},
"incomestmt_pl_element_rel": {
"name": "incomestmt_pl_element_rel",
"fields": {
"incomestmt_pl_element_rel_id": {
"name": "incomestmt_pl_element_rel_id",
"type": "INT",
"null": false,
"primary": true,
"autoincrement": true
},
"incomestmt_pl_element_rel_order": {
"name": "incomestmt_pl_element_rel_order",
"type": "INT",
"null": true
},
"incomestmt_pl_element_rel_account": {
"name": "incomestmt_pl_element_rel_account",
"type": "INT",
"null": false,
"foreignTable": "accounting_account",
"foreignKey": "accounting_account_id"
},
"incomestmt_pl_element_rel_element": {
"name": "incomestmt_pl_element_rel_element",
"type": "INT",
"null": false,
"foreignTable": "incomestmt_pl_element",
"foreignKey": "incomestmt_pl_element_id"
}
}
}
}

View File

@ -14,6 +14,8 @@ declare(strict_types=1);
namespace Modules\IncomeStatement\Admin;
use Modules\Accounting\Models\AccountAbstract;
use Modules\Accounting\Models\AccountAbstractMapper;
use Modules\IncomeStatement\Controller\ApiController;
use phpOMS\Application\ApplicationAbstract;
use phpOMS\Config\SettingsInterface;
@ -62,7 +64,7 @@ final class Installer extends InstallerAbstract
private static function importStructures(ApplicationAbstract $app) : void
{
/** @var \Modules\IncomeStatement\Controller\ApiController $module */
$module = $app->moduleManager->getModuleInstance('IncomeStatement', 'Api');
$module = $app->moduleManager->get('IncomeStatement', 'Api');
$structures = \scandir(__DIR__ . '/Install/Coa');
foreach ($structures as $file) {
@ -74,8 +76,8 @@ final class Installer extends InstallerAbstract
$request = new HttpRequest();
$request->header->account = 1;
$request->setData('code', \strtolower(\basename($file)));
$request->setData('name', \strtr(\basename($file), '_', ' '));
$request->setData('code', \strtolower(\basename($file, '.json')));
$request->setData('name', \strtr(\basename($file, '.json'), '_', ' '));
$module->apiIncomeStatementCreate($request, $response);
$responseData = $response->getData('');
@ -102,16 +104,31 @@ final class Installer extends InstallerAbstract
$request->setData('code', $element['name']);
$request->setData('content', \reset($element['l11n']));
$request->setData('language', \array_keys($element['l11n'])[0] ?? 'en');
$request->setData('accounts', \implode(',', $element['account']));
$request->setData('formula', $element['formula']);
$request->setData('style', $element['style']);
$request->setData('type', $element['type']);
$request->setData('pl', $structure);
$request->setData('order', $order);
$request->setData('expanded', $element['expanded'] ?? false);
if ($parent !== null) {
$request->setData('parent', $parent);
}
if (!empty($element['account'])) {
$accountObjects = AccountAbstractMapper::getAll()
->where('code', \array_map(function($account) {
return (string) $account;
}, $element['account']), 'IN')
->execute();
$request->setData('accounts', \implode(',',
\array_map(function (AccountAbstract $account) {
return $account->id;
}, $accountObjects)
));
}
$module->apiIncomeStatementElementCreate($request, $response);
$responseData = $response->getData('');
@ -130,7 +147,7 @@ final class Installer extends InstallerAbstract
$request = new HttpRequest();
$request->header->account = 1;
$request->setData('title', $l11n);
$request->setData('content', $l11n);
$request->setData('language', $language);
$request->setData('ref', $incomeStatementElement['id']);

View File

@ -14,6 +14,7 @@ declare(strict_types=1);
namespace Modules\IncomeStatement\Controller;
use Modules\Accounting\Models\NullAccountAbstract;
use Modules\IncomeStatement\Models\IncomeStatement;
use Modules\IncomeStatement\Models\IncomeStatementElement;
use Modules\IncomeStatement\Models\IncomeStatementElementL11nMapper;
@ -163,10 +164,18 @@ final class ApiController extends Controller
{
$element = new IncomeStatementElement();
$element->code = $request->getDataString('code') ?? '';
$element->formula = $request->getDataString('formula') ?? '';
$element->style = $request->getDataString('style') ?? '';
$element->incomeStatement = $request->getDataInt('pl') ?? 0;
$element->order = $request->getDataInt('order') ?? 0;
$element->expanded = $request->getDataBool('expanded') ?? false;
$element->parent = $request->getDataInt('parent');
$accounts = $request->getDataList('accounts');
foreach ($accounts as $account) {
$element->accounts[] = new NullAccountAbstract((int) $account);
}
$element->setL11n(
$request->getDataString('content') ?? '',
ISO639x1Enum::tryFromValue($request->getDataString('language')) ?? ISO639x1Enum::_EN

View File

@ -14,7 +14,9 @@ declare(strict_types=1);
namespace Modules\IncomeStatement\Controller;
use Modules\IncomeStatement\Models\IncomeStatementElementL11nMapper;
use Modules\IncomeStatement\Models\IncomeStatementElementMapper;
use Modules\IncomeStatement\Models\IncomeStatementMapper;
use phpOMS\Contract\RenderableInterface;
use phpOMS\DataStorage\Database\Query\OrderType;
use phpOMS\Message\RequestAbstract;
@ -49,14 +51,29 @@ final class BackendController extends Controller
$view->setTemplate('/Modules/IncomeStatement/Theme/Backend/pl-dashboard');
$view->data['nav'] = $this->app->moduleManager->get('Navigation')->createNavigationMid(1006401001, $request, $response);
$elements = IncomeStatementElementMapper::getAll()
$view->data['elements'] = IncomeStatementElementMapper::getAll()
->with('l11n')
->where('incomeStatement', $request->getDataInt('pl') ?? 1)
->where('l11n/language', $response->header->l11n->language)
->with('accounts')
->with('accounts/l11n')
->where('incomeStatement', $request->getDataInt('structure') ?? 1)
->where('l11n/language', $request->getDataString('language') ?? $response->header->l11n->language)
->where('accounts/l11n/language', $request->getDataString('language') ?? $response->header->l11n->language)
->sort('order', OrderType::ASC)
->execute();
$view->data['elements'] = $elements;
$view->data['structures'] = IncomeStatementMapper::getAll()
->execute();
$view->data['languages'] = [];
if (!empty($view->data['elements'])) {
$tempL11ns = IncomeStatementElementL11nMapper::getAll()
->where('ref', \reset($view->data['elements'])->id)
->execute();
foreach ($tempL11ns as $l11n) {
$view->data['languages'][] = $l11n->language;
}
}
return $view;
}

View File

@ -41,12 +41,17 @@ class IncomeStatementElement
public string $formula = '';
public string $style = '';
public int $order = 0;
public bool $expanded = false;
public int $incomeStatement = 0;
public ?int $parent = null;
public array $accounts = [];
/*
* String l11n
*

View File

@ -14,6 +14,7 @@ declare(strict_types=1);
namespace Modules\IncomeStatement\Models;
use Modules\Accounting\Models\AccountAbstractMapper;
use phpOMS\DataStorage\Database\Mapper\DataMapperFactory;
use phpOMS\Localization\BaseStringL11n;
@ -39,7 +40,10 @@ final class IncomeStatementElementMapper extends DataMapperFactory
public const COLUMNS = [
'incomestmt_pl_element_id' => ['name' => 'incomestmt_pl_element_id', 'type' => 'int', 'internal' => 'id'],
'incomestmt_pl_element_code' => ['name' => 'incomestmt_pl_element_code', 'type' => 'string', 'internal' => 'code', 'autocomplete' => true],
'incomestmt_pl_element_formula' => ['name' => 'incomestmt_pl_element_formula', 'type' => 'string', 'internal' => 'formula', 'autocomplete' => true],
'incomestmt_pl_element_style' => ['name' => 'incomestmt_pl_element_style', 'type' => 'string', 'internal' => 'style', 'autocomplete' => true],
'incomestmt_pl_element_order' => ['name' => 'incomestmt_pl_element_order', 'type' => 'int', 'internal' => 'order'],
'incomestmt_pl_element_expanded' => ['name' => 'incomestmt_pl_element_expanded', 'type' => 'bool', 'internal' => 'expanded'],
'incomestmt_pl_element_parent' => ['name' => 'incomestmt_pl_element_parent', 'type' => 'int', 'internal' => 'parent'],
'incomestmt_pl_element_pl' => ['name' => 'incomestmt_pl_element_pl', 'type' => 'int', 'internal' => 'incomeStatement'],
];
@ -58,6 +62,12 @@ final class IncomeStatementElementMapper extends DataMapperFactory
'column' => 'content',
'external' => null,
],
'accounts' => [
'mapper' => AccountAbstractMapper::class,
'table' => 'incomestmt_pl_element_rel',
'self' => 'incomestmt_pl_element_rel_element',
'external' => 'incomestmt_pl_element_rel_account',
],
];
/**

View File

@ -0,0 +1,33 @@
<?php
/**
* Jingga
*
* PHP Version 8.1
*
* @package Modules\PL
* @copyright Dennis Eichhorn
* @license OMS License 2.0
* @version 1.0.0
* @link https://jingga.app
*/
declare(strict_types=1);
return ['IncomeStatement' => [
'Start' => 'Start',
'End' => 'Ende',
'Overview' => 'Übersicht',
'Metrics' => 'Metriken',
'Charts' => 'Charts',
'Interval' => 'Intervall',
'Environment' => 'Environment',
'Monthly' => 'Monatlich',
'Quarterly' => 'Quartalsweise',
'Annually' => 'Jährlich',
'Category' => 'Kategorie',
'Subtotal' => 'Zwischensumme',
'Total' => 'Summe',
'HR' => 'Personal',
'Sales' => 'Umsatz',
'Diff' => 'Diff',
'Diff%' => 'Diff %',
]];

View File

@ -12,5 +12,22 @@
*/
declare(strict_types=1);
return ['PL' => [
return ['IncomeStatement' => [
'Start' => 'Start',
'End' => 'End',
'Overview' => 'Overview',
'Metrics' => 'Metrics',
'Charts' => 'Charts',
'Interval' => 'Interval',
'Environment' => 'Environment',
'Monthly' => 'Monthly',
'Quarterly' => 'Quarterly',
'Annually' => 'Annually',
'Category' => 'Category',
'Subtotal' => 'Subtotal',
'Total' => 'Total',
'HR' => 'HR',
'Diff' => 'Diff',
'Sales' => 'Sales',
'Diff%' => 'Diff %',
]];

View File

@ -12,54 +12,88 @@
*/
declare(strict_types=1);
use phpOMS\Localization\ISO639Enum;
function render_accounts(array $accounts) : string
{
$row = '';
foreach ($accounts as $account) {
$row .= <<<ROW
<div class="account data-row">
<div class="expand-col"></div>
<div class="name-col">{$account->code} - {$account->getL11n()}</div>
<div>123,456.00</div>
<div>123,456.00</div>
<div>123,456.00</div>
<div>123,456.00</div>
<div>123,456.00</div>
<div>123,456.00</div>
<div>123,456.00</div>
<div>123,456.00</div>
<div>123,456.00</div>
<div>123,456.00</div>
<div>123,456.00</div>
<div>123,456.00</div>
<div class="total-col">123,456.00</div>
<div class="total-col">1,234.56 %</div>
<div class="total-col">123,456.00</div>
</div>
ROW;
}
return $row;
}
function render_elements(array $elements, ?int $parent = null) : string
{
$row = '';
$fn = 'render_elements';
$acc = 'render_accounts';
foreach ($elements as $element) {
if ($element->parent !== $parent) {
continue;
}
$expand = '';
foreach ($elements as $child) {
if ($child->parent === $element->id
|| !empty($element->accounts)
) {
$expand = '<label for="iEle' . $element->id . '-expand" class="btn maximize"><i class="g-icon">add_circle</i></label><label for="iEle' . $element->id . '-expand" class="btn minimize"><i class="g-icon">do_not_disturb_on</i></label>';
break;
}
}
$expanded = $element->expanded ? ' checked' : '';
$row .= <<<ROW
<div>
<div style="display: flex; flex-direction: row; align-items: center; background: #ff000099;">
<div style="flex: 0; width: 30px; min-width: 30px; padding: 1px;"><label for="iElement{$element->id}-expand" class="btn"><i class="g-icon">add_circle</i></label></div>
<div style="flex: 0; width: 150px; min-width: 150px; box-sizing: border-box; padding-left: 0px;">{$element->getL11n()}</div>
<div style="flex: 1; padding: 1px;">+0.00%</div>
<div style="flex: 1; padding: 1px;">+0.00%</div>
<div style="flex: 1; padding: 1px;">+0.00%</div>
<div style="flex: 1; padding: 1px;">+0.00%</div>
<div style="flex: 1; padding: 1px;">+0.00%</div>
<div style="flex: 1; padding: 1px;">+0.00%</div>
<div style="flex: 1; padding: 1px;">+0.00%</div>
<div style="flex: 1; padding: 1px;">+0.00%</div>
<div style="flex: 1; padding: 1px;">+0.00%</div>
<div style="flex: 1; padding: 1px;">+0.00%</div>
<div style="flex: 1; padding: 1px;">+0.00%</div>
<div style="flex: 1; padding: 1px;">+0.00%</div>
<div style="flex: 1; padding: 1px;">+0.00%</div>
<div style="flex: 1; padding: 1px;">+0.00%</div>
<div style="flex: 1; padding: 1px;">+0.00%</div>
<div style="flex: 1; padding: 1px;">+0.00%</div>
<div style="flex: 1; padding: 1px;">+0.00%</div>
<div style="flex: 1; padding: 1px;">+0.00%</div>
<div style="flex: 1; padding: 1px;">+0.00%</div>
<div style="flex: 1; padding: 1px;">+0.00%</div>
<div style="flex: 1; padding: 1px;">+0.00%</div>
<div style="flex: 1; padding: 1px;">+0.00%</div>
<div style="flex: 1; padding: 1px;">+0.00%</div>
<div style="flex: 1; padding: 1px;">+0.00%</div>
<div style="flex: 1; padding: 1px;">+0.00%</div>
<div style="flex: 1; padding: 1px;">+0.00%</div>
<div style="flex: 1; padding: 1px;">+0.00%</div>
<div style="flex: 1; padding: 1px;">+0.00%</div>
<input id="iEle{$element->id}-expand" type="checkbox" class="vh"{$expanded}>
<div class="{$element->style} data-row">
<div class="expand-col">{$expand}</div>
<div class="name-col">{$element->getL11n()}</div>
<div>123,456.00</div>
<div>123,456.00</div>
<div>123,456.00</div>
<div>123,456.00</div>
<div>123,456.00</div>
<div>123,456.00</div>
<div>123,456.00</div>
<div>123,456.00</div>
<div>123,456.00</div>
<div>123,456.00</div>
<div>123,456.00</div>
<div>123,456.00</div>
<div class="total-col">123,456.00</div>
<div class="total-col">1,234.56 %</div>
<div class="total-col">123,456.00</div>
</div>
<input id="iElement{$element->id}-expand" type="checkbox" class="hidden">
<div class="checked-visibility">
{$fn($elements, $element->id)}
{$acc($element->accounts)}
</div>
</div>
ROW;
@ -70,48 +104,292 @@ function render_elements(array $elements, ?int $parent = null) : string
echo $this->data['nav']->render();
?>
<style>
div {
box-sizing: border-box;
}
<div class="row" style="font-size: 0.8rem; margin-top: 1rem;">
<div class="col-xs-12">
<div style="background: #ff00ff99;">
<div style="display: flex; flex-direction: row; align-items: center;">
<div style="flex: 0; width: 30px; min-width: 30px; text-align: center;"></div>
<div style="flex: 0; width: 150px; min-width: 150px; box-sizing: border-box; text-align: center;">Category</div>
<div style="flex: 1; text-align: center;">1</div>
<div style="flex: 1; text-align: center;">2</div>
<div style="flex: 1; text-align: center;">3</div>
<div style="flex: 1; text-align: center;">4</div>
<div style="flex: 1; text-align: center;">5</div>
<div style="flex: 1; text-align: center;">6</div>
<div style="flex: 1; text-align: center;">7</div>
<div style="flex: 1; text-align: center;">8</div>
<div style="flex: 1; text-align: center;">9</div>
<div style="flex: 1; text-align: center;">10</div>
<div style="flex: 1; text-align: center;">11</div>
<div style="flex: 1; text-align: center;">12</div>
<div style="flex: 1; text-align: center;">1</div>
<div style="flex: 1; text-align: center;">2</div>
<div style="flex: 1; text-align: center;">3</div>
<div style="flex: 1; text-align: center;">4</div>
<div style="flex: 1; text-align: center;">5</div>
<div style="flex: 1; text-align: center;">6</div>
<div style="flex: 1; text-align: center;">7</div>
<div style="flex: 1; text-align: center;">8</div>
<div style="flex: 1; text-align: center;">9</div>
<div style="flex: 1; text-align: center;">10</div>
<div style="flex: 1; text-align: center;">11</div>
<div style="flex: 1; text-align: center;">12</div>
<div style="flex: 1; text-align: center;">12</div>
<div style="flex: 1; text-align: center;">12</div>
<div style="flex: 1; text-align: center;">Diff %</div>
<div style="flex: 1; text-align: center;">Diff USD</div>
input:checked+div > div > .maximize {
display: none;
}
input+div > div > .minimize {
display: none;
}
input:checked+div > div > .minimize {
display: inline-block;
}
.title-cell {
padding: 1px;
text-align: center;
width: 95px;
}
.category {
background: #fff;
border-bottom: 1px solid #000 !important;
}
.subtotal {
background: #ffa82e;
border-bottom: 1px solid #000 !important;
}
.subtotal .total-col {
background: #ffa82e;
}
.total {
background: #ffa82e;
border-bottom: 1px solid #000 !important;
}
.total .total-col {
background: #ffa82e;
}
.total-col {
background: #cbfbcb;
}
.data-row {
display: inline-flex;
flex-direction: row;
border-bottom: 1px solid #fff;
align-items: stretch;
min-height: 34px;
}
.data-row div {
padding: .2rem 3px .2rem 3px;
display: flex;
align-items: center;
}
.account:nth-child(2n) {
background: #f9f9f9;
}
.account:nth-child(2n + 1) {
background: #efefef;
}
.data-row div:nth-child(n+3) {
width: 95px;
justify-content: end;
}
.expand-col {
width: 30px;
min-width: 30px;
padding: 1px;
}
.name-col {
width: 150px;
min-width: 150px;
padding-left: 0px;
border-right: 1px solid #000;
overflow: clip;
}
</style>
<div class="row">
<div class="col-xs-12 col-md-6">
<div class="box">
<div class="form-group">
<div class="input-control">
<select id="iStructure" name="structure" data-action='[{"listener": "change", "action": [{"key": 1, "type": "redirect", "uri": "{%}&structure={#iStructure}", "target": "self"}]}]'>
<?php foreach ($this->data['structures'] as $structure) : ?>
<option value="<?= $structure->id; ?>"<?= $this->request->getDataInt('structure') === $structure->id ? ' selected' : ''; ?>><?= $this->printHtml($structure->name); ?>
<?php endforeach; ?>
</select>
</div>
<div class="input-control">
<select id="iLanguage" name="language" data-action='[{"listener": "change", "action": [{"key": 1, "type": "redirect", "uri": "{%}&language={#iLanguage}", "target": "self"}]}]'>
<?php foreach ($this->data['languages'] as $language) : ?>
<option value="<?= $language; ?>"<?= $this->request->getDataString('language') === $language ? ' selected' : ''; ?>><?= $this->printHtml(ISO639Enum::getBy2Code($language)); ?>
<?php endforeach; ?>
</select>
</div>
</div>
</div>
</div>
</div>
<div class="row" style="font-size: 0.8rem;">
<div class="col-xs-12">
<?= \render_elements($this->data['elements'], null); ?>
<div class="row">
<div class="col-xs-12 col-md-6">
<section class="portlet">
<div class="portlet-body">
<div class="form-group">
<div class="input-control">
<label><?= $this->getHtml('Start'); ?></label>
<input type="date">
</div>
<div class="input-control">
<label><?= $this->getHtml('Start'); ?></label>
<input type="date">
</div>
</div>
<div class="form-group">
<div class="input-control">
<label><?= $this->getHtml('Interval'); ?></label>
<select>
<option><?= $this->getHtml('Monthly'); ?>
<option><?= $this->getHtml('Quarterly'); ?>
<option><?= $this->getHtml('Annually'); ?>
</select>
</div>
<div class="input-control">
<label><?= $this->getHtml('Environment'); ?></label>
<select></select>
</div>
</div>
</div>
<div class="portlet-foot">
<input type="submit" value="<?= $this->getHtml('Submit', '0', '0'); ?>">
<input class="close" type="submit" value="<?= $this->getHtml('Reset', '0', '0'); ?>">
</div>
</section>
</div>
<div class="col-xs-12 col-md-6">
<section class="portlet">
<div class="portlet-body">
<div class="form-group">
<div class="input-control">
<label><?= $this->getHtml('Start'); ?></label>
<input type="date">
</div>
<div class="input-control">
<label><?= $this->getHtml('Start'); ?></label>
<input type="date">
</div>
</div>
<div class="form-group">
<div class="input-control">
<label><?= $this->getHtml('Interval'); ?></label>
<select>
<option><?= $this->getHtml('Monthly'); ?>
<option><?= $this->getHtml('Quarterly'); ?>
<option><?= $this->getHtml('Annually'); ?>
</select>
</div>
<div class="input-control">
<label><?= $this->getHtml('Environment'); ?></label>
<select></select>
</div>
</div>
</div>
<div class="portlet-foot">
<input type="submit" value="<?= $this->getHtml('Submit', '0', '0'); ?>">
<input class="close" type="submit" value="<?= $this->getHtml('Reset', '0', '0'); ?>">
</div>
</section>
</div>
</div>
<div class="tabview tab-2">
<div class="box">
<ul class="tab-links">
<li><label for="c-tab-1"><?= $this->getHtml('Overview'); ?></label>
<li><label for="c-tab-4"><?= $this->getHtml('Charts'); ?></label>
</ul>
</div>
<div class="tab-content">
<input type="radio" id="c-tab-1" name="tabular-2"<?= $this->request->uri->fragment === 'c-tab-1' ? ' checked' : ''; ?>>
<div class="tab">
<div class="row sticky" style="font-size: 0.8rem; display: flex;">
<div style="display: flex; flex-direction: row; align-items: center; color: #fff; background: #3697db; padding: .5rem 0 .5rem 0">
<div style="width: 30px; min-width: 30px; text-align: center;"></div>
<div style="width: 150px; min-width: 150px; box-sizing: border-box; text-align: center;"><?= $this->getHtml('Category'); ?></div>
<div class="title-cell">1</div>
<div class="title-cell">2</div>
<div class="title-cell">3</div>
<div class="title-cell">4</div>
<div class="title-cell">5</div>
<div class="title-cell">6</div>
<div class="title-cell">7</div>
<div class="title-cell">8</div>
<div class="title-cell">9</div>
<div class="title-cell">10</div>
<div class="title-cell">11</div>
<div class="title-cell">12</div>
<div class="title-cell"><?= $this->getHtml('Total'); ?></div>
<div class="title-cell"><?= $this->getHtml('Diff%'); ?></div>
<div class="title-cell"><?= $this->getHtml('Diff'); ?> USD</div>
</div>
</div>
<div class="row" style="font-size: 0.8rem;">
<div class="col-xs-12"><?= \render_elements($this->data['elements'], null); ?></div>
</div>
</div>
<input type="radio" id="c-tab-4" name="tabular-2"<?= $this->request->uri->fragment === 'c-tab-4' ? ' checked' : ''; ?>>
<div class="tab">
<div class="row">
<div class="col-xs-12">
<section class="portlet">
<div class="portlet-body">
<img height="100%" width="100%" src="Web/Backend/img/under_construction.svg">
<!--
PL
1. Ebit
2. Ebit margin
3. EBITDA
4. EBITDA margin
5. Gross profit
6. Gross profit margin
7. HR development (headcount, costs, costs per employee, total+per department)
8. HR expense ratio
9. HR count
10. HR expense per employee
11. Total HR expenses (headcount, costs, costs per employee, total+per department)
12. Total HR expense ratio
13. Total HR expense per employee
14. Sales
15. HR sales per employee
16. Depreciation ratio
17. Sales segmentation
18. Net profit margin
Balance
1. Current Ratio
2. Quick Ratio
3. Working Capital
4. Debt/Equity
5. DSO
6. DPO
7. DIO
8. Cash conversion cycle
9. Receivables Turnover
10. Inventory Turnover
11. Average age of inventory
12. Intangibles to book value
13. Inventory to sales
14. LT dept as % of invested capital
15. ST dept as % of invested capital
16. LT dept to total debt
17. ST debt to total debt
18. Total liabilities to total assets
19. Price to working capital
20. Cash Ratio
21. Payable Turnover
22. Return on assets
23. Asset turnover ratio
-->
</div>
</section>
</div>
</div>
</div>
</div>
</div>

View File

@ -16,6 +16,7 @@
},
"directory": "IncomeStatement",
"dependencies": {
"Accounting": "*",
"Controlling": "*"
},
"providing": {