This commit is contained in:
Dennis Eichhorn 2024-02-28 05:09:09 +00:00
parent d9a6471683
commit 23b2181b01
14 changed files with 553 additions and 158 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

@ -8,7 +8,8 @@
"account": [], "account": [],
"type": "category", "type": "category",
"formula": "", "formula": "",
"style": "category", "style": "total",
"expanded": true,
"children": [ "children": [
{ {
"name": "A.A", "name": "A.A",
@ -27,7 +28,7 @@
"en": "Intangible Assets", "en": "Intangible Assets",
"de": "Immaterielle Vermögensgegenständ" "de": "Immaterielle Vermögensgegenständ"
}, },
"account": [], "account": [5],
"type": "category", "type": "category",
"formula": "", "formula": "",
"style": "category", "style": "category",
@ -38,7 +39,7 @@
"en": "Self-determined trademarks and similar rights and values", "en": "Self-determined trademarks and similar rights and values",
"de": "Selbst geschaffene gewerbliche Schutzrechte und ähnliche Rechte und Werte" "de": "Selbst geschaffene gewerbliche Schutzrechte und ähnliche Rechte und Werte"
}, },
"account": [], "account": [43,44,45,46,47,48],
"type": "category", "type": "category",
"formula": "", "formula": "",
"style": "category", "style": "category",
@ -50,7 +51,7 @@
"en": "Purchased licenses, trademarks and similar rights and values as well as licenses to such rights and values", "en": "Purchased licenses, trademarks and similar rights and values as well as licenses to such rights and values",
"de": "entgeltlich erworbene Konzessionen, gewerbliche Schutzrechte und ähnliche Rechte und Werte sowie Lizenzen an solchen Rechten und Werten" "de": "entgeltlich erworbene Konzessionen, gewerbliche Schutzrechte und ähnliche Rechte und Werte sowie Lizenzen an solchen Rechten und Werten"
}, },
"account": [], "account": [10,15,20,25,27,30],
"type": "category", "type": "category",
"formula": "", "formula": "",
"style": "category", "style": "category",
@ -62,7 +63,7 @@
"en": "Goodwill", "en": "Goodwill",
"de": "Geschäfts- oder Firmenwert" "de": "Geschäfts- oder Firmenwert"
}, },
"account": [], "account": [35],
"type": "category", "type": "category",
"formula": "", "formula": "",
"style": "category", "style": "category",
@ -74,7 +75,7 @@
"en": "Advance payments made", "en": "Advance payments made",
"de": "geleistete Anzahlungen" "de": "geleistete Anzahlungen"
}, },
"account": [], "account": [38,39],
"type": "category", "type": "category",
"formula": "", "formula": "",
"style": "category", "style": "category",
@ -99,7 +100,7 @@
"en": "Properties, rights equivalent to real property and buildings, including buildings on third-party land", "en": "Properties, rights equivalent to real property and buildings, including buildings on third-party land",
"de": "Grundstücke, grundstücksgleiche Rechte und Bauten einschließlich der Bauten auf fremden Grundstücken" "de": "Grundstücke, grundstücksgleiche Rechte und Bauten einschließlich der Bauten auf fremden Grundstücken"
}, },
"account": [], "account": [50,59,60,65,70,75,80,85,90,100,110,111,112,113,115,140,145,146,147,148,149,160,165,170,175,176,177,178,179,190,191,192,193,194],
"type": "category", "type": "category",
"formula": "", "formula": "",
"style": "category", "style": "category",
@ -111,7 +112,7 @@
"en": "Technical equipment and machinery", "en": "Technical equipment and machinery",
"de": "technische Anlagen und Maschinen" "de": "technische Anlagen und Maschinen"
}, },
"account": [], "account": [200,210,220,240,260,280],
"type": "category", "type": "category",
"formula": "", "formula": "",
"style": "category", "style": "category",
@ -123,7 +124,7 @@
"en": "Other equipment, operating and office equipment", "en": "Other equipment, operating and office equipment",
"de": "andere Anlagen, Betriebs- und Geschäftsausstattung" "de": "andere Anlagen, Betriebs- und Geschäftsausstattung"
}, },
"account": [], "account": [300,310,320,350,380,400,410,420,430,440,450,460,480,485,490],
"type": "category", "type": "category",
"formula": "", "formula": "",
"style": "category", "style": "category",
@ -135,7 +136,7 @@
"en": "Advance payments made and construction in progress", "en": "Advance payments made and construction in progress",
"de": "geleistete Anzahlungen und Anlagen im Bau" "de": "geleistete Anzahlungen und Anlagen im Bau"
}, },
"account": [], "account": [79,120,129,150,159,180,189,195,199,290,299,498,499],
"type": "category", "type": "category",
"formula": "", "formula": "",
"style": "category", "style": "category",
@ -160,7 +161,7 @@
"en": "Shares in affiliated companies", "en": "Shares in affiliated companies",
"de": "Anteile an verbundenen Unternehmen" "de": "Anteile an verbundenen Unternehmen"
}, },
"account": [], "account": [500,501,502,503,504,509],
"type": "category", "type": "category",
"formula": "", "formula": "",
"style": "category", "style": "category",
@ -172,7 +173,7 @@
"en": "Loans to affiliated companies", "en": "Loans to affiliated companies",
"de": "Ausleihungen an verbundene Unternehmen" "de": "Ausleihungen an verbundene Unternehmen"
}, },
"account": [], "account": [505,506,507,508,520,523,524],
"type": "category", "type": "category",
"formula": "", "formula": "",
"style": "category", "style": "category",
@ -184,7 +185,7 @@
"en": "Other long-term equity investments", "en": "Other long-term equity investments",
"de": "Beteiligungen" "de": "Beteiligungen"
}, },
"account": [], "account": [510,513,516,517,518,519,570],
"type": "category", "type": "category",
"formula": "", "formula": "",
"style": "category", "style": "category",
@ -208,7 +209,7 @@
"en": "Long-term securities", "en": "Long-term securities",
"de": "Wertpapiere des Anlagevermögens" "de": "Wertpapiere des Anlagevermögens"
}, },
"account": [], "account": [525,530,535,538],
"type": "category", "type": "category",
"formula": "", "formula": "",
"style": "category", "style": "category",
@ -220,7 +221,7 @@
"en": "Other loans", "en": "Other loans",
"de": "sonstige Ausleihungen" "de": "sonstige Ausleihungen"
}, },
"account": [], "account": [540,550,580,582,583,584,586,590],
"type": "category", "type": "category",
"formula": "", "formula": "",
"style": "category", "style": "category",
@ -418,7 +419,7 @@
"name": "A.C", "name": "A.C",
"l11n": { "l11n": {
"en": "Accrual", "en": "Accrual",
"de": "Rechnungsabgrenzungsposten" "de": "ARAP"
}, },
"account": [], "account": [],
"type": "category", "type": "category",
@ -461,7 +462,8 @@
"account": [], "account": [],
"type": "category", "type": "category",
"formula": "", "formula": "",
"style": "category", "style": "total",
"expanded": true,
"children": [ "children": [
{ {
"name": "P.A", "name": "P.A",
@ -469,7 +471,7 @@
"en": "Equity", "en": "Equity",
"de": "Eigenkapital" "de": "Eigenkapital"
}, },
"account": [], "account": [810,811,812,813,815,819],
"type": "category", "type": "category",
"formula": "", "formula": "",
"style": "category", "style": "category",
@ -480,7 +482,7 @@
"en": "Subscribed Capital", "en": "Subscribed Capital",
"de": "Gezeichnetes Kapital" "de": "Gezeichnetes Kapital"
}, },
"account": [], "account": [800,809],
"type": "category", "type": "category",
"formula": "", "formula": "",
"style": "category", "style": "category",
@ -651,7 +653,7 @@
"en": "Bonds", "en": "Bonds",
"de": "Anleihen" "de": "Anleihen"
}, },
"account": [], "account": [600,601,605,610,615,616,620,625],
"type": "category", "type": "category",
"formula": "", "formula": "",
"style": "category", "style": "category",
@ -676,7 +678,7 @@
"en": "Liabilities to financial institutions", "en": "Liabilities to financial institutions",
"de": "Verbindlichkeiten gegenüber Kreditinstituten" "de": "Verbindlichkeiten gegenüber Kreditinstituten"
}, },
"account": [], "account": [630, 631, 640, 650,660,661,670,680,690,699],
"type": "category", "type": "category",
"formula": "", "formula": "",
"style": "category", "style": "category",
@ -724,7 +726,7 @@
"en": "Liabilities to affiliated companies", "en": "Liabilities to affiliated companies",
"de": "Verbindlichkeiten gegenüber verbundenen Unternehmen" "de": "Verbindlichkeiten gegenüber verbundenen Unternehmen"
}, },
"account": [], "account": [700,701,705,710],
"type": "category", "type": "category",
"formula": "", "formula": "",
"style": "category", "style": "category",
@ -736,7 +738,7 @@
"en": "Liabilities to companies invested in", "en": "Liabilities to companies invested in",
"de": "Verbindlichkeiten gegenüber Unternehmen, mit denen ein Beteiligungsverhältnis besteht" "de": "Verbindlichkeiten gegenüber Unternehmen, mit denen ein Beteiligungsverhältnis besteht"
}, },
"account": [], "account": [715,716,720,725],
"type": "category", "type": "category",
"formula": "", "formula": "",
"style": "category", "style": "category",
@ -748,7 +750,7 @@
"en": "Other liabilities", "en": "Other liabilities",
"de": "sonstige Verbindlichkeiten" "de": "sonstige Verbindlichkeiten"
}, },
"account": [], "account": [730,731,740,750,755,760,761,764,767,770,771,774,777,780,781,784,787,790,799],
"type": "category", "type": "category",
"formula": "", "formula": "",
"style": "category", "style": "category",
@ -785,7 +787,7 @@
"name": "P.D", "name": "P.D",
"l11n": { "l11n": {
"en": "Accrual", "en": "Accrual",
"de": "Rechnungsabgrenzungsposten" "de": "PRAP"
}, },
"account": [], "account": [],
"type": "category", "type": "category",

View File

@ -8,7 +8,8 @@
"account": [], "account": [],
"type": "category", "type": "category",
"formula": "", "formula": "",
"style": "category", "style": "total",
"expanded": true,
"children": [ "children": [
{ {
"name": "A.A", "name": "A.A",
@ -373,7 +374,8 @@
"account": [], "account": [],
"type": "category", "type": "category",
"formula": "", "formula": "",
"style": "category", "style": "total",
"expanded": true,
"children": [ "children": [
{ {
"name": "P.A", "name": "P.A",

View File

@ -36,11 +36,26 @@
"type": "VARCHAR(255)", "type": "VARCHAR(255)",
"null": false "null": false
}, },
"balance_balance_element_formula": {
"name": "balance_balance_element_formula",
"type": "VARCHAR(255)",
"null": false
},
"balance_balance_element_style": {
"name": "balance_balance_element_style",
"type": "VARCHAR(255)",
"null": false
},
"balance_balance_element_order": { "balance_balance_element_order": {
"name": "balance_balance_element_order", "name": "balance_balance_element_order",
"type": "INT", "type": "INT",
"null": false "null": false
}, },
"balance_balance_element_expanded": {
"name": "balance_balance_element_expanded",
"type": "TINYINT(1)",
"null": false
},
"balance_balance_element_parent": { "balance_balance_element_parent": {
"name": "balance_balance_element_parent", "name": "balance_balance_element_parent",
"type": "INT", "type": "INT",
@ -87,5 +102,36 @@
"foreignKey": "language_639_1" "foreignKey": "language_639_1"
} }
} }
},
"balance_balance_element_rel": {
"name": "balance_balance_element_rel",
"fields": {
"balance_balance_element_rel_id": {
"name": "balance_balance_element_rel_id",
"type": "INT",
"null": false,
"primary": true,
"autoincrement": true
},
"balance_balance_element_rel_order": {
"name": "balance_balance_element_rel_order",
"type": "INT",
"null": true
},
"balance_balance_element_rel_account": {
"name": "balance_balance_element_rel_account",
"type": "INT",
"null": false,
"foreignTable": "accounting_account",
"foreignKey": "accounting_account_id"
},
"balance_balance_element_rel_element": {
"name": "balance_balance_element_rel_element",
"type": "INT",
"null": false,
"foreignTable": "balance_balance_element",
"foreignKey": "balance_balance_element_id"
}
}
} }
} }

View File

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

View File

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

View File

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

View File

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

View File

@ -14,6 +14,7 @@ declare(strict_types=1);
namespace Modules\Balance\Models; namespace Modules\Balance\Models;
use Modules\Accounting\Models\AccountAbstractMapper;
use phpOMS\DataStorage\Database\Mapper\DataMapperFactory; use phpOMS\DataStorage\Database\Mapper\DataMapperFactory;
use phpOMS\Localization\BaseStringL11n; use phpOMS\Localization\BaseStringL11n;
@ -39,7 +40,10 @@ final class BalanceElementMapper extends DataMapperFactory
public const COLUMNS = [ public const COLUMNS = [
'balance_balance_element_id' => ['name' => 'balance_balance_element_id', 'type' => 'int', 'internal' => 'id'], 'balance_balance_element_id' => ['name' => 'balance_balance_element_id', 'type' => 'int', 'internal' => 'id'],
'balance_balance_element_code' => ['name' => 'balance_balance_element_code', 'type' => 'string', 'internal' => 'code', 'autocomplete' => true], 'balance_balance_element_code' => ['name' => 'balance_balance_element_code', 'type' => 'string', 'internal' => 'code', 'autocomplete' => true],
'balance_balance_element_formula' => ['name' => 'balance_balance_element_formula', 'type' => 'string', 'internal' => 'formula', 'autocomplete' => true],
'balance_balance_element_style' => ['name' => 'balance_balance_element_style', 'type' => 'string', 'internal' => 'style', 'autocomplete' => true],
'balance_balance_element_order' => ['name' => 'balance_balance_element_order', 'type' => 'int', 'internal' => 'order'], 'balance_balance_element_order' => ['name' => 'balance_balance_element_order', 'type' => 'int', 'internal' => 'order'],
'balance_balance_element_expanded' => ['name' => 'balance_balance_element_expanded', 'type' => 'bool', 'internal' => 'expanded'],
'balance_balance_element_parent' => ['name' => 'balance_balance_element_parent', 'type' => 'int', 'internal' => 'parent'], 'balance_balance_element_parent' => ['name' => 'balance_balance_element_parent', 'type' => 'int', 'internal' => 'parent'],
'balance_balance_element_balance' => ['name' => 'balance_balance_element_balance', 'type' => 'int', 'internal' => 'balance'], 'balance_balance_element_balance' => ['name' => 'balance_balance_element_balance', 'type' => 'int', 'internal' => 'balance'],
]; ];
@ -58,6 +62,12 @@ final class BalanceElementMapper extends DataMapperFactory
'column' => 'content', 'column' => 'content',
'external' => null, 'external' => null,
], ],
'accounts' => [
'mapper' => AccountAbstractMapper::class,
'table' => 'balance_balance_element_rel',
'self' => 'balance_balance_element_rel_element',
'external' => 'balance_balance_element_rel_account',
],
]; ];
/** /**

View File

@ -0,0 +1,31 @@
<?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 ['Balance' => [
'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',
'Diff' => 'Diff',
'Diff%' => 'Diff %',
]];

View File

@ -4,7 +4,7 @@
* *
* PHP Version 8.1 * PHP Version 8.1
* *
* @package Modules\Balance * @package Modules\PL
* @copyright Dennis Eichhorn * @copyright Dennis Eichhorn
* @license OMS License 2.0 * @license OMS License 2.0
* @version 1.0.0 * @version 1.0.0
@ -13,4 +13,19 @@
declare(strict_types=1); declare(strict_types=1);
return ['Balance' => [ return ['Balance' => [
'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',
'Diff' => 'Diff',
'Diff%' => 'Diff %',
]]; ]];

View File

@ -12,54 +12,88 @@
*/ */
declare(strict_types=1); 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 function render_elements(array $elements, ?int $parent = null) : string
{ {
$row = ''; $row = '';
$fn = 'render_elements'; $fn = 'render_elements';
$acc = 'render_accounts';
foreach ($elements as $element) { foreach ($elements as $element) {
if ($element->parent !== $parent) { if ($element->parent !== $parent) {
continue; 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 $row .= <<<ROW
<div> <div>
<div style="display: flex; flex-direction: row; align-items: center; background: #ff000099;"> <input id="iEle{$element->id}-expand" type="checkbox" class="vh"{$expanded}>
<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 class="{$element->style} data-row">
<div style="flex: 0; width: 150px; min-width: 150px; box-sizing: border-box; padding-left: 0px;">{$element->getL11n()}</div> <div class="expand-col">{$expand}</div>
<div style="flex: 1; padding: 1px;">+0.00%</div> <div class="name-col">{$element->getL11n()}</div>
<div style="flex: 1; padding: 1px;">+0.00%</div> <div>123,456.00</div>
<div style="flex: 1; padding: 1px;">+0.00%</div> <div>123,456.00</div>
<div style="flex: 1; padding: 1px;">+0.00%</div> <div>123,456.00</div>
<div style="flex: 1; padding: 1px;">+0.00%</div> <div>123,456.00</div>
<div style="flex: 1; padding: 1px;">+0.00%</div> <div>123,456.00</div>
<div style="flex: 1; padding: 1px;">+0.00%</div> <div>123,456.00</div>
<div style="flex: 1; padding: 1px;">+0.00%</div> <div>123,456.00</div>
<div style="flex: 1; padding: 1px;">+0.00%</div> <div>123,456.00</div>
<div style="flex: 1; padding: 1px;">+0.00%</div> <div>123,456.00</div>
<div style="flex: 1; padding: 1px;">+0.00%</div> <div>123,456.00</div>
<div style="flex: 1; padding: 1px;">+0.00%</div> <div>123,456.00</div>
<div style="flex: 1; padding: 1px;">+0.00%</div> <div>123,456.00</div>
<div style="flex: 1; padding: 1px;">+0.00%</div> <div class="total-col">123,456.00</div>
<div style="flex: 1; padding: 1px;">+0.00%</div> <div class="total-col">1,234.56 %</div>
<div style="flex: 1; padding: 1px;">+0.00%</div> <div class="total-col">123,456.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> </div>
<input id="iElement{$element->id}-expand" type="checkbox" class="hidden">
<div class="checked-visibility"> <div class="checked-visibility">
{$fn($elements, $element->id)} {$fn($elements, $element->id)}
{$acc($element->accounts)}
</div> </div>
</div> </div>
ROW; ROW;
@ -70,46 +104,305 @@ function render_elements(array $elements, ?int $parent = null) : string
echo $this->data['nav']->render(); echo $this->data['nav']->render();
?> ?>
<style>
div {
box-sizing: border-box;
}
<div class="row" style="font-size: 0.8rem; margin-top: 1rem;"> input:checked+div > div > .maximize {
<div class="col-xs-12"> display: none;
<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> input+div > div > .minimize {
<div style="flex: 0; width: 150px; min-width: 150px; box-sizing: border-box; text-align: center;">Category</div> display: none;
<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> input:checked+div > div > .minimize {
<div style="flex: 1; text-align: center;">4</div> display: inline-block;
<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> .title-cell {
<div style="flex: 1; text-align: center;">8</div> padding: 1px;
<div style="flex: 1; text-align: center;">9</div> text-align: center;
<div style="flex: 1; text-align: center;">10</div> width: 95px;
<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> .category {
<div style="flex: 1; text-align: center;">2</div> background: #fff;
<div style="flex: 1; text-align: center;">3</div> border-bottom: 1px solid #000 !important;
<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> .subtotal {
<div style="flex: 1; text-align: center;">7</div> background: #ffa82e;
<div style="flex: 1; text-align: center;">8</div> border-bottom: 1px solid #000 !important;
<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> .subtotal .total-col {
<div style="flex: 1; text-align: center;">12</div> background: #ffa82e;
<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> .total {
<div style="flex: 1; text-align: center;">Diff USD</div> 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> </div>
</div> </div>
<div class="row" style="font-size: 0.8rem;"> <div class="row">
<div class="col-xs-12"><?= \render_elements($this->data['elements'], null); ?></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 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-3"><?= $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-2" name="tabular-2"<?= $this->request->uri->fragment === 'c-tab-2' ? ' checked' : ''; ?>>
<div class="tab">
<div class="row">
<div class="col-xs-12">
<section class="portlet">
<div class="portlet-body">
<img style="max-width: 100%; max-height: 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>
<input type="radio" id="c-tab-3" name="tabular-2"<?= $this->request->uri->fragment === 'c-tab-3' ? ' 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">
</div>
</section>
</div>
</div>
</div>
</div>
</div> </div>

View File

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