Release 2.33.0 (#5438)
This commit is contained in:
87
composer.lock
generated
87
composer.lock
generated
@@ -775,26 +775,29 @@
|
||||
},
|
||||
{
|
||||
"name": "doctrine/deprecations",
|
||||
"version": "1.1.4",
|
||||
"version": "1.1.5",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/doctrine/deprecations.git",
|
||||
"reference": "31610dbb31faa98e6b5447b62340826f54fbc4e9"
|
||||
"reference": "459c2f5dd3d6a4633d3b5f46ee2b1c40f57d3f38"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/doctrine/deprecations/zipball/31610dbb31faa98e6b5447b62340826f54fbc4e9",
|
||||
"reference": "31610dbb31faa98e6b5447b62340826f54fbc4e9",
|
||||
"url": "https://api.github.com/repos/doctrine/deprecations/zipball/459c2f5dd3d6a4633d3b5f46ee2b1c40f57d3f38",
|
||||
"reference": "459c2f5dd3d6a4633d3b5f46ee2b1c40f57d3f38",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": "^7.1 || ^8.0"
|
||||
},
|
||||
"conflict": {
|
||||
"phpunit/phpunit": "<=7.5 || >=13"
|
||||
},
|
||||
"require-dev": {
|
||||
"doctrine/coding-standard": "^9 || ^12",
|
||||
"phpstan/phpstan": "1.4.10 || 2.0.3",
|
||||
"doctrine/coding-standard": "^9 || ^12 || ^13",
|
||||
"phpstan/phpstan": "1.4.10 || 2.1.11",
|
||||
"phpstan/phpstan-phpunit": "^1.0 || ^2",
|
||||
"phpunit/phpunit": "^7.5 || ^8.5 || ^9.5",
|
||||
"phpunit/phpunit": "^7.5 || ^8.5 || ^9.6 || ^10.5 || ^11.5 || ^12",
|
||||
"psr/log": "^1 || ^2 || ^3"
|
||||
},
|
||||
"suggest": {
|
||||
@@ -814,9 +817,9 @@
|
||||
"homepage": "https://www.doctrine-project.org/",
|
||||
"support": {
|
||||
"issues": "https://github.com/doctrine/deprecations/issues",
|
||||
"source": "https://github.com/doctrine/deprecations/tree/1.1.4"
|
||||
"source": "https://github.com/doctrine/deprecations/tree/1.1.5"
|
||||
},
|
||||
"time": "2024-12-07T21:18:45+00:00"
|
||||
"time": "2025-04-07T20:06:18+00:00"
|
||||
},
|
||||
{
|
||||
"name": "doctrine/doctrine-bundle",
|
||||
@@ -2269,16 +2272,16 @@
|
||||
},
|
||||
{
|
||||
"name": "jms/serializer",
|
||||
"version": "3.32.3",
|
||||
"version": "3.32.4",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/schmittjoh/serializer.git",
|
||||
"reference": "033c9beab9eb708509a3d400e9f0ffeb2d440e71"
|
||||
"reference": "f5c6227b2664d1e75fda65f1e6c5686a0c034b31"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/schmittjoh/serializer/zipball/033c9beab9eb708509a3d400e9f0ffeb2d440e71",
|
||||
"reference": "033c9beab9eb708509a3d400e9f0ffeb2d440e71",
|
||||
"url": "https://api.github.com/repos/schmittjoh/serializer/zipball/f5c6227b2664d1e75fda65f1e6c5686a0c034b31",
|
||||
"reference": "f5c6227b2664d1e75fda65f1e6c5686a0c034b31",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -2355,15 +2358,19 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/schmittjoh/serializer/issues",
|
||||
"source": "https://github.com/schmittjoh/serializer/tree/3.32.3"
|
||||
"source": "https://github.com/schmittjoh/serializer/tree/3.32.4"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
"url": "https://github.com/goetas",
|
||||
"type": "github"
|
||||
},
|
||||
{
|
||||
"url": "https://github.com/scyzoryck",
|
||||
"type": "github"
|
||||
}
|
||||
],
|
||||
"time": "2025-02-11T23:16:25+00:00"
|
||||
"time": "2025-04-06T18:42:47+00:00"
|
||||
},
|
||||
{
|
||||
"name": "jms/serializer-bundle",
|
||||
@@ -2456,16 +2463,16 @@
|
||||
},
|
||||
{
|
||||
"name": "kevinpapst/tabler-bundle",
|
||||
"version": "1.7.0",
|
||||
"version": "1.8.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/kevinpapst/TablerBundle.git",
|
||||
"reference": "39b5e2946c0d4fea5ad05be9b1cdad686d7035b3"
|
||||
"reference": "7cf2672d7181041efe0ccb9b1186bc0d87816735"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/kevinpapst/TablerBundle/zipball/39b5e2946c0d4fea5ad05be9b1cdad686d7035b3",
|
||||
"reference": "39b5e2946c0d4fea5ad05be9b1cdad686d7035b3",
|
||||
"url": "https://api.github.com/repos/kevinpapst/TablerBundle/zipball/7cf2672d7181041efe0ccb9b1186bc0d87816735",
|
||||
"reference": "7cf2672d7181041efe0ccb9b1186bc0d87816735",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -2515,7 +2522,7 @@
|
||||
"description": "Admin/Backend theme bundle for Symfony based on Tabler.io",
|
||||
"support": {
|
||||
"issues": "https://github.com/kevinpapst/TablerBundle/issues",
|
||||
"source": "https://github.com/kevinpapst/TablerBundle/tree/1.7.0"
|
||||
"source": "https://github.com/kevinpapst/TablerBundle/tree/1.8.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -2527,7 +2534,7 @@
|
||||
"type": "github"
|
||||
}
|
||||
],
|
||||
"time": "2025-02-13T08:14:16+00:00"
|
||||
"time": "2025-04-20T12:41:26+00:00"
|
||||
},
|
||||
{
|
||||
"name": "league/csv",
|
||||
@@ -3867,16 +3874,16 @@
|
||||
},
|
||||
{
|
||||
"name": "phpdocumentor/reflection-docblock",
|
||||
"version": "5.6.1",
|
||||
"version": "5.6.2",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/phpDocumentor/ReflectionDocBlock.git",
|
||||
"reference": "e5e784149a09bd69d9a5e3b01c5cbd2e2bd653d8"
|
||||
"reference": "92dde6a5919e34835c506ac8c523ef095a95ed62"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/e5e784149a09bd69d9a5e3b01c5cbd2e2bd653d8",
|
||||
"reference": "e5e784149a09bd69d9a5e3b01c5cbd2e2bd653d8",
|
||||
"url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/92dde6a5919e34835c506ac8c523ef095a95ed62",
|
||||
"reference": "92dde6a5919e34835c506ac8c523ef095a95ed62",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -3925,9 +3932,9 @@
|
||||
"description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.",
|
||||
"support": {
|
||||
"issues": "https://github.com/phpDocumentor/ReflectionDocBlock/issues",
|
||||
"source": "https://github.com/phpDocumentor/ReflectionDocBlock/tree/5.6.1"
|
||||
"source": "https://github.com/phpDocumentor/ReflectionDocBlock/tree/5.6.2"
|
||||
},
|
||||
"time": "2024-12-07T09:39:29+00:00"
|
||||
"time": "2025-04-13T19:20:35+00:00"
|
||||
},
|
||||
{
|
||||
"name": "phpdocumentor/type-resolver",
|
||||
@@ -10350,16 +10357,16 @@
|
||||
},
|
||||
{
|
||||
"name": "zircote/swagger-php",
|
||||
"version": "5.0.7",
|
||||
"version": "5.1.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/zircote/swagger-php.git",
|
||||
"reference": "18457fa71f753cfd4a2b21916baf329864fdfaa6"
|
||||
"reference": "a9b953c25f5bd11ea0542636936de04504496bd9"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/zircote/swagger-php/zipball/18457fa71f753cfd4a2b21916baf329864fdfaa6",
|
||||
"reference": "18457fa71f753cfd4a2b21916baf329864fdfaa6",
|
||||
"url": "https://api.github.com/repos/zircote/swagger-php/zipball/a9b953c25f5bd11ea0542636936de04504496bd9",
|
||||
"reference": "a9b953c25f5bd11ea0542636936de04504496bd9",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -10420,8 +10427,8 @@
|
||||
"homepage": "https://radebatz.net"
|
||||
}
|
||||
],
|
||||
"description": "swagger-php - Generate interactive documentation for your RESTful API using phpdoc annotations",
|
||||
"homepage": "https://github.com/zircote/swagger-php/",
|
||||
"description": "Generate interactive documentation for your RESTful API using PHP attributes (preferred) or PHPDoc annotations",
|
||||
"homepage": "https://github.com/zircote/swagger-php",
|
||||
"keywords": [
|
||||
"api",
|
||||
"json",
|
||||
@@ -10430,9 +10437,9 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/zircote/swagger-php/issues",
|
||||
"source": "https://github.com/zircote/swagger-php/tree/5.0.7"
|
||||
"source": "https://github.com/zircote/swagger-php/tree/5.1.0"
|
||||
},
|
||||
"time": "2025-03-19T03:31:11+00:00"
|
||||
"time": "2025-04-18T00:35:12+00:00"
|
||||
}
|
||||
],
|
||||
"packages-dev": [
|
||||
@@ -11267,16 +11274,16 @@
|
||||
},
|
||||
{
|
||||
"name": "phpstan/phpstan",
|
||||
"version": "2.1.11",
|
||||
"version": "2.1.12",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/phpstan/phpstan.git",
|
||||
"reference": "8ca5f79a8f63c49b2359065832a654e1ec70ac30"
|
||||
"reference": "96dde49e967c0c22812bcfa7bda4ff82c09f3b0c"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/phpstan/phpstan/zipball/8ca5f79a8f63c49b2359065832a654e1ec70ac30",
|
||||
"reference": "8ca5f79a8f63c49b2359065832a654e1ec70ac30",
|
||||
"url": "https://api.github.com/repos/phpstan/phpstan/zipball/96dde49e967c0c22812bcfa7bda4ff82c09f3b0c",
|
||||
"reference": "96dde49e967c0c22812bcfa7bda4ff82c09f3b0c",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -11321,7 +11328,7 @@
|
||||
"type": "github"
|
||||
}
|
||||
],
|
||||
"time": "2025-03-24T13:45:00+00:00"
|
||||
"time": "2025-04-16T13:19:18+00:00"
|
||||
},
|
||||
{
|
||||
"name": "phpstan/phpstan-deprecation-rules",
|
||||
|
||||
@@ -1868,6 +1868,13 @@
|
||||
'rtl' => false,
|
||||
'translation' => false,
|
||||
],
|
||||
'ta' =>
|
||||
[
|
||||
'date' => 'd/M/yy',
|
||||
'time' => 'h:mm a',
|
||||
'rtl' => false,
|
||||
'translation' => true,
|
||||
],
|
||||
'tr' =>
|
||||
[
|
||||
'date' => 'd.MM.y',
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
parameters:
|
||||
locale: en
|
||||
# can be regenerated with: bin/console kimai:reset:locales
|
||||
kimai_locales: ['ar', 'ca', 'cs', 'da', 'de', 'de_CH', 'el', 'en', 'eo', 'es', 'eu', 'fa', 'fi', 'fo', 'fr', 'he', 'hr', 'hu', 'id', 'it', 'ja', 'ko', 'nb_NO', 'nl', 'pa', 'pl', 'pt', 'pt_BR', 'ro', 'ru', 'sk', 'sl', 'sv', 'tr', 'uk', 'vi', 'zh_CN', 'zh_Hant', 'zh_Hant_TW', 'ca_AD', 'ca_ES', 'ca_FR', 'ca_IT', 'cs_CZ', 'da_DK', 'da_GL', 'de_AT', 'de_BE', 'de_CH', 'de_DE', 'de_IT', 'de_LI', 'de_LU', 'el_CY', 'el_GR', 'en_AE', 'en_AG', 'en_AI', 'en_AS', 'en_AT', 'en_AU', 'en_BB', 'en_BE', 'en_BI', 'en_BM', 'en_BS', 'en_BW', 'en_BZ', 'en_CA', 'en_CC', 'en_CH', 'en_CK', 'en_CM', 'en_CX', 'en_CY', 'en_DE', 'en_DG', 'en_DK', 'en_DM', 'en_ER', 'en_FI', 'en_FJ', 'en_FK', 'en_FM', 'en_GB', 'en_GD', 'en_GG', 'en_GH', 'en_GI', 'en_GM', 'en_GU', 'en_GY', 'en_HK', 'en_ID', 'en_IE', 'en_IL', 'en_IM', 'en_IN', 'en_IO', 'en_JE', 'en_JM', 'en_KE', 'en_KI', 'en_KN', 'en_KY', 'en_LC', 'en_LR', 'en_LS', 'en_MG', 'en_MH', 'en_MO', 'en_MP', 'en_MS', 'en_MT', 'en_MU', 'en_MV', 'en_MW', 'en_MY', 'en_NA', 'en_NF', 'en_NG', 'en_NH', 'en_NL', 'en_NR', 'en_NU', 'en_NZ', 'en_PG', 'en_PH', 'en_PK', 'en_PN', 'en_PR', 'en_PW', 'en_RH', 'en_RW', 'en_SB', 'en_SC', 'en_SD', 'en_SE', 'en_SG', 'en_SH', 'en_SI', 'en_SL', 'en_SS', 'en_SX', 'en_SZ', 'en_TC', 'en_TK', 'en_TO', 'en_TT', 'en_TV', 'en_TZ', 'en_UG', 'en_UM', 'en_US', 'en_VC', 'en_VG', 'en_VI', 'en_VU', 'en_WS', 'en_ZA', 'en_ZM', 'en_ZW', 'es_AR', 'es_BO', 'es_BR', 'es_BZ', 'es_CL', 'es_CO', 'es_CR', 'es_CU', 'es_DO', 'es_EA', 'es_EC', 'es_ES', 'es_GQ', 'es_GT', 'es_HN', 'es_IC', 'es_MX', 'es_NI', 'es_PA', 'es_PE', 'es_PH', 'es_PR', 'es_PY', 'es_SV', 'es_US', 'es_UY', 'es_VE', 'eu_ES', 'fa_AF', 'fa_IR', 'fi_FI', 'fo_DK', 'fo_FO', 'fr_BE', 'fr_BF', 'fr_BI', 'fr_BJ', 'fr_BL', 'fr_CA', 'fr_CD', 'fr_CF', 'fr_CG', 'fr_CH', 'fr_CI', 'fr_CM', 'fr_DJ', 'fr_DZ', 'fr_FR', 'fr_GA', 'fr_GF', 'fr_GN', 'fr_GP', 'fr_GQ', 'fr_HT', 'fr_KM', 'fr_LU', 'fr_MA', 'fr_MC', 'fr_MF', 'fr_MG', 'fr_ML', 'fr_MQ', 'fr_MR', 'fr_MU', 'fr_NC', 'fr_NE', 'fr_PF', 'fr_PM', 'fr_RE', 'fr_RW', 'fr_SC', 'fr_SN', 'fr_SY', 'fr_TD', 'fr_TG', 'fr_TN', 'fr_VU', 'fr_WF', 'fr_YT', 'he_IL', 'hr_BA', 'hr_HR', 'hu_HU', 'it_CH', 'it_IT', 'it_SM', 'it_VA', 'ja_JP', 'ko_CN', 'ko_KP', 'ko_KR', 'nl_AW', 'nl_BE', 'nl_BQ', 'nl_CW', 'nl_NL', 'nl_SR', 'nl_SX', 'pl_PL', 'pt_AO', 'pt_BR', 'pt_CH', 'pt_CV', 'pt_GQ', 'pt_GW', 'pt_LU', 'pt_MO', 'pt_MZ', 'pt_PT', 'pt_ST', 'pt_TL', 'ro_MD', 'ro_RO', 'ru_BY', 'ru_KG', 'ru_KZ', 'ru_MD', 'ru_RU', 'ru_UA', 'sk_SK', 'sv_AX', 'sv_FI', 'sv_SE', 'tr_CY', 'tr_TR', 'uk_UA', 'vi_VN']
|
||||
kimai_locales: ['ar', 'cs', 'da', 'de', 'de_CH', 'el', 'en', 'eo', 'es', 'eu', 'fa', 'fi', 'fo', 'fr', 'he', 'hr', 'hu', 'id', 'it', 'ja', 'ko', 'nb_NO', 'nl', 'pa', 'pl', 'pt', 'pt_BR', 'ro', 'ru', 'sk', 'sl', 'sv', 'ta', 'tr', 'uk', 'vi', 'zh_CN', 'zh_Hant', 'zh_Hant_TW', 'cs_CZ', 'da_DK', 'da_GL', 'de_AT', 'de_BE', 'de_CH', 'de_DE', 'de_IT', 'de_LI', 'de_LU', 'el_CY', 'el_GR', 'en_AE', 'en_AG', 'en_AI', 'en_AS', 'en_AT', 'en_AU', 'en_BB', 'en_BE', 'en_BI', 'en_BM', 'en_BS', 'en_BW', 'en_BZ', 'en_CA', 'en_CC', 'en_CH', 'en_CK', 'en_CM', 'en_CX', 'en_CY', 'en_DE', 'en_DG', 'en_DK', 'en_DM', 'en_ER', 'en_FI', 'en_FJ', 'en_FK', 'en_FM', 'en_GB', 'en_GD', 'en_GG', 'en_GH', 'en_GI', 'en_GM', 'en_GU', 'en_GY', 'en_HK', 'en_ID', 'en_IE', 'en_IL', 'en_IM', 'en_IN', 'en_IO', 'en_JE', 'en_JM', 'en_KE', 'en_KI', 'en_KN', 'en_KY', 'en_LC', 'en_LR', 'en_LS', 'en_MG', 'en_MH', 'en_MO', 'en_MP', 'en_MS', 'en_MT', 'en_MU', 'en_MV', 'en_MW', 'en_MY', 'en_NA', 'en_NF', 'en_NG', 'en_NH', 'en_NL', 'en_NR', 'en_NU', 'en_NZ', 'en_PG', 'en_PH', 'en_PK', 'en_PN', 'en_PR', 'en_PW', 'en_RH', 'en_RW', 'en_SB', 'en_SC', 'en_SD', 'en_SE', 'en_SG', 'en_SH', 'en_SI', 'en_SL', 'en_SS', 'en_SX', 'en_SZ', 'en_TC', 'en_TK', 'en_TO', 'en_TT', 'en_TV', 'en_TZ', 'en_UG', 'en_UM', 'en_US', 'en_VC', 'en_VG', 'en_VI', 'en_VU', 'en_WS', 'en_ZA', 'en_ZM', 'en_ZW', 'es_AR', 'es_BO', 'es_BR', 'es_BZ', 'es_CL', 'es_CO', 'es_CR', 'es_CU', 'es_DO', 'es_EA', 'es_EC', 'es_ES', 'es_GQ', 'es_GT', 'es_HN', 'es_IC', 'es_MX', 'es_NI', 'es_PA', 'es_PE', 'es_PH', 'es_PR', 'es_PY', 'es_SV', 'es_US', 'es_UY', 'es_VE', 'eu_ES', 'fa_AF', 'fa_IR', 'fi_FI', 'fo_DK', 'fo_FO', 'fr_BE', 'fr_BF', 'fr_BI', 'fr_BJ', 'fr_BL', 'fr_CA', 'fr_CD', 'fr_CF', 'fr_CG', 'fr_CH', 'fr_CI', 'fr_CM', 'fr_DJ', 'fr_DZ', 'fr_FR', 'fr_GA', 'fr_GF', 'fr_GN', 'fr_GP', 'fr_GQ', 'fr_HT', 'fr_KM', 'fr_LU', 'fr_MA', 'fr_MC', 'fr_MF', 'fr_MG', 'fr_ML', 'fr_MQ', 'fr_MR', 'fr_MU', 'fr_NC', 'fr_NE', 'fr_PF', 'fr_PM', 'fr_RE', 'fr_RW', 'fr_SC', 'fr_SN', 'fr_SY', 'fr_TD', 'fr_TG', 'fr_TN', 'fr_VU', 'fr_WF', 'fr_YT', 'he_IL', 'hr_BA', 'hr_HR', 'hu_HU', 'it_CH', 'it_IT', 'it_SM', 'it_VA', 'ja_JP', 'ko_CN', 'ko_KP', 'ko_KR', 'nl_AW', 'nl_BE', 'nl_BQ', 'nl_CW', 'nl_NL', 'nl_SR', 'nl_SX', 'pl_PL', 'pt_AO', 'pt_BR', 'pt_CH', 'pt_CV', 'pt_GQ', 'pt_GW', 'pt_LU', 'pt_MO', 'pt_MZ', 'pt_PT', 'pt_ST', 'pt_TL', 'ro_MD', 'ro_RO', 'ru_BY', 'ru_KG', 'ru_KZ', 'ru_MD', 'ru_RU', 'ru_UA', 'sk_SK', 'sv_AX', 'sv_FI', 'sv_SE', 'tr_CY', 'tr_TR', 'uk_UA', 'vi_VN']
|
||||
|
||||
services:
|
||||
# default configuration for services in *this* file
|
||||
|
||||
60
phpstan.neon
60
phpstan.neon
@@ -2097,11 +2097,6 @@ parameters:
|
||||
count: 1
|
||||
path: src/Form/TimesheetAdminEditForm.php
|
||||
|
||||
-
|
||||
message: "#^Cannot call method format\\(\\) on mixed\\.$#"
|
||||
count: 4
|
||||
path: src/Form/TimesheetEditForm.php
|
||||
|
||||
-
|
||||
message: "#^Cannot call method getEnd\\(\\) on App\\\\Entity\\\\Timesheet\\|null\\.$#"
|
||||
count: 2
|
||||
@@ -2122,11 +2117,6 @@ parameters:
|
||||
count: 1
|
||||
path: src/Form/TimesheetEditForm.php
|
||||
|
||||
-
|
||||
message: "#^Cannot clone non\\-object variable \\$end of type mixed\\.$#"
|
||||
count: 1
|
||||
path: src/Form/TimesheetEditForm.php
|
||||
|
||||
-
|
||||
message: "#^Method App\\\\Form\\\\TimesheetEditForm\\:\\:addActivity\\(\\) has parameter \\$options with no value type specified in iterable type array\\.$#"
|
||||
count: 1
|
||||
@@ -3027,46 +3017,6 @@ parameters:
|
||||
count: 1
|
||||
path: src/Invoice/Hydrator/InvoiceModelCustomerHydrator.php
|
||||
|
||||
-
|
||||
message: "#^Cannot call method getAddress\\(\\) on App\\\\Entity\\\\InvoiceTemplate\\|null\\.$#"
|
||||
count: 1
|
||||
path: src/Invoice/Hydrator/InvoiceModelDefaultHydrator.php
|
||||
|
||||
-
|
||||
message: "#^Cannot call method getCompany\\(\\) on App\\\\Entity\\\\InvoiceTemplate\\|null\\.$#"
|
||||
count: 1
|
||||
path: src/Invoice/Hydrator/InvoiceModelDefaultHydrator.php
|
||||
|
||||
-
|
||||
message: "#^Cannot call method getContact\\(\\) on App\\\\Entity\\\\InvoiceTemplate\\|null\\.$#"
|
||||
count: 1
|
||||
path: src/Invoice/Hydrator/InvoiceModelDefaultHydrator.php
|
||||
|
||||
-
|
||||
message: "#^Cannot call method getDueDays\\(\\) on App\\\\Entity\\\\InvoiceTemplate\\|null\\.$#"
|
||||
count: 1
|
||||
path: src/Invoice/Hydrator/InvoiceModelDefaultHydrator.php
|
||||
|
||||
-
|
||||
message: "#^Cannot call method getLanguage\\(\\) on App\\\\Entity\\\\InvoiceTemplate\\|null\\.$#"
|
||||
count: 1
|
||||
path: src/Invoice/Hydrator/InvoiceModelDefaultHydrator.php
|
||||
|
||||
-
|
||||
message: "#^Cannot call method getName\\(\\) on App\\\\Entity\\\\InvoiceTemplate\\|null\\.$#"
|
||||
count: 1
|
||||
path: src/Invoice/Hydrator/InvoiceModelDefaultHydrator.php
|
||||
|
||||
-
|
||||
message: "#^Cannot call method getPaymentDetails\\(\\) on App\\\\Entity\\\\InvoiceTemplate\\|null\\.$#"
|
||||
count: 1
|
||||
path: src/Invoice/Hydrator/InvoiceModelDefaultHydrator.php
|
||||
|
||||
-
|
||||
message: "#^Cannot call method getPaymentTerms\\(\\) on App\\\\Entity\\\\InvoiceTemplate\\|null\\.$#"
|
||||
count: 1
|
||||
path: src/Invoice/Hydrator/InvoiceModelDefaultHydrator.php
|
||||
|
||||
-
|
||||
message: "#^Cannot call method getSubtotal\\(\\) on App\\\\Invoice\\\\CalculatorInterface\\|null\\.$#"
|
||||
count: 1
|
||||
@@ -3082,11 +3032,6 @@ parameters:
|
||||
count: 2
|
||||
path: src/Invoice/Hydrator/InvoiceModelDefaultHydrator.php
|
||||
|
||||
-
|
||||
message: "#^Cannot call method getTitle\\(\\) on App\\\\Entity\\\\InvoiceTemplate\\|null\\.$#"
|
||||
count: 1
|
||||
path: src/Invoice/Hydrator/InvoiceModelDefaultHydrator.php
|
||||
|
||||
-
|
||||
message: "#^Cannot call method getTotal\\(\\) on App\\\\Invoice\\\\CalculatorInterface\\|null\\.$#"
|
||||
count: 1
|
||||
@@ -3097,11 +3042,6 @@ parameters:
|
||||
count: 1
|
||||
path: src/Invoice/Hydrator/InvoiceModelDefaultHydrator.php
|
||||
|
||||
-
|
||||
message: "#^Cannot call method getVatId\\(\\) on App\\\\Entity\\\\InvoiceTemplate\\|null\\.$#"
|
||||
count: 1
|
||||
path: src/Invoice/Hydrator/InvoiceModelDefaultHydrator.php
|
||||
|
||||
-
|
||||
message: "#^Method App\\\\Invoice\\\\Hydrator\\\\InvoiceModelDefaultHydrator\\:\\:hydrate\\(\\) return type has no value type specified in iterable type array\\.$#"
|
||||
count: 1
|
||||
|
||||
@@ -120,12 +120,23 @@ class ActivityService
|
||||
// we cannot use max(number) because a varchar column returns unexpected results
|
||||
$start = $this->repository->countActivity();
|
||||
$i = 0;
|
||||
$createDate = new \DateTimeImmutable();
|
||||
|
||||
do {
|
||||
$start++;
|
||||
|
||||
$numberGenerator = new NumberGenerator($format, function (string $originalFormat, string $format, int $increaseBy) use ($start): string|int {
|
||||
$numberGenerator = new NumberGenerator($format, function (string $originalFormat, string $format, int $increaseBy) use ($start, $createDate): string|int {
|
||||
return match ($format) {
|
||||
'Y' => $createDate->format('Y'),
|
||||
'y' => $createDate->format('y'),
|
||||
'M' => $createDate->format('m'),
|
||||
'm' => $createDate->format('n'),
|
||||
'D' => $createDate->format('d'),
|
||||
'd' => $createDate->format('j'),
|
||||
'YY' => (int) $createDate->format('Y') + $increaseBy,
|
||||
'yy' => (int) $createDate->format('y') + $increaseBy,
|
||||
'MM' => (int) $createDate->format('m') + $increaseBy,
|
||||
'DD' => (int) $createDate->format('d') + $increaseBy,
|
||||
'ac' => $start + $increaseBy,
|
||||
default => $originalFormat,
|
||||
};
|
||||
|
||||
@@ -39,7 +39,7 @@ final class RegenerateLocalesCommand extends Command
|
||||
*
|
||||
* @var string[]
|
||||
*/
|
||||
private array $noRegionCode = ['ar', 'id', 'pa', 'sl', 'ca'];
|
||||
private array $noRegionCode = ['ar', 'id', 'pa', 'sl', 'ca', 'ta'];
|
||||
/**
|
||||
* A list of locales that will be activated, no matter if translation files exist for them.
|
||||
*
|
||||
@@ -47,11 +47,11 @@ final class RegenerateLocalesCommand extends Command
|
||||
*/
|
||||
private array $addLocaleToList = ['zh_Hant_TW'];
|
||||
/**
|
||||
* A list of locales that will NOT be activated, as no translations exist by now.
|
||||
* A list of locales that will NOT be activated, as not enough translations exist by now.
|
||||
*
|
||||
* @var string[]
|
||||
*/
|
||||
private array $skipLocale = ['ca'];
|
||||
private array $skipLocale = ['ca', 'et'];
|
||||
|
||||
public function __construct(
|
||||
private readonly string $projectDirectory,
|
||||
@@ -86,6 +86,7 @@ final class RegenerateLocalesCommand extends Command
|
||||
$firstLevelLocales[] = $l;
|
||||
}
|
||||
$firstLevelLocales = array_unique(array_merge($firstLevelLocales, $this->addLocaleToList));
|
||||
|
||||
$io->title('First level locales found');
|
||||
$io->writeln(implode('|', $firstLevelLocales));
|
||||
|
||||
@@ -198,8 +199,23 @@ final class RegenerateLocalesCommand extends Command
|
||||
|
||||
// in the future this list should be reduced to the list of available translations, but for a long time users
|
||||
// could choose from the entire list of all locales, so we likely have to keep that forever ...
|
||||
$io->title('List of "kimai_locales" for services.yaml');
|
||||
$io->writeln("['" . implode("', '", $locales) . "']");
|
||||
$listOfLocales = array_map(fn ($locale) => "'$locale'", $locales);
|
||||
$filename = 'config/services.yaml';
|
||||
$targetFile = $this->projectDirectory . DIRECTORY_SEPARATOR . $filename;
|
||||
$content = file_get_contents($targetFile);
|
||||
if ($content === false) {
|
||||
$io->error('Failed reading configuration file at ' . $filename);
|
||||
} else {
|
||||
$content = preg_replace(
|
||||
'/^(\s*kimai_locales:\s*\[).*?(\])$/m',
|
||||
'${1}' . implode(', ', $listOfLocales) . '${2}',
|
||||
$content
|
||||
);
|
||||
|
||||
file_put_contents($targetFile, $content);
|
||||
|
||||
$io->success('Replaced locale definitions in: ' . $filename);
|
||||
}
|
||||
|
||||
ksort($appLocales);
|
||||
|
||||
|
||||
@@ -17,11 +17,11 @@ final class Constants
|
||||
/**
|
||||
* The current release version
|
||||
*/
|
||||
public const VERSION = '2.32.0';
|
||||
public const VERSION = '2.33.0';
|
||||
/**
|
||||
* The current release: major * 10000 + minor * 100 + patch
|
||||
*/
|
||||
public const VERSION_ID = 23200;
|
||||
public const VERSION_ID = 23300;
|
||||
/**
|
||||
* The software name
|
||||
*/
|
||||
|
||||
@@ -63,6 +63,8 @@ final class ContractController extends AbstractController
|
||||
|
||||
/** @var \DateTime $yearDate */
|
||||
$yearDate = $values->getDate();
|
||||
// make sure we use the correct datetime for the selected user
|
||||
$yearDate = $this->getDateTimeFactory($profile)->createStartOfYear($yearDate);
|
||||
$year = $workingTimeService->getYear($profile, $yearDate, $now);
|
||||
|
||||
$page = new PageSetup('work_times');
|
||||
|
||||
@@ -137,12 +137,23 @@ final class CustomerService
|
||||
// we cannot use max(number) because a varchar column returns unexpected results
|
||||
$start = $this->repository->countCustomer();
|
||||
$i = 0;
|
||||
$createDate = new \DateTimeImmutable();
|
||||
|
||||
do {
|
||||
$start++;
|
||||
|
||||
$numberGenerator = new NumberGenerator($format, function (string $originalFormat, string $format, int $increaseBy) use ($start): string|int {
|
||||
$numberGenerator = new NumberGenerator($format, function (string $originalFormat, string $format, int $increaseBy) use ($start, $createDate): string|int {
|
||||
return match ($format) {
|
||||
'Y' => $createDate->format('Y'),
|
||||
'y' => $createDate->format('y'),
|
||||
'M' => $createDate->format('m'),
|
||||
'm' => $createDate->format('n'),
|
||||
'D' => $createDate->format('d'),
|
||||
'd' => $createDate->format('j'),
|
||||
'YY' => (int) $createDate->format('Y') + $increaseBy,
|
||||
'yy' => (int) $createDate->format('y') + $increaseBy,
|
||||
'MM' => (int) $createDate->format('m') + $increaseBy,
|
||||
'DD' => (int) $createDate->format('d') + $increaseBy,
|
||||
'cc' => $start + $increaseBy,
|
||||
default => $originalFormat,
|
||||
};
|
||||
|
||||
@@ -12,6 +12,7 @@ namespace App\Export\Base;
|
||||
use App\Entity\ExportableItem;
|
||||
use App\Export\ExportFilename;
|
||||
use App\Export\Package\CellFormatter\DateStringFormatter;
|
||||
use App\Export\Package\CellFormatter\DurationPlainFormatter;
|
||||
use App\Export\Package\SpoutSpreadsheet;
|
||||
use App\Export\RendererInterface;
|
||||
use App\Export\TimesheetExportInterface;
|
||||
@@ -71,6 +72,7 @@ final class CsvRenderer implements RendererInterface, TimesheetExportInterface
|
||||
$spreadsheet->open($filename);
|
||||
|
||||
$this->spreadsheetRenderer->registerFormatter('date', new DateStringFormatter());
|
||||
$this->spreadsheetRenderer->registerFormatter('duration', new DurationPlainFormatter());
|
||||
$this->spreadsheetRenderer->writeSpreadsheet($spreadsheet, $exportItems, $query);
|
||||
|
||||
return new \SplFileInfo($filename);
|
||||
|
||||
@@ -105,7 +105,7 @@ final class SpreadsheetRenderer
|
||||
$formula = null;
|
||||
if (\in_array($column->getName(), $totalColumns)) {
|
||||
$columnName = $columnNames[$totalColumn - 1];
|
||||
$formula = \sprintf('=SUM(%s2:%s%s)', $columnName, $columnName, $currentRow);
|
||||
$formula = \sprintf('=SUBTOTAL(9,%s2:%s%s)', $columnName, $columnName, $currentRow);
|
||||
}
|
||||
$totalRow[] = $formula;
|
||||
$totalColumn++;
|
||||
|
||||
15
src/Export/Package/CellFormatter/CellWithFormatInterface.php
Normal file
15
src/Export/Package/CellFormatter/CellWithFormatInterface.php
Normal file
@@ -0,0 +1,15 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Kimai time-tracking app.
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace App\Export\Package\CellFormatter;
|
||||
|
||||
interface CellWithFormatInterface
|
||||
{
|
||||
public function getFormat(): string;
|
||||
}
|
||||
@@ -9,7 +9,7 @@
|
||||
|
||||
namespace App\Export\Package\CellFormatter;
|
||||
|
||||
final class DateFormatter implements CellFormatterInterface
|
||||
final class DateFormatter implements CellFormatterInterface, CellWithFormatInterface
|
||||
{
|
||||
public function formatValue(mixed $value): mixed
|
||||
{
|
||||
@@ -23,4 +23,9 @@ final class DateFormatter implements CellFormatterInterface
|
||||
|
||||
throw new \InvalidArgumentException('Only DateTimeInterface can be formatted');
|
||||
}
|
||||
|
||||
public function getFormat(): string
|
||||
{
|
||||
return 'yyyy-mm-dd';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,23 +9,34 @@
|
||||
|
||||
namespace App\Export\Package\CellFormatter;
|
||||
|
||||
use App\Utils\Duration;
|
||||
|
||||
final class DurationFormatter implements CellFormatterInterface
|
||||
final class DurationFormatter implements CellFormatterInterface, CellWithFormatInterface
|
||||
{
|
||||
private Duration $duration;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->duration = new Duration();
|
||||
}
|
||||
|
||||
public function formatValue(mixed $value): mixed
|
||||
{
|
||||
if (is_numeric($value)) {
|
||||
return $this->duration->format((int) $value);
|
||||
if (!is_numeric($value) || (int) $value === 0) {
|
||||
return new \DateInterval('PT0S');
|
||||
}
|
||||
|
||||
return $this->duration->format(0);
|
||||
$value = (int) $value;
|
||||
|
||||
$seconds = abs($value);
|
||||
$hours = intdiv($seconds, 3600);
|
||||
$seconds %= 3600;
|
||||
$minutes = intdiv($seconds, 60);
|
||||
$seconds %= 60;
|
||||
|
||||
$intervalSpec = \sprintf('PT%dH%dM%dS', $hours, $minutes, $seconds);
|
||||
$interval = new \DateInterval($intervalSpec);
|
||||
|
||||
if ($value < 0) {
|
||||
$interval->invert = 1;
|
||||
}
|
||||
|
||||
return $interval;
|
||||
}
|
||||
|
||||
public function getFormat(): string
|
||||
{
|
||||
return '[hh]:mm:ss';
|
||||
}
|
||||
}
|
||||
|
||||
37
src/Export/Package/CellFormatter/DurationPlainFormatter.php
Normal file
37
src/Export/Package/CellFormatter/DurationPlainFormatter.php
Normal file
@@ -0,0 +1,37 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Kimai time-tracking app.
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace App\Export\Package\CellFormatter;
|
||||
|
||||
final class DurationPlainFormatter implements CellFormatterInterface
|
||||
{
|
||||
public function formatValue(mixed $value): mixed
|
||||
{
|
||||
if (!is_numeric($value) || (int) $value === 0) {
|
||||
return '0:00:00';
|
||||
}
|
||||
|
||||
$value = (int) $value;
|
||||
|
||||
$seconds = abs($value);
|
||||
$hours = intdiv($seconds, 3600);
|
||||
$seconds %= 3600;
|
||||
$minutes = intdiv($seconds, 60);
|
||||
$seconds %= 60;
|
||||
|
||||
$intervalSpec = \sprintf('PT%dH%dM%dS', $hours, $minutes, $seconds);
|
||||
$interval = new \DateInterval($intervalSpec);
|
||||
|
||||
if ($value < 0) {
|
||||
$interval->invert = 1;
|
||||
}
|
||||
|
||||
return $interval->format('%r%h:%I:%S');
|
||||
}
|
||||
}
|
||||
@@ -11,6 +11,7 @@ namespace App\Export\Package;
|
||||
|
||||
use App\Entity\ExportableItem;
|
||||
use App\Export\Package\CellFormatter\CellFormatterInterface;
|
||||
use App\Export\Package\CellFormatter\CellWithFormatInterface;
|
||||
|
||||
class Column
|
||||
{
|
||||
@@ -71,4 +72,13 @@ class Column
|
||||
{
|
||||
return $this->header ?? $this->name;
|
||||
}
|
||||
|
||||
public function getFormat(): ?string
|
||||
{
|
||||
if ($this->formatter instanceof CellWithFormatInterface) {
|
||||
return $this->formatter->getFormat();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,7 +26,8 @@ use Symfony\Contracts\Translation\TranslatorInterface;
|
||||
|
||||
class SpoutSpreadsheet implements SpreadsheetPackage
|
||||
{
|
||||
private Style $dateStyle;
|
||||
/** @var array<int, Style|null> */
|
||||
private array $styles = [];
|
||||
|
||||
public function __construct(
|
||||
private readonly WriterInterface $writer,
|
||||
@@ -34,7 +35,6 @@ class SpoutSpreadsheet implements SpreadsheetPackage
|
||||
)
|
||||
{
|
||||
$this->writer->setCreator(Constants::SOFTWARE);
|
||||
$this->dateStyle = (new Style())->setFormat('yyyy-mm-dd');
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -48,9 +48,15 @@ class SpoutSpreadsheet implements SpreadsheetPackage
|
||||
}
|
||||
|
||||
$tmp = [];
|
||||
$i = 0;
|
||||
foreach ($columns as $column) {
|
||||
$title = $this->translator->trans($column->getHeader());
|
||||
$tmp[] = Cell::fromValue($title);
|
||||
$style = null;
|
||||
if ($column->getFormat() !== null) {
|
||||
$style = (new Style())->setFormat($column->getFormat());
|
||||
}
|
||||
$this->styles[$i++] = $style;
|
||||
}
|
||||
|
||||
$style = new Style();
|
||||
@@ -100,12 +106,9 @@ class SpoutSpreadsheet implements SpreadsheetPackage
|
||||
}
|
||||
|
||||
$tmp = [];
|
||||
$i = 0;
|
||||
foreach ($columns as $column) {
|
||||
if ($column instanceof \DateTimeInterface) {
|
||||
$tmp[] = Cell::fromValue($column, $this->dateStyle);
|
||||
} else {
|
||||
$tmp[] = Cell::fromValue($column); // @phpstan-ignore argument.type
|
||||
}
|
||||
$tmp[] = Cell::fromValue($column, $this->styles[$i++]); // @phpstan-ignore argument.type
|
||||
}
|
||||
|
||||
$this->writer->addRow(new Row($tmp, $style));
|
||||
|
||||
@@ -207,15 +207,22 @@ class TimesheetEditForm extends AbstractType
|
||||
|
||||
/** @var \DateTime|null $date */
|
||||
$date = $event->getForm()->get('begin_date')->getData();
|
||||
/** @var \DateTime|null $time */
|
||||
$time = $event->getForm()->get('begin_time')->getData();
|
||||
|
||||
if ($date === null || $time === null) {
|
||||
return;
|
||||
}
|
||||
|
||||
// if the user did not change the time, make sure to keep the seconds
|
||||
$seconds = 0;
|
||||
if ($data->getBegin()?->format('H:i') === $time->format('H:i')) {
|
||||
$seconds = $data->getBegin()->format('s') ?? 0;
|
||||
}
|
||||
|
||||
// mutable datetime are a problem for doctrine
|
||||
$newDate = clone $date;
|
||||
$newDate->setTime($time->format('H'), $time->format('i'));
|
||||
$newDate->setTime((int) $time->format('H'), (int) $time->format('i'), (int) $seconds);
|
||||
|
||||
if ($data->getBegin() === null || $data->getBegin()->getTimestamp() !== $newDate->getTimestamp()) {
|
||||
$data->setBegin($newDate);
|
||||
@@ -251,6 +258,7 @@ class TimesheetEditForm extends AbstractType
|
||||
$timesheet = $event->getData();
|
||||
$oldEnd = $timesheet->getEnd();
|
||||
|
||||
/** @var \DateTime|null $end */
|
||||
$end = $event->getForm()->get('end_time')->getData();
|
||||
if ($end === null || $end === false) {
|
||||
$timesheet->setEnd(null);
|
||||
@@ -267,8 +275,15 @@ class TimesheetEditForm extends AbstractType
|
||||
if ($time === null) {
|
||||
throw new \Exception('Cannot work with timesheets without start time');
|
||||
}
|
||||
|
||||
// if the user did not change the time, make sure to keep the seconds
|
||||
$seconds = 0;
|
||||
if ($oldEnd !== null && $oldEnd->format('H:i') === $end->format('H:i')) {
|
||||
$seconds = $oldEnd->format('s') ?? 0;
|
||||
}
|
||||
|
||||
$newEnd = clone $time;
|
||||
$newEnd->setTime($end->format('H'), $end->format('i'));
|
||||
$newEnd->setTime((int) $end->format('H'), (int) $end->format('i'), (int) $seconds);
|
||||
|
||||
if ($newEnd < $time) {
|
||||
$newEnd->modify('+ 1 day');
|
||||
|
||||
@@ -18,11 +18,17 @@ final class InvoiceModelDefaultHydrator implements InvoiceModelHydrator
|
||||
|
||||
public function hydrate(InvoiceModel $model): array
|
||||
{
|
||||
$template = $model->getTemplate();
|
||||
if ($template === null) {
|
||||
throw new \InvalidArgumentException('InvoiceModel needs a template');
|
||||
}
|
||||
|
||||
$currency = $model->getCurrency();
|
||||
$tax = $model->getCalculator()->getTax();
|
||||
$total = $model->getCalculator()->getTotal();
|
||||
$subtotal = $model->getCalculator()->getSubtotal();
|
||||
$formatter = $model->getFormatter();
|
||||
$language = $template->getLanguage();
|
||||
|
||||
$values = [
|
||||
'invoice.due_date' => $formatter->getFormattedDateTime($model->getDueDate()),
|
||||
@@ -31,7 +37,7 @@ final class InvoiceModelDefaultHydrator implements InvoiceModelHydrator
|
||||
'invoice.date_process' => $model->getInvoiceDate()->format(self::DATE_PROCESS_FORMAT), // since 2.14
|
||||
'invoice.number' => $model->getInvoiceNumber(),
|
||||
'invoice.currency' => $currency,
|
||||
'invoice.language' => $model->getTemplate()->getLanguage(), // since 1.9
|
||||
'invoice.language' => $language, // since 1.9
|
||||
'invoice.currency_symbol' => $formatter->getCurrencySymbol($currency),
|
||||
'invoice.vat' => $model->getCalculator()->getVat(),
|
||||
'invoice.tax_hide' => $model->isHideZeroTax() && $tax === 0.00,
|
||||
@@ -47,15 +53,17 @@ final class InvoiceModelDefaultHydrator implements InvoiceModelHydrator
|
||||
'invoice.subtotal_nc' => $formatter->getFormattedMoney($subtotal, $currency, false),
|
||||
'invoice.subtotal_plain' => $subtotal,
|
||||
|
||||
'template.name' => $model->getTemplate()->getName() ?? '',
|
||||
'template.company' => $model->getTemplate()->getCompany() ?? '',
|
||||
'template.address' => $model->getTemplate()->getAddress() ?? '',
|
||||
'template.title' => $model->getTemplate()->getTitle() ?? '',
|
||||
'template.payment_terms' => $model->getTemplate()->getPaymentTerms() ?? '',
|
||||
'template.due_days' => $model->getTemplate()->getDueDays(),
|
||||
'template.vat_id' => $model->getTemplate()->getVatId() ?? '',
|
||||
'template.contact' => $model->getTemplate()->getContact() ?? '',
|
||||
'template.payment_details' => $model->getTemplate()->getPaymentDetails() ?? '',
|
||||
'template.name' => $template->getName() ?? '',
|
||||
'template.company' => $template->getCompany() ?? '',
|
||||
'template.address' => $template->getAddress() ?? '',
|
||||
'template.title' => $template->getTitle() ?? '',
|
||||
'template.payment_terms' => $template->getPaymentTerms() ?? '',
|
||||
'template.due_days' => $template->getDueDays(),
|
||||
'template.vat_id' => $template->getVatId() ?? '',
|
||||
'template.contact' => $template->getContact() ?? '',
|
||||
'template.country' => null,
|
||||
'template.country_name' => null,
|
||||
'template.payment_details' => $template->getPaymentDetails() ?? '',
|
||||
|
||||
'query.begin' => '',
|
||||
'query.begin_day' => '',
|
||||
|
||||
@@ -128,12 +128,23 @@ final class ProjectService
|
||||
// we cannot use max(number) because a varchar column returns unexpected results
|
||||
$start = $this->repository->countProject();
|
||||
$i = 0;
|
||||
$createDate = new \DateTimeImmutable();
|
||||
|
||||
do {
|
||||
$start++;
|
||||
|
||||
$numberGenerator = new NumberGenerator($format, function (string $originalFormat, string $format, int $increaseBy) use ($start): string|int {
|
||||
$numberGenerator = new NumberGenerator($format, function (string $originalFormat, string $format, int $increaseBy) use ($start, $createDate): string|int {
|
||||
return match ($format) {
|
||||
'Y' => $createDate->format('Y'),
|
||||
'y' => $createDate->format('y'),
|
||||
'M' => $createDate->format('m'),
|
||||
'm' => $createDate->format('n'),
|
||||
'D' => $createDate->format('d'),
|
||||
'd' => $createDate->format('j'),
|
||||
'YY' => (int) $createDate->format('Y') + $increaseBy,
|
||||
'yy' => (int) $createDate->format('y') + $increaseBy,
|
||||
'MM' => (int) $createDate->format('m') + $increaseBy,
|
||||
'DD' => (int) $createDate->format('d') + $increaseBy,
|
||||
'pc' => $start + $increaseBy,
|
||||
default => $originalFormat,
|
||||
};
|
||||
|
||||
@@ -48,8 +48,14 @@ final class DateTimeFactory
|
||||
return $date;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function getStartOfLastMonth(): DateTimeInterface
|
||||
{
|
||||
@trigger_error('The method "DateTimeFactory::getStartOfLastMonth()" will be removed soon', E_USER_DEPRECATED);
|
||||
|
||||
$date = $this->createDateTime('first day of -1 month');
|
||||
$date = $date->setTime(0, 0, 0);
|
||||
|
||||
@@ -66,9 +72,13 @@ final class DateTimeFactory
|
||||
return $this->createDateTime($date);
|
||||
}
|
||||
|
||||
return DateTime::createFromInterface($date);
|
||||
return $this->createDateTime($date->format('Y-m-d H:i:s'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
private function createDate(DateTimeInterface|string|null $date = null): \DateTimeImmutable
|
||||
{
|
||||
if ($date === null) {
|
||||
@@ -79,7 +89,7 @@ final class DateTimeFactory
|
||||
return $this->create($date);
|
||||
}
|
||||
|
||||
return \DateTimeImmutable::createFromInterface($date);
|
||||
return $this->create($date->format('Y-m-d H:i:s'));
|
||||
}
|
||||
|
||||
public function getStartOfWeek(DateTimeInterface|string|null $date = null): DateTime
|
||||
@@ -125,8 +135,14 @@ final class DateTimeFactory
|
||||
return $date;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function getEndOfLastMonth(): DateTimeInterface
|
||||
{
|
||||
@trigger_error('The method "DateTimeFactory::getEndOfLastMonth()" will be removed soon', E_USER_DEPRECATED);
|
||||
|
||||
$date = $this->createDateTime('last day of -1 month');
|
||||
$date = $date->setTime(23, 59, 59);
|
||||
|
||||
@@ -152,15 +168,27 @@ final class DateTimeFactory
|
||||
return new \DateTimeImmutable($datetime, $this->getTimezone());
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function createStartOfDay(DateTimeInterface|string|null $date = null): \DateTimeImmutable
|
||||
{
|
||||
@trigger_error('The method "DateTimeFactory::createStartOfDay()" will be removed soon', E_USER_DEPRECATED);
|
||||
|
||||
$date = $this->createDate($date);
|
||||
|
||||
return $date->modify('00:00:00');
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated
|
||||
* @codeCoverageIgnore
|
||||
*/
|
||||
public function createEndOfDay(DateTimeInterface|string|null $date = null): \DateTimeImmutable
|
||||
{
|
||||
@trigger_error('The method "DateTimeFactory::createEndOfDay()" will be removed soon', E_USER_DEPRECATED);
|
||||
|
||||
$date = $this->createDate($date);
|
||||
|
||||
return $date->modify('23:59:59');
|
||||
|
||||
@@ -97,9 +97,9 @@ final class ThemeExtension implements RuntimeExtensionInterface
|
||||
return $class;
|
||||
}
|
||||
|
||||
public function generateTitle(?string $prefix = null, string $delimiter = ' – '): string
|
||||
public function generateTitle(): string
|
||||
{
|
||||
return ($prefix ?? '') . Constants::SOFTWARE;
|
||||
return Constants::SOFTWARE;
|
||||
}
|
||||
|
||||
public function colorize(?string $color, ?string $identifier = null): string
|
||||
|
||||
@@ -35,7 +35,8 @@ class ActivityServiceTest extends TestCase
|
||||
private function getSut(
|
||||
?EventDispatcherInterface $dispatcher = null,
|
||||
?ValidatorInterface $validator = null,
|
||||
?ActivityRepository $repository = null
|
||||
?ActivityRepository $repository = null,
|
||||
array $configuration = []
|
||||
): ActivityService {
|
||||
if ($repository === null) {
|
||||
$repository = $this->createMock(ActivityRepository::class);
|
||||
@@ -50,7 +51,7 @@ class ActivityServiceTest extends TestCase
|
||||
$validator->method('validate')->willReturn(new ConstraintViolationList());
|
||||
}
|
||||
|
||||
$configuration = SystemConfigurationFactory::createStub(['activity' => []]);
|
||||
$configuration = SystemConfigurationFactory::createStub(['activity' => $configuration]);
|
||||
|
||||
$service = new ActivityService($repository, $configuration, $dispatcher, $validator);
|
||||
|
||||
@@ -155,4 +156,71 @@ class ActivityServiceTest extends TestCase
|
||||
$project = $sut->createNewActivity();
|
||||
self::assertNull($project->getProject());
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider getTestData
|
||||
*/
|
||||
public function testActivityNumber(string $format, int|string $expected): void
|
||||
{
|
||||
$sut = $this->getSut(null, null, null, ['number_format' => $format]);
|
||||
$activity = $sut->createNewActivity();
|
||||
|
||||
self::assertEquals((string) $expected, $activity->getNumber());
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<int, array<int, string|\DateTime|int>>
|
||||
*/
|
||||
public static function getTestData(): array
|
||||
{
|
||||
$dateTime = new \DateTime();
|
||||
|
||||
$yearLong = (int) $dateTime->format('Y');
|
||||
$yearShort = (int) $dateTime->format('y');
|
||||
$monthLong = $dateTime->format('m');
|
||||
$monthShort = (int) $dateTime->format('n');
|
||||
$dayLong = $dateTime->format('d');
|
||||
$dayShort = (int) $dateTime->format('j');
|
||||
|
||||
return [
|
||||
// simple tests for single calls
|
||||
['{ac,1}', '2'],
|
||||
['{ac,2}', '02'],
|
||||
['{ac,3}', '002'],
|
||||
['{ac,4}', '0002'],
|
||||
['{Y}', $yearLong],
|
||||
['{y}', $yearShort],
|
||||
['{M}', $monthLong],
|
||||
['{m}', $monthShort],
|
||||
['{D}', $dayLong],
|
||||
['{d}', $dayShort],
|
||||
// number formatting (not testing the lower case versions, as the tests might break depending on the date)
|
||||
['{Y,6}', '00' . $yearLong],
|
||||
['{M,3}', '0' . $monthLong],
|
||||
['{D,3}', '0' . $dayLong],
|
||||
// increment dates
|
||||
['{YY}', $yearLong + 1],
|
||||
['{YY+1}', $yearLong + 1],
|
||||
['{YY+2}', $yearLong + 2],
|
||||
['{YY+3}', $yearLong + 3],
|
||||
['{YY-1}', $yearLong - 1],
|
||||
['{YY-2}', $yearLong - 2],
|
||||
['{YY-3}', $yearLong - 3],
|
||||
['{yy}', $yearShort + 1],
|
||||
['{yy+1}', $yearShort + 1],
|
||||
['{yy+2}', $yearShort + 2],
|
||||
['{yy+3}', $yearShort + 3],
|
||||
['{yy-1}', $yearShort - 1],
|
||||
['{yy-2}', $yearShort - 2],
|
||||
['{yy-3}', $yearShort - 3],
|
||||
['{MM}', $monthShort + 1], // cast to int removes leading zero
|
||||
['{MM+1}', $monthShort + 1], // cast to int removes leading zero
|
||||
['{MM+2}', $monthShort + 2], // cast to int removes leading zero
|
||||
['{MM+3}', $monthShort + 3], // cast to int removes leading zero
|
||||
['{DD}', $dayShort + 1], // cast to int removes leading zero
|
||||
['{DD+1}', $dayShort + 1], // cast to int removes leading zero
|
||||
['{DD+2}', $dayShort + 2], // cast to int removes leading zero
|
||||
['{DD+3}', $dayShort + 3], // cast to int removes leading zero
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -157,4 +157,84 @@ class CustomerServiceTest extends TestCase
|
||||
$Customer = new Customer('foo');
|
||||
$sut->saveNewCustomer($Customer);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider getTestData
|
||||
*/
|
||||
public function testCustomerNumber(string $format, int|string $expected): void
|
||||
{
|
||||
$configuration = SystemConfigurationFactory::createStub([
|
||||
'defaults' => [
|
||||
'customer' => [
|
||||
'timezone' => 'Europe/Vienna',
|
||||
'country' => 'IN',
|
||||
'currency' => 'RUB',
|
||||
]
|
||||
],
|
||||
'customer' => [
|
||||
'number_format' => $format
|
||||
]
|
||||
]);
|
||||
|
||||
$sut = $this->getSut(null, null, null, $configuration);
|
||||
$customer = $sut->createNewCustomer('Test');
|
||||
|
||||
self::assertEquals((string) $expected, $customer->getNumber());
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<int, array<int, string|\DateTime|int>>
|
||||
*/
|
||||
public static function getTestData(): array
|
||||
{
|
||||
$dateTime = new \DateTime();
|
||||
|
||||
$yearLong = (int) $dateTime->format('Y');
|
||||
$yearShort = (int) $dateTime->format('y');
|
||||
$monthLong = $dateTime->format('m');
|
||||
$monthShort = (int) $dateTime->format('n');
|
||||
$dayLong = $dateTime->format('d');
|
||||
$dayShort = (int) $dateTime->format('j');
|
||||
|
||||
return [
|
||||
// simple tests for single calls
|
||||
['{cc,1}', '2'],
|
||||
['{cc,2}', '02'],
|
||||
['{cc,3}', '002'],
|
||||
['{cc,4}', '0002'],
|
||||
['{Y}', $yearLong],
|
||||
['{y}', $yearShort],
|
||||
['{M}', $monthLong],
|
||||
['{m}', $monthShort],
|
||||
['{D}', $dayLong],
|
||||
['{d}', $dayShort],
|
||||
// number formatting (not testing the lower case versions, as the tests might break depending on the date)
|
||||
['{Y,6}', '00' . $yearLong],
|
||||
['{M,3}', '0' . $monthLong],
|
||||
['{D,3}', '0' . $dayLong],
|
||||
// increment dates
|
||||
['{YY}', $yearLong + 1],
|
||||
['{YY+1}', $yearLong + 1],
|
||||
['{YY+2}', $yearLong + 2],
|
||||
['{YY+3}', $yearLong + 3],
|
||||
['{YY-1}', $yearLong - 1],
|
||||
['{YY-2}', $yearLong - 2],
|
||||
['{YY-3}', $yearLong - 3],
|
||||
['{yy}', $yearShort + 1],
|
||||
['{yy+1}', $yearShort + 1],
|
||||
['{yy+2}', $yearShort + 2],
|
||||
['{yy+3}', $yearShort + 3],
|
||||
['{yy-1}', $yearShort - 1],
|
||||
['{yy-2}', $yearShort - 2],
|
||||
['{yy-3}', $yearShort - 3],
|
||||
['{MM}', $monthShort + 1], // cast to int removes leading zero
|
||||
['{MM+1}', $monthShort + 1], // cast to int removes leading zero
|
||||
['{MM+2}', $monthShort + 2], // cast to int removes leading zero
|
||||
['{MM+3}', $monthShort + 3], // cast to int removes leading zero
|
||||
['{DD}', $dayShort + 1], // cast to int removes leading zero
|
||||
['{DD+1}', $dayShort + 1], // cast to int removes leading zero
|
||||
['{DD+2}', $dayShort + 2], // cast to int removes leading zero
|
||||
['{DD+3}', $dayShort + 3], // cast to int removes leading zero
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -173,15 +173,13 @@ class InvoiceTest extends TestCase
|
||||
$user1->method('getUsername')->willReturn('foo-bar');
|
||||
|
||||
$timesheet = new Timesheet();
|
||||
$timesheet
|
||||
->setDuration(3600)
|
||||
->setRate(293.27)
|
||||
->setUser($user1)
|
||||
->setActivity($activity)
|
||||
->setProject($project)
|
||||
->setBegin(new \DateTime())
|
||||
->setEnd(new \DateTime())
|
||||
;
|
||||
$timesheet->setDuration(3600);
|
||||
$timesheet->setRate(293.27);
|
||||
$timesheet->setUser($user1);
|
||||
$timesheet->setActivity($activity);
|
||||
$timesheet->setProject($project);
|
||||
$timesheet->setBegin(new \DateTime());
|
||||
$timesheet->setEnd(new \DateTime());
|
||||
|
||||
$entries = [$timesheet];
|
||||
|
||||
|
||||
@@ -28,10 +28,13 @@ use Symfony\Contracts\Translation\TranslatorInterface;
|
||||
*/
|
||||
class CsvRendererTest extends AbstractRendererTestCase
|
||||
{
|
||||
protected function getAbstractRenderer(): CsvRenderer
|
||||
protected function getAbstractRenderer(bool $exportDecimal = false): CsvRenderer
|
||||
{
|
||||
$user = $this->createMock(User::class);
|
||||
$user->expects($this->any())->method('isExportDecimal')->willReturn($exportDecimal);
|
||||
|
||||
$security = $this->createMock(Security::class);
|
||||
$security->expects($this->any())->method('getUser')->willReturn(new User());
|
||||
$security->expects($this->any())->method('getUser')->willReturn($user);
|
||||
$security->expects($this->any())->method('isGranted')->willReturn(true);
|
||||
|
||||
$translator = $this->createMock(TranslatorInterface::class);
|
||||
@@ -53,16 +56,17 @@ class CsvRendererTest extends AbstractRendererTestCase
|
||||
public static function getTestModel(): array
|
||||
{
|
||||
return [
|
||||
['400', '2437.12', '1947.99', 7, 6, 1, 2, 2]
|
||||
['400', '2437.12', '1947.99', 7, 6, 1, 2, 2, false],
|
||||
['400', '2437.12', '1947.99', 7, 6, 1, 2, 2, true]
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider getTestModel
|
||||
*/
|
||||
public function testRender(string $totalDuration, string $totalRate, string $expectedRate, int $expectedRows, int $expectedDescriptions, int $expectedUser1, int $expectedUser2, int $expectedUser3): void
|
||||
public function testRender(string $totalDuration, string $totalRate, string $expectedRate, int $expectedRows, int $expectedDescriptions, int $expectedUser1, int $expectedUser2, int $expectedUser3, bool $exportDecimal): void
|
||||
{
|
||||
$sut = $this->getAbstractRenderer();
|
||||
$sut = $this->getAbstractRenderer($exportDecimal);
|
||||
|
||||
/** @var BinaryFileResponse $response */
|
||||
$response = $this->render($sut);
|
||||
@@ -102,7 +106,7 @@ class CsvRendererTest extends AbstractRendererTestCase
|
||||
'2019-06-16',
|
||||
'12:00',
|
||||
'12:06',
|
||||
'0:06',
|
||||
($exportDecimal ? '0.11' : '0:06:40'),
|
||||
//'0.11',
|
||||
'EUR',
|
||||
'0',
|
||||
@@ -136,7 +140,7 @@ class CsvRendererTest extends AbstractRendererTestCase
|
||||
'2019-06-16',
|
||||
'12:00',
|
||||
'12:06',
|
||||
'0:06',
|
||||
($exportDecimal ? '0.11' : '0:06:40'),
|
||||
//'0.11',
|
||||
'EUR',
|
||||
'0',
|
||||
|
||||
@@ -17,6 +17,12 @@ use PHPUnit\Framework\TestCase;
|
||||
*/
|
||||
class DateFormatterTest extends TestCase
|
||||
{
|
||||
public function testGetFormat(): void
|
||||
{
|
||||
$formatter = new DateFormatter();
|
||||
self::assertEquals('yyyy-mm-dd', $formatter->getFormat());
|
||||
}
|
||||
|
||||
public function testFormatValueReturnsFormattedDateForDateTime(): void
|
||||
{
|
||||
$formatter = new DateFormatter();
|
||||
|
||||
@@ -17,38 +17,57 @@ use PHPUnit\Framework\TestCase;
|
||||
*/
|
||||
class DurationFormatterTest extends TestCase
|
||||
{
|
||||
public function testGetFormat(): void
|
||||
{
|
||||
$formatter = new DurationFormatter();
|
||||
self::assertEquals('[hh]:mm:ss', $formatter->getFormat());
|
||||
}
|
||||
|
||||
public function testFormatValueReturnsFormattedDurationQuiteLong(): void
|
||||
{
|
||||
$formatter = new DurationFormatter();
|
||||
$result = $formatter->formatValue(701213);
|
||||
self::assertInstanceOf(\DateInterval::class, $result);
|
||||
self::assertEquals('194:46:53', $result->format('%r%H:%I:%S'));
|
||||
}
|
||||
|
||||
public function testFormatValueReturnsFormattedDurationForNumericValue(): void
|
||||
{
|
||||
$formatter = new DurationFormatter();
|
||||
$result = $formatter->formatValue(7200);
|
||||
self::assertEquals('2:00', $result);
|
||||
$result = $formatter->formatValue(7213);
|
||||
self::assertInstanceOf(\DateInterval::class, $result);
|
||||
self::assertEquals('02:00:13', $result->format('%r%H:%I:%S'));
|
||||
}
|
||||
|
||||
public function testFormatValueReturnsZeroForNonNumericValue(): void
|
||||
{
|
||||
$formatter = new DurationFormatter();
|
||||
$result = $formatter->formatValue('not a number');
|
||||
self::assertEquals('0:00', $result);
|
||||
self::assertInstanceOf(\DateInterval::class, $result);
|
||||
self::assertEquals('00:00:00', $result->format('%r%H:%I:%S'));
|
||||
}
|
||||
|
||||
public function testFormatValueReturnsFormattedDurationForFloatValue(): void
|
||||
{
|
||||
$formatter = new DurationFormatter();
|
||||
$result = $formatter->formatValue(4500.5);
|
||||
self::assertEquals('1:15', $result);
|
||||
$result = $formatter->formatValue(4521.5);
|
||||
self::assertInstanceOf(\DateInterval::class, $result);
|
||||
self::assertEquals('01:15:21', $result->format('%r%H:%I:%S'));
|
||||
}
|
||||
|
||||
public function testFormatValueReturnsZeroForNullValue(): void
|
||||
{
|
||||
$formatter = new DurationFormatter();
|
||||
$result = $formatter->formatValue(null);
|
||||
self::assertEquals('0:00', $result);
|
||||
self::assertInstanceOf(\DateInterval::class, $result);
|
||||
self::assertEquals('00:00:00', $result->format('%r%H:%I:%S'));
|
||||
}
|
||||
|
||||
public function testFormatValueReturnsFormattedDurationForNegativeValue(): void
|
||||
{
|
||||
$formatter = new DurationFormatter();
|
||||
$result = $formatter->formatValue(-3600);
|
||||
self::assertEquals('-1:00', $result);
|
||||
self::assertInstanceOf(\DateInterval::class, $result);
|
||||
self::assertEquals('-01:00:00', $result->format('%r%H:%I:%S'));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Kimai time-tracking app.
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace App\Tests\Export\Package\CellFormatter;
|
||||
|
||||
use App\Export\Package\CellFormatter\DurationPlainFormatter;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
/**
|
||||
* @covers \App\Export\Package\CellFormatter\DurationPlainFormatter
|
||||
*/
|
||||
class DurationPlainFormatterTest extends TestCase
|
||||
{
|
||||
public function testFormatValueReturnsFormattedDurationQuiteLong(): void
|
||||
{
|
||||
$formatter = new DurationPlainFormatter();
|
||||
$result = $formatter->formatValue(701213);
|
||||
self::assertEquals('194:46:53', $result);
|
||||
}
|
||||
|
||||
public function testFormatValueReturnsFormattedDurationForNumericValue(): void
|
||||
{
|
||||
$formatter = new DurationPlainFormatter();
|
||||
$result = $formatter->formatValue(8246);
|
||||
self::assertEquals('2:17:26', $result);
|
||||
}
|
||||
|
||||
public function testFormatValueReturnsZeroForNonNumericValue(): void
|
||||
{
|
||||
$formatter = new DurationPlainFormatter();
|
||||
$result = $formatter->formatValue('not a number');
|
||||
self::assertEquals('0:00:00', $result);
|
||||
}
|
||||
|
||||
public function testFormatValueReturnsFormattedDurationForFloatValue(): void
|
||||
{
|
||||
$formatter = new DurationPlainFormatter();
|
||||
$result = $formatter->formatValue(44513.5);
|
||||
self::assertEquals('12:21:53', $result);
|
||||
}
|
||||
|
||||
public function testFormatValueReturnsZeroForNullValue(): void
|
||||
{
|
||||
$formatter = new DurationPlainFormatter();
|
||||
$result = $formatter->formatValue(null);
|
||||
self::assertEquals('0:00:00', $result);
|
||||
}
|
||||
|
||||
public function testFormatValueReturnsFormattedDurationForNegativeValue(): void
|
||||
{
|
||||
$formatter = new DurationPlainFormatter();
|
||||
$result = $formatter->formatValue(-3600);
|
||||
self::assertEquals('-1:00:00', $result);
|
||||
}
|
||||
}
|
||||
@@ -11,6 +11,7 @@ namespace App\Tests\Export\Package;
|
||||
|
||||
use App\Entity\ExportableItem;
|
||||
use App\Export\Package\CellFormatter\CellFormatterInterface;
|
||||
use App\Export\Package\CellFormatter\DateFormatter;
|
||||
use App\Export\Package\Column;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
@@ -85,4 +86,17 @@ class ColumnTest extends TestCase
|
||||
$column = new Column('testName', $formatter);
|
||||
self::assertEquals('testName', $column->getHeader());
|
||||
}
|
||||
|
||||
public function testWithFormatReturnsNull(): void
|
||||
{
|
||||
$formatter = $this->createMock(CellFormatterInterface::class);
|
||||
$column = new Column('testName', $formatter);
|
||||
self::assertNull($column->getFormat());
|
||||
}
|
||||
|
||||
public function testWithFormatReturnsValueFromFormatter(): void
|
||||
{
|
||||
$column = new Column('testName', new DateFormatter());
|
||||
self::assertEquals('yyyy-mm-dd', $column->getFormat());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -67,84 +67,72 @@ abstract class AbstractRendererTestCase extends KernelTestCase
|
||||
$user2->method('getUsername')->willReturn('hello-world');
|
||||
|
||||
$timesheet = new Timesheet();
|
||||
$timesheet
|
||||
->setDuration(3600) // 60 minutes
|
||||
->setRate(293.27)
|
||||
->setUser($user1)
|
||||
->setActivity($activity)
|
||||
->setProject($project)
|
||||
->setBegin(new \DateTime())
|
||||
->setEnd(new \DateTime())
|
||||
;
|
||||
$timesheet->setDuration(3600);
|
||||
$timesheet->setRate(293.27);
|
||||
$timesheet->setUser($user1);
|
||||
$timesheet->setActivity($activity);
|
||||
$timesheet->setProject($project);
|
||||
$timesheet->setBegin(new \DateTime());
|
||||
$timesheet->setEnd(new \DateTime());
|
||||
|
||||
$timesheet2 = new Timesheet();
|
||||
$timesheet2
|
||||
->setDuration(400)
|
||||
->setRate(84.75)
|
||||
->setUser($user2)
|
||||
->setActivity($activity)
|
||||
->setProject($project)
|
||||
->setBegin(new \DateTime())
|
||||
->setEnd(new \DateTime())
|
||||
;
|
||||
$timesheet2->setDuration(400);
|
||||
$timesheet2->setRate(84.75);
|
||||
$timesheet2->setUser($user2);
|
||||
$timesheet2->setActivity($activity);
|
||||
$timesheet2->setProject($project);
|
||||
$timesheet2->setBegin(new \DateTime());
|
||||
$timesheet2->setEnd(new \DateTime());
|
||||
|
||||
$timesheet3 = new Timesheet();
|
||||
$timesheet3
|
||||
->setDuration(1800)
|
||||
->setRate(111.11)
|
||||
->setUser($user1)
|
||||
->setActivity($activity)
|
||||
->setProject($project)
|
||||
->setBegin(new \DateTime())
|
||||
->setEnd(new \DateTime())
|
||||
;
|
||||
$timesheet3->setDuration(1800);
|
||||
$timesheet3->setRate(111.11);
|
||||
$timesheet3->setUser($user1);
|
||||
$timesheet3->setActivity($activity);
|
||||
$timesheet3->setProject($project);
|
||||
$timesheet3->setBegin(new \DateTime());
|
||||
$timesheet3->setEnd(new \DateTime());
|
||||
|
||||
$timesheet4 = new Timesheet();
|
||||
$timesheet4
|
||||
->setDuration(400)
|
||||
->setRate(1947.99)
|
||||
->setUser($user2)
|
||||
->setDescription('== jhg ljhg ') // make sure that spreadsheets don't render it as formula
|
||||
->setActivity($activity)
|
||||
->setProject($project)
|
||||
->setBegin(new \DateTime())
|
||||
->setEnd(new \DateTime())
|
||||
->addTag((new Tag())->setName('foo'))
|
||||
;
|
||||
$timesheet4->setDuration(400);
|
||||
$timesheet4->setRate(1947.99);
|
||||
$timesheet4->setUser($user2);
|
||||
$timesheet4->setDescription('== jhg ljhg '); // make sure that spreadsheets don't render it as formula
|
||||
$timesheet4->setActivity($activity);
|
||||
$timesheet4->setProject($project);
|
||||
$timesheet4->setBegin(new \DateTime());
|
||||
$timesheet4->setEnd(new \DateTime());
|
||||
$timesheet4->addTag((new Tag())->setName('foo'));
|
||||
|
||||
$userKevin = new User();
|
||||
$userKevin->setAlias('Kevin');
|
||||
$userKevin->setUserIdentifier('kevin');
|
||||
|
||||
$timesheet5 = new Timesheet();
|
||||
$timesheet5
|
||||
->setDuration(400)
|
||||
->setFixedRate(84)
|
||||
->setUser($userKevin)
|
||||
->setActivity($activity)
|
||||
->setProject($project)
|
||||
->setBegin(new \DateTime('2019-06-16 12:00:00'))
|
||||
->setEnd(new \DateTime('2019-06-16 12:06:40'))
|
||||
->addTag((new Tag())->setName('foo'))
|
||||
->addTag((new Tag())->setName('bar'))
|
||||
->setMetaField((new TimesheetMeta())->setName('foo')->setValue('meta-bar')->setIsVisible(true))
|
||||
->setMetaField((new TimesheetMeta())->setName('foo2')->setValue('meta-bar2')->setIsVisible(true))
|
||||
;
|
||||
$timesheet5->setDuration(400);
|
||||
$timesheet5->setFixedRate(84);
|
||||
$timesheet5->setUser($userKevin);
|
||||
$timesheet5->setActivity($activity);
|
||||
$timesheet5->setProject($project);
|
||||
$timesheet5->setBegin(new \DateTime('2019-06-16 12:00:00'));
|
||||
$timesheet5->setEnd(new \DateTime('2019-06-16 12:06:40'));
|
||||
$timesheet5->addTag((new Tag())->setName('foo'));
|
||||
$timesheet5->addTag((new Tag())->setName('bar'));
|
||||
$timesheet5->setMetaField((new TimesheetMeta())->setName('foo')->setValue('meta-bar')->setIsVisible(true));
|
||||
$timesheet5->setMetaField((new TimesheetMeta())->setName('foo2')->setValue('meta-bar2')->setIsVisible(true));
|
||||
|
||||
$userNivek = new User();
|
||||
$userNivek->setAlias('niveK');
|
||||
$userNivek->setUserIdentifier('nivek');
|
||||
|
||||
$timesheet6 = new Timesheet();
|
||||
$timesheet6
|
||||
->setDuration(400)
|
||||
->setFixedRate(-100.92)
|
||||
->setUser($userNivek)
|
||||
->setActivity($activity)
|
||||
->setProject($project)
|
||||
->setBegin(new \DateTime('2019-06-16 12:00:00'))
|
||||
->setEnd(new \DateTime('2019-06-16 12:06:40'))
|
||||
;
|
||||
$timesheet6->setDuration(400);
|
||||
$timesheet6->setFixedRate(-100.92);
|
||||
$timesheet6->setUser($userNivek);
|
||||
$timesheet6->setActivity($activity);
|
||||
$timesheet6->setProject($project);
|
||||
$timesheet6->setBegin(new \DateTime('2019-06-16 12:00:00'));
|
||||
$timesheet6->setEnd(new \DateTime('2019-06-16 12:06:40'));
|
||||
|
||||
$entries = [$timesheet, $timesheet2, $timesheet3, $timesheet4, $timesheet5, $timesheet6];
|
||||
|
||||
|
||||
@@ -65,67 +65,57 @@ abstract class AbstractRendererTestCase extends KernelTestCase
|
||||
$user2->method('getUserIdentifier')->willReturn('hello-world');
|
||||
|
||||
$timesheet = new Timesheet();
|
||||
$timesheet
|
||||
->setDuration(3600)
|
||||
->setRate(293.27)
|
||||
->setUser($user1)
|
||||
->setActivity($activity)
|
||||
->setProject($project)
|
||||
->setBegin(new \DateTime())
|
||||
->setEnd(new \DateTime())
|
||||
;
|
||||
$timesheet->setDuration(3600);
|
||||
$timesheet->setRate(293.27);
|
||||
$timesheet->setUser($user1);
|
||||
$timesheet->setActivity($activity);
|
||||
$timesheet->setProject($project);
|
||||
$timesheet->setBegin(new \DateTime());
|
||||
$timesheet->setEnd(new \DateTime());
|
||||
|
||||
$timesheet2 = new Timesheet();
|
||||
$timesheet2
|
||||
->setDuration(400)
|
||||
->setRate(84.75)
|
||||
->setUser($user2)
|
||||
->setActivity($activity)
|
||||
->setProject($project)
|
||||
->setBegin(new \DateTime())
|
||||
->setEnd(new \DateTime())
|
||||
;
|
||||
$timesheet2->setDuration(400);
|
||||
$timesheet2->setRate(84.75);
|
||||
$timesheet2->setUser($user2);
|
||||
$timesheet2->setActivity($activity);
|
||||
$timesheet2->setProject($project);
|
||||
$timesheet2->setBegin(new \DateTime());
|
||||
$timesheet2->setEnd(new \DateTime());
|
||||
|
||||
$timesheet3 = new Timesheet();
|
||||
$timesheet3
|
||||
->setDuration(1800)
|
||||
->setRate(111.11)
|
||||
->setUser($user1)
|
||||
->setActivity($activity)
|
||||
->setProject($project)
|
||||
->setBegin(new \DateTime())
|
||||
->setEnd(new \DateTime())
|
||||
;
|
||||
$timesheet3->setDuration(1800);
|
||||
$timesheet3->setRate(111.11);
|
||||
$timesheet3->setUser($user1);
|
||||
$timesheet3->setActivity($activity);
|
||||
$timesheet3->setProject($project);
|
||||
$timesheet3->setBegin(new \DateTime());
|
||||
$timesheet3->setEnd(new \DateTime());
|
||||
|
||||
$timesheet4 = new Timesheet();
|
||||
$timesheet4
|
||||
->setDuration(400)
|
||||
->setRate(1947.99)
|
||||
->setUser($user2)
|
||||
->setActivity($activity)
|
||||
->setProject($project)
|
||||
->setBegin(new \DateTime())
|
||||
->setEnd(new \DateTime())
|
||||
->addTag((new Tag())->setName('foo'))
|
||||
;
|
||||
$timesheet4->setDuration(400);
|
||||
$timesheet4->setRate(1947.99);
|
||||
$timesheet4->setUser($user2);
|
||||
$timesheet4->setActivity($activity);
|
||||
$timesheet4->setProject($project);
|
||||
$timesheet4->setBegin(new \DateTime());
|
||||
$timesheet4->setEnd(new \DateTime());
|
||||
$timesheet4->addTag((new Tag())->setName('foo'));
|
||||
|
||||
$user = new User();
|
||||
$user->setUserIdentifier('kevin');
|
||||
|
||||
$timesheet5 = new Timesheet();
|
||||
$timesheet5
|
||||
->setDuration(400)
|
||||
->setFixedRate(84)
|
||||
->setUser($user)
|
||||
->setActivity($activity)
|
||||
->setProject($project)
|
||||
->setBegin(new \DateTime('2019-06-16 12:00:00'))
|
||||
->setEnd(new \DateTime('2019-06-16 12:06:40'))
|
||||
->addTag((new Tag())->setName('foo'))
|
||||
->addTag((new Tag())->setName('bar'))
|
||||
->setMetaField((new TimesheetMeta())->setName('foo')->setValue('meta-bar')->setIsVisible(true))
|
||||
->setMetaField((new TimesheetMeta())->setName('foo2')->setValue('meta-bar2')->setIsVisible(true))
|
||||
;
|
||||
$timesheet5->setDuration(400);
|
||||
$timesheet5->setFixedRate(84);
|
||||
$timesheet5->setUser($user);
|
||||
$timesheet5->setActivity($activity);
|
||||
$timesheet5->setProject($project);
|
||||
$timesheet5->setBegin(new \DateTime('2019-06-16 12:00:00'));
|
||||
$timesheet5->setEnd(new \DateTime('2019-06-16 12:06:40'));
|
||||
$timesheet5->addTag((new Tag())->setName('foo'));
|
||||
$timesheet5->addTag((new Tag())->setName('bar'));
|
||||
$timesheet5->setMetaField((new TimesheetMeta())->setName('foo')->setValue('meta-bar')->setIsVisible(true));
|
||||
$timesheet5->setMetaField((new TimesheetMeta())->setName('foo2')->setValue('meta-bar2')->setIsVisible(true));
|
||||
|
||||
$entries = [$timesheet, $timesheet2, $timesheet3, $timesheet4, $timesheet5];
|
||||
|
||||
|
||||
@@ -86,14 +86,13 @@ abstract class AbstractCalculatorTestCase extends TestCase
|
||||
}
|
||||
|
||||
$timesheet = new Timesheet();
|
||||
$timesheet
|
||||
->setDescription('timesheet description')
|
||||
->setBegin(new \DateTime())
|
||||
->setDuration(3600)
|
||||
->setRate(293.27)
|
||||
->setUser($user)
|
||||
->setActivity($activity)
|
||||
->setProject($project);
|
||||
$timesheet->setDescription('timesheet description');
|
||||
$timesheet->setBegin(new \DateTime());
|
||||
$timesheet->setDuration(3600);
|
||||
$timesheet->setRate(293.27);
|
||||
$timesheet->setUser($user);
|
||||
$timesheet->setActivity($activity);
|
||||
$timesheet->setProject($project);
|
||||
|
||||
$model = (new InvoiceModelFactoryFactory($this))->create()->createModel(new DebugFormatter(), $customer, $template, $query);
|
||||
$model->addEntries([$timesheet]);
|
||||
|
||||
@@ -54,82 +54,74 @@ class ActivityInvoiceCalculatorTest extends AbstractCalculatorTestCase
|
||||
$activity3->method('getId')->willReturn(3);
|
||||
|
||||
$timesheet = new Timesheet();
|
||||
$timesheet
|
||||
->setBegin(new \DateTime('2018-11-29'))
|
||||
->setEnd(new \DateTime())
|
||||
->setDuration(3600)
|
||||
->setRate(293.27)
|
||||
->setUser($user)
|
||||
->setActivity($activity1)
|
||||
->setProject((new Project())->setName('bar'));
|
||||
$timesheet->setBegin(new \DateTime('2018-11-29'));
|
||||
$timesheet->setEnd(new \DateTime());
|
||||
$timesheet->setDuration(3600);
|
||||
$timesheet->setRate(293.27);
|
||||
$timesheet->setUser($user);
|
||||
$timesheet->setActivity($activity1);
|
||||
$timesheet->setProject((new Project())->setName('bar'));
|
||||
|
||||
$timesheet2 = new Timesheet();
|
||||
$timesheet2
|
||||
->setBegin(clone $date)
|
||||
->setEnd(new \DateTime())
|
||||
->setDuration(400)
|
||||
->setRate(84.75)
|
||||
->setUser($user)
|
||||
->setActivity($activity2)
|
||||
->setProject((new Project())->setName('bar'));
|
||||
$timesheet2->setBegin(clone $date);
|
||||
$timesheet2->setEnd(new \DateTime());
|
||||
$timesheet2->setDuration(400);
|
||||
$timesheet2->setRate(84.75);
|
||||
$timesheet2->setUser($user);
|
||||
$timesheet2->setActivity($activity2);
|
||||
$timesheet2->setProject((new Project())->setName('bar'));
|
||||
|
||||
$timesheet3 = new Timesheet();
|
||||
$timesheet3
|
||||
->setBegin(new \DateTime('2018-11-28'))
|
||||
->setEnd(new \DateTime())
|
||||
->setDuration(1800)
|
||||
->setRate(111.11)
|
||||
->setUser($user)
|
||||
->setActivity($activity1)
|
||||
->setProject((new Project())->setName('bar'));
|
||||
$timesheet3->setBegin(new \DateTime('2018-11-28'));
|
||||
$timesheet3->setEnd(new \DateTime());
|
||||
$timesheet3->setDuration(1800);
|
||||
$timesheet3->setRate(111.11);
|
||||
$timesheet3->setUser($user);
|
||||
$timesheet3->setActivity($activity1);
|
||||
$timesheet3->setProject((new Project())->setName('bar'));
|
||||
|
||||
$timesheet4 = new Timesheet();
|
||||
$timesheet4
|
||||
->setBegin(new \DateTime('2018-11-28'))
|
||||
->setEnd(new \DateTime())
|
||||
->setDuration(400)
|
||||
->setRate(1947.99)
|
||||
->setUser($user)
|
||||
->setActivity($activity2)
|
||||
->setProject((new Project())->setName('bar'));
|
||||
$timesheet4->setBegin(new \DateTime('2018-11-28'));
|
||||
$timesheet4->setEnd(new \DateTime());
|
||||
$timesheet4->setDuration(400);
|
||||
$timesheet4->setRate(1947.99);
|
||||
$timesheet4->setUser($user);
|
||||
$timesheet4->setActivity($activity2);
|
||||
$timesheet4->setProject((new Project())->setName('bar'));
|
||||
|
||||
$timesheet5 = new Timesheet();
|
||||
$timesheet5
|
||||
->setBegin(new \DateTime('2018-11-29'))
|
||||
->setEnd(new \DateTime())
|
||||
->setDuration(400)
|
||||
->setRate(84)
|
||||
->setUser(new User())
|
||||
->setActivity($activity3)
|
||||
->setProject((new Project())->setName('bar'));
|
||||
$timesheet5->setBegin(new \DateTime('2018-11-29'));
|
||||
$timesheet5->setEnd(new \DateTime());
|
||||
$timesheet5->setDuration(400);
|
||||
$timesheet5->setRate(84);
|
||||
$timesheet5->setUser(new User());
|
||||
$timesheet5->setActivity($activity3);
|
||||
$timesheet5->setProject((new Project())->setName('bar'));
|
||||
|
||||
$timesheet6 = new Timesheet();
|
||||
$timesheet6
|
||||
->setBegin(clone $date)
|
||||
->setEnd(new \DateTime())
|
||||
->setDuration(0)
|
||||
->setRate(0)
|
||||
->setUser(new User())
|
||||
->setProject((new Project())->setName('bar'));
|
||||
$timesheet6->setBegin(clone $date);
|
||||
$timesheet6->setEnd(new \DateTime());
|
||||
$timesheet6->setDuration(0);
|
||||
$timesheet6->setRate(0);
|
||||
$timesheet6->setUser(new User());
|
||||
$timesheet6->setProject((new Project())->setName('bar'));
|
||||
|
||||
$timesheet7 = new Timesheet();
|
||||
$timesheet7
|
||||
->setBegin(clone $date)
|
||||
->setEnd(new \DateTime('2018-11-18'))
|
||||
->setDuration(0)
|
||||
->setRate(0)
|
||||
->setUser(new User())
|
||||
->setActivity(new Activity())
|
||||
->setProject((new Project())->setName('bar'));
|
||||
$timesheet7->setBegin(clone $date);
|
||||
$timesheet7->setEnd(new \DateTime('2018-11-18'));
|
||||
$timesheet7->setDuration(0);
|
||||
$timesheet7->setRate(0);
|
||||
$timesheet7->setUser(new User());
|
||||
$timesheet7->setActivity(new Activity());
|
||||
$timesheet7->setProject((new Project())->setName('bar'));
|
||||
|
||||
$timesheet8 = new Timesheet();
|
||||
$timesheet8
|
||||
->setBegin(clone $date)
|
||||
->setEnd(new \DateTime())
|
||||
->setDuration(0)
|
||||
->setRate(0)
|
||||
->setUser(new User())
|
||||
->setProject((new Project())->setName('bar'));
|
||||
$timesheet8->setBegin(clone $date);
|
||||
$timesheet8->setEnd(new \DateTime());
|
||||
$timesheet8->setDuration(0);
|
||||
$timesheet8->setRate(0);
|
||||
$timesheet8->setUser(new User());
|
||||
$timesheet8->setProject((new Project())->setName('bar'));
|
||||
|
||||
$entries = [$timesheet, $timesheet2, $timesheet3, $timesheet4, $timesheet5, $timesheet6, $timesheet7, $timesheet8];
|
||||
|
||||
|
||||
@@ -57,92 +57,83 @@ class ActivityUserInvoiceCalculatorTest extends AbstractCalculatorTestCase
|
||||
$activity3->method('getId')->willReturn(3);
|
||||
|
||||
$timesheet = new Timesheet();
|
||||
$timesheet
|
||||
->setBegin(new \DateTime())
|
||||
->setEnd(new \DateTime())
|
||||
->setDuration(3600)
|
||||
->setRate(293.27)
|
||||
->setUser($user1)
|
||||
->setActivity($activity1)
|
||||
->setProject((new Project())->setName('bar'));
|
||||
$timesheet->setBegin(new \DateTime());
|
||||
$timesheet->setEnd(new \DateTime());
|
||||
$timesheet->setDuration(3600);
|
||||
$timesheet->setRate(293.27);
|
||||
$timesheet->setUser($user1);
|
||||
$timesheet->setActivity($activity1);
|
||||
$timesheet->setProject((new Project())->setName('bar'));
|
||||
|
||||
$timesheet2 = new Timesheet();
|
||||
$timesheet2
|
||||
->setBegin(new \DateTime('2018-11-18'))
|
||||
->setEnd(new \DateTime())
|
||||
->setDuration(400)
|
||||
->setRate(84.75)
|
||||
->setUser($user1)
|
||||
->setActivity($activity2)
|
||||
->setProject((new Project())->setName('bar'));
|
||||
$timesheet2->setBegin(new \DateTime('2018-11-18'));
|
||||
$timesheet2->setEnd(new \DateTime());
|
||||
$timesheet2->setDuration(400);
|
||||
$timesheet2->setRate(84.75);
|
||||
$timesheet2->setUser($user1);
|
||||
$timesheet2->setActivity($activity2);
|
||||
$timesheet2->setProject((new Project())->setName('bar'));
|
||||
|
||||
$timesheet3 = new Timesheet();
|
||||
$timesheet3
|
||||
->setBegin(clone $date)
|
||||
->setEnd(new \DateTime())
|
||||
->setDuration(1800)
|
||||
->setRate(111.11)
|
||||
->setUser($user1)
|
||||
->setActivity($activity1)
|
||||
->setProject((new Project())->setName('bar'));
|
||||
$timesheet3->setBegin(clone $date);
|
||||
$timesheet3->setEnd(new \DateTime());
|
||||
$timesheet3->setDuration(1800);
|
||||
$timesheet3->setRate(111.11);
|
||||
$timesheet3->setUser($user1);
|
||||
$timesheet3->setActivity($activity1);
|
||||
$timesheet3->setProject((new Project())->setName('bar'));
|
||||
|
||||
$timesheet4 = new Timesheet();
|
||||
$timesheet4
|
||||
->setBegin(new \DateTime('2018-11-29'))
|
||||
->setEnd(new \DateTime())
|
||||
->setDuration(400)
|
||||
->setRate(1947.99)
|
||||
->setUser($user1)
|
||||
->setActivity($activity2)
|
||||
->setProject((new Project())->setName('bar'));
|
||||
$timesheet4->setBegin(new \DateTime('2018-11-29'));
|
||||
$timesheet4->setEnd(new \DateTime());
|
||||
$timesheet4->setDuration(400);
|
||||
$timesheet4->setRate(1947.99);
|
||||
$timesheet4->setUser($user1);
|
||||
$timesheet4->setActivity($activity2);
|
||||
$timesheet4->setProject((new Project())->setName('bar'));
|
||||
|
||||
$timesheet5 = new Timesheet();
|
||||
$timesheet5
|
||||
->setBegin(new \DateTime('2018-11-18'))
|
||||
->setEnd(new \DateTime())
|
||||
->setDuration(400)
|
||||
->setRate(84)
|
||||
->setUser($user2)
|
||||
->setActivity($activity3)
|
||||
->setProject((new Project())->setName('bar'));
|
||||
$timesheet5->setBegin(new \DateTime('2018-11-18'));
|
||||
$timesheet5->setEnd(new \DateTime());
|
||||
$timesheet5->setDuration(400);
|
||||
$timesheet5->setRate(84);
|
||||
$timesheet5->setUser($user2);
|
||||
$timesheet5->setActivity($activity3);
|
||||
$timesheet5->setProject((new Project())->setName('bar'));
|
||||
|
||||
$timesheet5a = new Timesheet();
|
||||
$timesheet5a
|
||||
->setBegin(new \DateTime('2018-11-08'))
|
||||
->setEnd(new \DateTime())
|
||||
->setDuration(400)
|
||||
->setRate(84)
|
||||
->setUser($user1)
|
||||
->setActivity($activity3)
|
||||
->setProject((new Project())->setName('bar'));
|
||||
$timesheet5a->setBegin(new \DateTime('2018-11-08'));
|
||||
$timesheet5a->setEnd(new \DateTime());
|
||||
$timesheet5a->setDuration(400);
|
||||
$timesheet5a->setRate(84);
|
||||
$timesheet5a->setUser($user1);
|
||||
$timesheet5a->setActivity($activity3);
|
||||
$timesheet5a->setProject((new Project())->setName('bar'));
|
||||
|
||||
$timesheet6 = new Timesheet();
|
||||
$timesheet6
|
||||
->setBegin(clone $date)
|
||||
->setEnd(new \DateTime())
|
||||
->setDuration(0)
|
||||
->setRate(0)
|
||||
->setUser($user1)
|
||||
->setProject((new Project())->setName('bar'));
|
||||
$timesheet6->setBegin(clone $date);
|
||||
$timesheet6->setEnd(new \DateTime());
|
||||
$timesheet6->setDuration(0);
|
||||
$timesheet6->setRate(0);
|
||||
$timesheet6->setUser($user1);
|
||||
$timesheet6->setProject((new Project())->setName('bar'));
|
||||
|
||||
$timesheet7 = new Timesheet();
|
||||
$timesheet7
|
||||
->setBegin(clone $date)
|
||||
->setEnd(new \DateTime())
|
||||
->setDuration(0)
|
||||
->setRate(0)
|
||||
->setUser($user2)
|
||||
->setActivity(new Activity())
|
||||
->setProject((new Project())->setName('bar'));
|
||||
$timesheet7->setBegin(clone $date);
|
||||
$timesheet7->setEnd(new \DateTime());
|
||||
$timesheet7->setDuration(0);
|
||||
$timesheet7->setRate(0);
|
||||
$timesheet7->setUser($user2);
|
||||
$timesheet7->setActivity(new Activity());
|
||||
$timesheet7->setProject((new Project())->setName('bar'));
|
||||
|
||||
$timesheet8 = new Timesheet();
|
||||
$timesheet8
|
||||
->setBegin(clone $date)
|
||||
->setEnd(new \DateTime())
|
||||
->setDuration(0)
|
||||
->setRate(0)
|
||||
->setUser($user2)
|
||||
->setProject((new Project())->setName('bar'));
|
||||
$timesheet8->setBegin(clone $date);
|
||||
$timesheet8->setEnd(new \DateTime());
|
||||
$timesheet8->setDuration(0);
|
||||
$timesheet8->setRate(0);
|
||||
$timesheet8->setUser($user2);
|
||||
$timesheet8->setProject((new Project())->setName('bar'));
|
||||
|
||||
$entries = [$timesheet, $timesheet2, $timesheet3, $timesheet4, $timesheet5, $timesheet5a, $timesheet6, $timesheet7, $timesheet8];
|
||||
|
||||
|
||||
@@ -55,54 +55,49 @@ class DateInvoiceCalculatorTest extends AbstractCalculatorTestCase
|
||||
$project3->method('getId')->willReturn(3);
|
||||
|
||||
$timesheet = new Timesheet();
|
||||
$timesheet
|
||||
->setBegin(new DateTime('2018-11-29'))
|
||||
->setEnd(new DateTime())
|
||||
->setDuration(3600)
|
||||
->setRate(293.27)
|
||||
->setUser($user)
|
||||
->setActivity((new Activity())->setName('sdsd'))
|
||||
->setProject($project1);
|
||||
$timesheet->setBegin(new DateTime('2018-11-29'));
|
||||
$timesheet->setEnd(new DateTime());
|
||||
$timesheet->setDuration(3600);
|
||||
$timesheet->setRate(293.27);
|
||||
$timesheet->setUser($user);
|
||||
$timesheet->setActivity((new Activity())->setName('sdsd'));
|
||||
$timesheet->setProject($project1);
|
||||
|
||||
$timesheet2 = new Timesheet();
|
||||
$timesheet2
|
||||
->setBegin(new DateTime('2018-11-29'))
|
||||
->setEnd(new DateTime())
|
||||
->setDuration(400)
|
||||
->setRate(84.75)
|
||||
->setUser($user)
|
||||
->setActivity((new Activity())->setName('bar'))
|
||||
->setProject($project2);
|
||||
$timesheet2->setBegin(new DateTime('2018-11-29'));
|
||||
$timesheet2->setEnd(new DateTime());
|
||||
$timesheet2->setDuration(400);
|
||||
$timesheet2->setRate(84.75);
|
||||
$timesheet2->setUser($user);
|
||||
$timesheet2->setActivity((new Activity())->setName('bar'));
|
||||
$timesheet2->setProject($project2);
|
||||
|
||||
$timesheet3 = new Timesheet();
|
||||
$timesheet3
|
||||
->setBegin(new DateTime('2018-11-28'))
|
||||
->setEnd(new DateTime())
|
||||
->setDuration(1800)
|
||||
->setRate(111.11)
|
||||
->setUser($user)
|
||||
->setActivity((new Activity())->setName('foo'))
|
||||
->setProject($project1);
|
||||
$timesheet3->setBegin(new DateTime('2018-11-28'));
|
||||
$timesheet3->setEnd(new DateTime());
|
||||
$timesheet3->setDuration(1800);
|
||||
$timesheet3->setRate(111.11);
|
||||
$timesheet3->setUser($user);
|
||||
$timesheet3->setActivity((new Activity())->setName('foo'));
|
||||
$timesheet3->setProject($project1);
|
||||
|
||||
$timesheet4 = new Timesheet();
|
||||
$timesheet4
|
||||
->setBegin($date)
|
||||
->setEnd(new DateTime('2018-11-28'))
|
||||
->setDuration(400)
|
||||
->setRate(1947.99)
|
||||
->setUser($user)
|
||||
->setActivity((new Activity())->setName('blub'))
|
||||
->setProject($project2);
|
||||
$timesheet4->setBegin($date);
|
||||
$timesheet4->setEnd(new DateTime('2018-11-28'));
|
||||
$timesheet4->setDuration(400);
|
||||
$timesheet4->setRate(1947.99);
|
||||
$timesheet4->setUser($user);
|
||||
$timesheet4->setActivity((new Activity())->setName('blub'));
|
||||
$timesheet4->setProject($project2);
|
||||
|
||||
$timesheet5 = new Timesheet();
|
||||
$timesheet5
|
||||
->setBegin(new DateTime('2018-11-28'))
|
||||
->setEnd(new DateTime())
|
||||
->setDuration(400)
|
||||
->setRate(84)
|
||||
->setUser(new User())
|
||||
->setActivity(new Activity())
|
||||
->setProject($project3);
|
||||
$timesheet5->setBegin(new DateTime('2018-11-28'));
|
||||
$timesheet5->setEnd(new DateTime());
|
||||
$timesheet5->setDuration(400);
|
||||
$timesheet5->setRate(84);
|
||||
$timesheet5->setUser(new User());
|
||||
$timesheet5->setActivity(new Activity());
|
||||
$timesheet5->setProject($project3);
|
||||
|
||||
$entries = [$timesheet, $timesheet2, $timesheet3, $timesheet4, $timesheet5];
|
||||
|
||||
|
||||
@@ -57,54 +57,49 @@ class DateUserInvoiceCalculatorTest extends AbstractCalculatorTestCase
|
||||
$project3->method('getId')->willReturn(3);
|
||||
|
||||
$timesheet = new Timesheet();
|
||||
$timesheet
|
||||
->setBegin(new DateTime('2018-11-29'))
|
||||
->setEnd(new DateTime())
|
||||
->setDuration(3600)
|
||||
->setRate(293.27)
|
||||
->setUser($user1)
|
||||
->setActivity((new Activity())->setName('sdsd'))
|
||||
->setProject($project1);
|
||||
$timesheet->setBegin(new DateTime('2018-11-29'));
|
||||
$timesheet->setEnd(new DateTime());
|
||||
$timesheet->setDuration(3600);
|
||||
$timesheet->setRate(293.27);
|
||||
$timesheet->setUser($user1);
|
||||
$timesheet->setActivity((new Activity())->setName('sdsd'));
|
||||
$timesheet->setProject($project1);
|
||||
|
||||
$timesheet2 = new Timesheet();
|
||||
$timesheet2
|
||||
->setBegin(new DateTime('2018-11-29'))
|
||||
->setEnd(new DateTime())
|
||||
->setDuration(400)
|
||||
->setRate(84.75)
|
||||
->setUser($user1)
|
||||
->setActivity((new Activity())->setName('bar'))
|
||||
->setProject($project2);
|
||||
$timesheet2->setBegin(new DateTime('2018-11-29'));
|
||||
$timesheet2->setEnd(new DateTime());
|
||||
$timesheet2->setDuration(400);
|
||||
$timesheet2->setRate(84.75);
|
||||
$timesheet2->setUser($user1);
|
||||
$timesheet2->setActivity((new Activity())->setName('bar'));
|
||||
$timesheet2->setProject($project2);
|
||||
|
||||
$timesheet3 = new Timesheet();
|
||||
$timesheet3
|
||||
->setBegin(new DateTime('2018-11-28'))
|
||||
->setEnd(new DateTime())
|
||||
->setDuration(1800)
|
||||
->setRate(111.11)
|
||||
->setUser($user1)
|
||||
->setActivity((new Activity())->setName('foo'))
|
||||
->setProject($project1);
|
||||
$timesheet3->setBegin(new DateTime('2018-11-28'));
|
||||
$timesheet3->setEnd(new DateTime());
|
||||
$timesheet3->setDuration(1800);
|
||||
$timesheet3->setRate(111.11);
|
||||
$timesheet3->setUser($user1);
|
||||
$timesheet3->setActivity((new Activity())->setName('foo'));
|
||||
$timesheet3->setProject($project1);
|
||||
|
||||
$timesheet4 = new Timesheet();
|
||||
$timesheet4
|
||||
->setBegin(new DateTime())
|
||||
->setEnd(new DateTime())
|
||||
->setDuration(400)
|
||||
->setRate(1947.99)
|
||||
->setUser($user1)
|
||||
->setActivity((new Activity())->setName('blub'))
|
||||
->setProject($project2);
|
||||
$timesheet4->setBegin(new DateTime());
|
||||
$timesheet4->setEnd(new DateTime());
|
||||
$timesheet4->setDuration(400);
|
||||
$timesheet4->setRate(1947.99);
|
||||
$timesheet4->setUser($user1);
|
||||
$timesheet4->setActivity((new Activity())->setName('blub'));
|
||||
$timesheet4->setProject($project2);
|
||||
|
||||
$timesheet5 = new Timesheet();
|
||||
$timesheet5
|
||||
->setBegin(new DateTime('2018-11-28'))
|
||||
->setEnd(new DateTime())
|
||||
->setDuration(400)
|
||||
->setRate(84)
|
||||
->setUser($user2)
|
||||
->setActivity(new Activity())
|
||||
->setProject($project3);
|
||||
$timesheet5->setBegin(new DateTime('2018-11-28'));
|
||||
$timesheet5->setEnd(new DateTime());
|
||||
$timesheet5->setDuration(400);
|
||||
$timesheet5->setRate(84);
|
||||
$timesheet5->setUser($user2);
|
||||
$timesheet5->setActivity(new Activity());
|
||||
$timesheet5->setProject($project3);
|
||||
|
||||
$entries = [$timesheet, $timesheet2, $timesheet3, $timesheet4, $timesheet5];
|
||||
|
||||
|
||||
@@ -54,58 +54,53 @@ class PriceInvoiceCalculatorTest extends AbstractCalculatorTestCase
|
||||
$project3->method('getId')->willReturn(3);
|
||||
|
||||
$timesheet = new Timesheet();
|
||||
$timesheet
|
||||
->setBegin(new DateTime('2018-11-29'))
|
||||
->setEnd(new DateTime())
|
||||
->setDuration(3600)
|
||||
->setHourlyRate(293.27)
|
||||
->setRate(293.27)
|
||||
->setUser($user)
|
||||
->setActivity((new Activity())->setName('sdsd'))
|
||||
->setProject($project1);
|
||||
$timesheet->setBegin(new DateTime('2018-11-29'));
|
||||
$timesheet->setEnd(new DateTime());
|
||||
$timesheet->setDuration(3600);
|
||||
$timesheet->setHourlyRate(293.27);
|
||||
$timesheet->setRate(293.27);
|
||||
$timesheet->setUser($user);
|
||||
$timesheet->setActivity((new Activity())->setName('sdsd'));
|
||||
$timesheet->setProject($project1);
|
||||
|
||||
$timesheet2 = new Timesheet();
|
||||
$timesheet2
|
||||
->setBegin(new DateTime('2018-11-29'))
|
||||
->setEnd(new DateTime())
|
||||
->setDuration(400)
|
||||
->setHourlyRate(293.27)
|
||||
->setRate(84.75)
|
||||
->setUser($user)
|
||||
->setActivity((new Activity())->setName('bar'))
|
||||
->setProject($project2);
|
||||
$timesheet2->setBegin(new DateTime('2018-11-29'));
|
||||
$timesheet2->setEnd(new DateTime());
|
||||
$timesheet2->setDuration(400);
|
||||
$timesheet2->setHourlyRate(293.27);
|
||||
$timesheet2->setRate(84.75);
|
||||
$timesheet2->setUser($user);
|
||||
$timesheet2->setActivity((new Activity())->setName('bar'));
|
||||
$timesheet2->setProject($project2);
|
||||
|
||||
$timesheet3 = new Timesheet();
|
||||
$timesheet3
|
||||
->setBegin(new DateTime('2018-11-28'))
|
||||
->setEnd(new DateTime())
|
||||
->setDuration(1800)
|
||||
->setFixedRate(111.11)
|
||||
->setRate(111.11)
|
||||
->setUser($user)
|
||||
->setActivity((new Activity())->setName('foo'))
|
||||
->setProject($project1);
|
||||
$timesheet3->setBegin(new DateTime('2018-11-28'));
|
||||
$timesheet3->setEnd(new DateTime());
|
||||
$timesheet3->setDuration(1800);
|
||||
$timesheet3->setFixedRate(111.11);
|
||||
$timesheet3->setRate(111.11);
|
||||
$timesheet3->setUser($user);
|
||||
$timesheet3->setActivity((new Activity())->setName('foo'));
|
||||
$timesheet3->setProject($project1);
|
||||
|
||||
$timesheet4 = new Timesheet();
|
||||
$timesheet4
|
||||
->setBegin(new DateTime('2018-11-28'))
|
||||
->setEnd(new DateTime())
|
||||
->setDuration(400)
|
||||
->setHourlyRate(0)
|
||||
->setRate(1947.99)
|
||||
->setUser($user)
|
||||
->setActivity((new Activity())->setName('blub'))
|
||||
->setProject($project2);
|
||||
$timesheet4->setBegin(new DateTime('2018-11-28'));
|
||||
$timesheet4->setEnd(new DateTime());
|
||||
$timesheet4->setDuration(400);
|
||||
$timesheet4->setHourlyRate(0);
|
||||
$timesheet4->setRate(1947.99);
|
||||
$timesheet4->setUser($user);
|
||||
$timesheet4->setActivity((new Activity())->setName('blub'));
|
||||
$timesheet4->setProject($project2);
|
||||
|
||||
$timesheet5 = new Timesheet();
|
||||
$timesheet5
|
||||
->setBegin(new DateTime('2018-11-28'))
|
||||
->setEnd(new DateTime())
|
||||
->setDuration(400)
|
||||
->setRate(84)
|
||||
->setUser(new User())
|
||||
->setActivity(new Activity())
|
||||
->setProject($project3);
|
||||
$timesheet5->setBegin(new DateTime('2018-11-28'));
|
||||
$timesheet5->setEnd(new DateTime());
|
||||
$timesheet5->setDuration(400);
|
||||
$timesheet5->setRate(84);
|
||||
$timesheet5->setUser(new User());
|
||||
$timesheet5->setActivity(new Activity());
|
||||
$timesheet5->setProject($project3);
|
||||
|
||||
$entries = [$timesheet, $timesheet2, $timesheet3, $timesheet4, $timesheet5];
|
||||
|
||||
|
||||
@@ -54,54 +54,49 @@ class ProjectInvoiceCalculatorTest extends AbstractCalculatorTestCase
|
||||
$project3->method('getId')->willReturn(3);
|
||||
|
||||
$timesheet = new Timesheet();
|
||||
$timesheet
|
||||
->setBegin(new DateTime('2018-11-29'))
|
||||
->setEnd(new DateTime())
|
||||
->setDuration(3600)
|
||||
->setRate(293.27)
|
||||
->setUser($user)
|
||||
->setActivity((new Activity())->setName('sdsd'))
|
||||
->setProject($project1);
|
||||
$timesheet->setBegin(new DateTime('2018-11-29'));
|
||||
$timesheet->setEnd(new DateTime());
|
||||
$timesheet->setDuration(3600);
|
||||
$timesheet->setRate(293.27);
|
||||
$timesheet->setUser($user);
|
||||
$timesheet->setActivity((new Activity())->setName('sdsd'));
|
||||
$timesheet->setProject($project1);
|
||||
|
||||
$timesheet2 = new Timesheet();
|
||||
$timesheet2
|
||||
->setBegin(new DateTime('2018-11-28'))
|
||||
->setEnd(new DateTime())
|
||||
->setDuration(400)
|
||||
->setRate(84.75)
|
||||
->setUser($user)
|
||||
->setActivity((new Activity())->setName('bar'))
|
||||
->setProject($project2);
|
||||
$timesheet2->setBegin(new DateTime('2018-11-28'));
|
||||
$timesheet2->setEnd(new DateTime());
|
||||
$timesheet2->setDuration(400);
|
||||
$timesheet2->setRate(84.75);
|
||||
$timesheet2->setUser($user);
|
||||
$timesheet2->setActivity((new Activity())->setName('bar'));
|
||||
$timesheet2->setProject($project2);
|
||||
|
||||
$timesheet3 = new Timesheet();
|
||||
$timesheet3
|
||||
->setBegin(new DateTime('2018-11-29'))
|
||||
->setEnd(new DateTime())
|
||||
->setDuration(1800)
|
||||
->setRate(111.11)
|
||||
->setUser($user)
|
||||
->setActivity((new Activity())->setName('foo'))
|
||||
->setProject($project1);
|
||||
$timesheet3->setBegin(new DateTime('2018-11-29'));
|
||||
$timesheet3->setEnd(new DateTime());
|
||||
$timesheet3->setDuration(1800);
|
||||
$timesheet3->setRate(111.11);
|
||||
$timesheet3->setUser($user);
|
||||
$timesheet3->setActivity((new Activity())->setName('foo'));
|
||||
$timesheet3->setProject($project1);
|
||||
|
||||
$timesheet4 = new Timesheet();
|
||||
$timesheet4
|
||||
->setBegin(new DateTime('2018-11-08'))
|
||||
->setEnd(new DateTime())
|
||||
->setDuration(400)
|
||||
->setRate(1947.99)
|
||||
->setUser($user)
|
||||
->setActivity((new Activity())->setName('blub'))
|
||||
->setProject($project2);
|
||||
$timesheet4->setBegin(new DateTime('2018-11-08'));
|
||||
$timesheet4->setEnd(new DateTime());
|
||||
$timesheet4->setDuration(400);
|
||||
$timesheet4->setRate(1947.99);
|
||||
$timesheet4->setUser($user);
|
||||
$timesheet4->setActivity((new Activity())->setName('blub'));
|
||||
$timesheet4->setProject($project2);
|
||||
|
||||
$timesheet5 = new Timesheet();
|
||||
$timesheet5
|
||||
->setBegin(new DateTime('2018-11-28'))
|
||||
->setEnd(new DateTime())
|
||||
->setDuration(400)
|
||||
->setRate(84)
|
||||
->setUser(new User())
|
||||
->setActivity(new Activity())
|
||||
->setProject($project3);
|
||||
$timesheet5->setBegin(new DateTime('2018-11-28'));
|
||||
$timesheet5->setEnd(new DateTime());
|
||||
$timesheet5->setDuration(400);
|
||||
$timesheet5->setRate(84);
|
||||
$timesheet5->setUser(new User());
|
||||
$timesheet5->setActivity(new Activity());
|
||||
$timesheet5->setProject($project3);
|
||||
|
||||
$entries = [$timesheet, $timesheet2, $timesheet3, $timesheet4, $timesheet5];
|
||||
|
||||
|
||||
@@ -57,54 +57,49 @@ class ProjectUserInvoiceCalculatorTest extends AbstractCalculatorTestCase
|
||||
$project3->method('getId')->willReturn(3);
|
||||
|
||||
$timesheet = new Timesheet();
|
||||
$timesheet
|
||||
->setBegin(new DateTime('2018-11-29'))
|
||||
->setEnd(new DateTime())
|
||||
->setDuration(3600)
|
||||
->setRate(293.27)
|
||||
->setUser($user1)
|
||||
->setActivity((new Activity())->setName('sdsd'))
|
||||
->setProject($project1);
|
||||
$timesheet->setBegin(new DateTime('2018-11-29'));
|
||||
$timesheet->setEnd(new DateTime());
|
||||
$timesheet->setDuration(3600);
|
||||
$timesheet->setRate(293.27);
|
||||
$timesheet->setUser($user1);
|
||||
$timesheet->setActivity((new Activity())->setName('sdsd'));
|
||||
$timesheet->setProject($project1);
|
||||
|
||||
$timesheet2 = new Timesheet();
|
||||
$timesheet2
|
||||
->setBegin(new DateTime('2018-11-28'))
|
||||
->setEnd(new DateTime())
|
||||
->setDuration(400)
|
||||
->setRate(84.75)
|
||||
->setUser($user1)
|
||||
->setActivity((new Activity())->setName('bar'))
|
||||
->setProject($project2);
|
||||
$timesheet2->setBegin(new DateTime('2018-11-28'));
|
||||
$timesheet2->setEnd(new DateTime());
|
||||
$timesheet2->setDuration(400);
|
||||
$timesheet2->setRate(84.75);
|
||||
$timesheet2->setUser($user1);
|
||||
$timesheet2->setActivity((new Activity())->setName('bar'));
|
||||
$timesheet2->setProject($project2);
|
||||
|
||||
$timesheet3 = new Timesheet();
|
||||
$timesheet3
|
||||
->setBegin(new DateTime('2018-11-29'))
|
||||
->setEnd(new DateTime())
|
||||
->setDuration(1800)
|
||||
->setRate(111.11)
|
||||
->setUser($user1)
|
||||
->setActivity((new Activity())->setName('foo'))
|
||||
->setProject($project1);
|
||||
$timesheet3->setBegin(new DateTime('2018-11-29'));
|
||||
$timesheet3->setEnd(new DateTime());
|
||||
$timesheet3->setDuration(1800);
|
||||
$timesheet3->setRate(111.11);
|
||||
$timesheet3->setUser($user1);
|
||||
$timesheet3->setActivity((new Activity())->setName('foo'));
|
||||
$timesheet3->setProject($project1);
|
||||
|
||||
$timesheet4 = new Timesheet();
|
||||
$timesheet4
|
||||
->setBegin(new DateTime('2018-11-08'))
|
||||
->setEnd(new DateTime())
|
||||
->setDuration(400)
|
||||
->setRate(1947.99)
|
||||
->setUser($user1)
|
||||
->setActivity((new Activity())->setName('blub'))
|
||||
->setProject($project2);
|
||||
$timesheet4->setBegin(new DateTime('2018-11-08'));
|
||||
$timesheet4->setEnd(new DateTime());
|
||||
$timesheet4->setDuration(400);
|
||||
$timesheet4->setRate(1947.99);
|
||||
$timesheet4->setUser($user1);
|
||||
$timesheet4->setActivity((new Activity())->setName('blub'));
|
||||
$timesheet4->setProject($project2);
|
||||
|
||||
$timesheet5 = new Timesheet();
|
||||
$timesheet5
|
||||
->setBegin(new DateTime('2018-11-28'))
|
||||
->setEnd(new DateTime())
|
||||
->setDuration(400)
|
||||
->setRate(84)
|
||||
->setUser($user2)
|
||||
->setActivity(new Activity())
|
||||
->setProject($project3);
|
||||
$timesheet5->setBegin(new DateTime('2018-11-28'));
|
||||
$timesheet5->setEnd(new DateTime());
|
||||
$timesheet5->setDuration(400);
|
||||
$timesheet5->setRate(84);
|
||||
$timesheet5->setUser($user2);
|
||||
$timesheet5->setActivity(new Activity());
|
||||
$timesheet5->setProject($project3);
|
||||
|
||||
$entries = [$timesheet, $timesheet2, $timesheet3, $timesheet4, $timesheet5];
|
||||
|
||||
|
||||
@@ -49,43 +49,37 @@ class ShortInvoiceCalculatorTest extends AbstractCalculatorTestCase
|
||||
$activity->setProject($project);
|
||||
|
||||
$timesheet = new Timesheet();
|
||||
$timesheet
|
||||
->setDuration(3600)
|
||||
->setRate(293.27)
|
||||
->setHourlyRate(293.27)
|
||||
->setUser(new User())
|
||||
->setActivity($activity)
|
||||
->setProject($project)
|
||||
->setBegin(new \DateTime('2018-11-29'))
|
||||
->setEnd(new \DateTime())
|
||||
->addTag((new Tag())->setName('foo'))
|
||||
->addTag((new Tag())->setName('bar'))
|
||||
;
|
||||
$timesheet->setDuration(3600);
|
||||
$timesheet->setRate(293.27);
|
||||
$timesheet->setHourlyRate(293.27);
|
||||
$timesheet->setUser(new User());
|
||||
$timesheet->setActivity($activity);
|
||||
$timesheet->setProject($project);
|
||||
$timesheet->setBegin(new \DateTime('2018-11-29'));
|
||||
$timesheet->setEnd(new \DateTime());
|
||||
$timesheet->addTag((new Tag())->setName('foo'));
|
||||
$timesheet->addTag((new Tag())->setName('bar'));
|
||||
|
||||
$timesheet2 = new Timesheet();
|
||||
$timesheet2
|
||||
->setDuration(400)
|
||||
->setRate(32.59)
|
||||
->setHourlyRate(293.27)
|
||||
->setUser(new User())
|
||||
->setActivity($activity)
|
||||
->setProject($project)
|
||||
->setBegin(new \DateTime('2018-11-28'))
|
||||
->setEnd(new \DateTime())
|
||||
->addTag((new Tag())->setName('bar1'))
|
||||
;
|
||||
$timesheet2->setDuration(400);
|
||||
$timesheet2->setRate(32.59);
|
||||
$timesheet2->setHourlyRate(293.27);
|
||||
$timesheet2->setUser(new User());
|
||||
$timesheet2->setActivity($activity);
|
||||
$timesheet2->setProject($project);
|
||||
$timesheet2->setBegin(new \DateTime('2018-11-28'));
|
||||
$timesheet2->setEnd(new \DateTime());
|
||||
$timesheet2->addTag((new Tag())->setName('bar1'));
|
||||
|
||||
$timesheet3 = new Timesheet();
|
||||
$timesheet3
|
||||
->setDuration(1800)
|
||||
->setRate(146.64)
|
||||
->setHourlyRate(293.27)
|
||||
->setUser(new User())
|
||||
->setActivity($activity)
|
||||
->setProject($project)
|
||||
->setBegin(new \DateTime('2018-11-29'))
|
||||
->setEnd(new \DateTime())
|
||||
;
|
||||
$timesheet3->setDuration(1800);
|
||||
$timesheet3->setRate(146.64);
|
||||
$timesheet3->setHourlyRate(293.27);
|
||||
$timesheet3->setUser(new User());
|
||||
$timesheet3->setActivity($activity);
|
||||
$timesheet3->setProject($project);
|
||||
$timesheet3->setBegin(new \DateTime('2018-11-29'));
|
||||
$timesheet3->setEnd(new \DateTime());
|
||||
|
||||
$entries = [$timesheet, $timesheet2, $timesheet3];
|
||||
|
||||
@@ -134,40 +128,34 @@ class ShortInvoiceCalculatorTest extends AbstractCalculatorTestCase
|
||||
$activity->setProject($project);
|
||||
|
||||
$timesheet = new Timesheet();
|
||||
$timesheet
|
||||
->setDuration(3600)
|
||||
->setRate(293.27)
|
||||
->setHourlyRate(293.27)
|
||||
->setUser(new User())
|
||||
->setActivity($activity)
|
||||
->setProject($project)
|
||||
->setBegin(new \DateTime())
|
||||
->setEnd(new \DateTime())
|
||||
;
|
||||
$timesheet->setDuration(3600);
|
||||
$timesheet->setRate(293.27);
|
||||
$timesheet->setHourlyRate(293.27);
|
||||
$timesheet->setUser(new User());
|
||||
$timesheet->setActivity($activity);
|
||||
$timesheet->setProject($project);
|
||||
$timesheet->setBegin(new \DateTime());
|
||||
$timesheet->setEnd(new \DateTime());
|
||||
|
||||
$timesheet2 = new Timesheet();
|
||||
$timesheet2
|
||||
->setDuration(400)
|
||||
->setRate(84)
|
||||
->setHourlyRate(756.00)
|
||||
->setUser(new User())
|
||||
->setActivity($activity)
|
||||
->setProject($project)
|
||||
->setBegin(new \DateTime())
|
||||
->setEnd(new \DateTime())
|
||||
;
|
||||
$timesheet2->setDuration(400);
|
||||
$timesheet2->setRate(84);
|
||||
$timesheet2->setHourlyRate(756.00);
|
||||
$timesheet2->setUser(new User());
|
||||
$timesheet2->setActivity($activity);
|
||||
$timesheet2->setProject($project);
|
||||
$timesheet2->setBegin(new \DateTime());
|
||||
$timesheet2->setEnd(new \DateTime());
|
||||
|
||||
$timesheet3 = new Timesheet();
|
||||
$timesheet3
|
||||
->setDuration(1800)
|
||||
->setRate(111.11)
|
||||
->setHourlyRate(222.22)
|
||||
->setUser(new User())
|
||||
->setActivity($activity)
|
||||
->setProject($project)
|
||||
->setBegin(new \DateTime())
|
||||
->setEnd(new \DateTime())
|
||||
;
|
||||
$timesheet3->setDuration(1800);
|
||||
$timesheet3->setRate(111.11);
|
||||
$timesheet3->setHourlyRate(222.22);
|
||||
$timesheet3->setUser(new User());
|
||||
$timesheet3->setActivity($activity);
|
||||
$timesheet3->setProject($project);
|
||||
$timesheet3->setBegin(new \DateTime());
|
||||
$timesheet3->setEnd(new \DateTime());
|
||||
|
||||
$entries = [$timesheet, $timesheet2, $timesheet3];
|
||||
|
||||
@@ -212,38 +200,32 @@ class ShortInvoiceCalculatorTest extends AbstractCalculatorTestCase
|
||||
$activity->setProject($project);
|
||||
|
||||
$timesheet = new Timesheet();
|
||||
$timesheet
|
||||
->setDuration(3600)
|
||||
->setRate(293.27)
|
||||
->setUser(new User())
|
||||
->setActivity($activity)
|
||||
->setProject($project)
|
||||
->setBegin(new \DateTime())
|
||||
->setEnd(new \DateTime())
|
||||
;
|
||||
$timesheet->setDuration(3600);
|
||||
$timesheet->setRate(293.27);
|
||||
$timesheet->setUser(new User());
|
||||
$timesheet->setActivity($activity);
|
||||
$timesheet->setProject($project);
|
||||
$timesheet->setBegin(new \DateTime());
|
||||
$timesheet->setEnd(new \DateTime());
|
||||
|
||||
$timesheet2 = new Timesheet();
|
||||
$timesheet2
|
||||
->setDuration(400)
|
||||
->setFixedRate(84)
|
||||
->setRate(84)
|
||||
->setUser(new User())
|
||||
->setActivity($activity)
|
||||
->setProject($project)
|
||||
->setBegin(new \DateTime())
|
||||
->setEnd(new \DateTime())
|
||||
;
|
||||
$timesheet2->setDuration(400);
|
||||
$timesheet2->setFixedRate(84);
|
||||
$timesheet2->setRate(84);
|
||||
$timesheet2->setUser(new User());
|
||||
$timesheet2->setActivity($activity);
|
||||
$timesheet2->setProject($project);
|
||||
$timesheet2->setBegin(new \DateTime());
|
||||
$timesheet2->setEnd(new \DateTime());
|
||||
|
||||
$timesheet3 = new Timesheet();
|
||||
$timesheet3
|
||||
->setDuration(1800)
|
||||
->setRate(111.11)
|
||||
->setUser(new User())
|
||||
->setActivity($activity)
|
||||
->setProject($project)
|
||||
->setBegin(new \DateTime())
|
||||
->setEnd(new \DateTime())
|
||||
;
|
||||
$timesheet3->setDuration(1800);
|
||||
$timesheet3->setRate(111.11);
|
||||
$timesheet3->setUser(new User());
|
||||
$timesheet3->setActivity($activity);
|
||||
$timesheet3->setProject($project);
|
||||
$timesheet3->setBegin(new \DateTime());
|
||||
$timesheet3->setEnd(new \DateTime());
|
||||
|
||||
$entries = [$timesheet, $timesheet2, $timesheet3];
|
||||
|
||||
|
||||
@@ -52,54 +52,49 @@ class UserInvoiceCalculatorTest extends AbstractCalculatorTestCase
|
||||
$user3->method('getId')->willReturn(3);
|
||||
|
||||
$timesheet = new Timesheet();
|
||||
$timesheet
|
||||
->setBegin(new \DateTime('2018-11-29'))
|
||||
->setEnd(new \DateTime())
|
||||
->setDuration(3600)
|
||||
->setRate(293.27)
|
||||
->setUser($user1)
|
||||
->setActivity($activity)
|
||||
->setProject((new Project())->setName('bar'));
|
||||
$timesheet->setBegin(new \DateTime('2018-11-29'));
|
||||
$timesheet->setEnd(new \DateTime());
|
||||
$timesheet->setDuration(3600);
|
||||
$timesheet->setRate(293.27);
|
||||
$timesheet->setUser($user1);
|
||||
$timesheet->setActivity($activity);
|
||||
$timesheet->setProject((new Project())->setName('bar'));
|
||||
|
||||
$timesheet2 = new Timesheet();
|
||||
$timesheet2
|
||||
->setBegin(new \DateTime('2018-11-28'))
|
||||
->setEnd(new \DateTime())
|
||||
->setDuration(400)
|
||||
->setRate(84.75)
|
||||
->setUser($user2)
|
||||
->setActivity($activity)
|
||||
->setProject((new Project())->setName('bar'));
|
||||
$timesheet2->setBegin(new \DateTime('2018-11-28'));
|
||||
$timesheet2->setEnd(new \DateTime());
|
||||
$timesheet2->setDuration(400);
|
||||
$timesheet2->setRate(84.75);
|
||||
$timesheet2->setUser($user2);
|
||||
$timesheet2->setActivity($activity);
|
||||
$timesheet2->setProject((new Project())->setName('bar'));
|
||||
|
||||
$timesheet3 = new Timesheet();
|
||||
$timesheet3
|
||||
->setBegin(new \DateTime('2018-11-08'))
|
||||
->setEnd(new \DateTime())
|
||||
->setDuration(1800)
|
||||
->setRate(111.11)
|
||||
->setUser($user1)
|
||||
->setActivity($activity)
|
||||
->setProject((new Project())->setName('bar'));
|
||||
$timesheet3->setBegin(new \DateTime('2018-11-08'));
|
||||
$timesheet3->setEnd(new \DateTime());
|
||||
$timesheet3->setDuration(1800);
|
||||
$timesheet3->setRate(111.11);
|
||||
$timesheet3->setUser($user1);
|
||||
$timesheet3->setActivity($activity);
|
||||
$timesheet3->setProject((new Project())->setName('bar'));
|
||||
|
||||
$timesheet4 = new Timesheet();
|
||||
$timesheet4
|
||||
->setBegin(new \DateTime('2018-11-28'))
|
||||
->setEnd(new \DateTime())
|
||||
->setDuration(400)
|
||||
->setRate(1947.99)
|
||||
->setUser($user2)
|
||||
->setActivity($activity)
|
||||
->setProject((new Project())->setName('bar'));
|
||||
$timesheet4->setBegin(new \DateTime('2018-11-28'));
|
||||
$timesheet4->setEnd(new \DateTime());
|
||||
$timesheet4->setDuration(400);
|
||||
$timesheet4->setRate(1947.99);
|
||||
$timesheet4->setUser($user2);
|
||||
$timesheet4->setActivity($activity);
|
||||
$timesheet4->setProject((new Project())->setName('bar'));
|
||||
|
||||
$timesheet5 = new Timesheet();
|
||||
$timesheet5
|
||||
->setBegin(new \DateTime())
|
||||
->setEnd(new \DateTime())
|
||||
->setDuration(400)
|
||||
->setRate(84)
|
||||
->setUser($user3)
|
||||
->setActivity($activity)
|
||||
->setProject((new Project())->setName('bar'));
|
||||
$timesheet5->setBegin(new \DateTime());
|
||||
$timesheet5->setEnd(new \DateTime());
|
||||
$timesheet5->setDuration(400);
|
||||
$timesheet5->setRate(84);
|
||||
$timesheet5->setUser($user3);
|
||||
$timesheet5->setActivity($activity);
|
||||
$timesheet5->setProject((new Project())->setName('bar'));
|
||||
|
||||
$entries = [$timesheet, $timesheet2, $timesheet3, $timesheet4, $timesheet5];
|
||||
|
||||
|
||||
@@ -57,54 +57,49 @@ class WeeklyInvoiceCalculatorTest extends AbstractCalculatorTestCase
|
||||
$end = new \DateTime('now', $timezone);
|
||||
|
||||
$timesheet = new Timesheet();
|
||||
$timesheet
|
||||
->setBegin(new DateTime('2018-11-26 12:00:00', $timezone))
|
||||
->setEnd(clone $end)
|
||||
->setDuration(3600)
|
||||
->setRate(293.27)
|
||||
->setUser($user)
|
||||
->setActivity((new Activity())->setName('sdsd'))
|
||||
->setProject($project1);
|
||||
$timesheet->setBegin(new DateTime('2018-11-26 12:00:00', $timezone));
|
||||
$timesheet->setEnd(clone $end);
|
||||
$timesheet->setDuration(3600);
|
||||
$timesheet->setRate(293.27);
|
||||
$timesheet->setUser($user);
|
||||
$timesheet->setActivity((new Activity())->setName('sdsd'));
|
||||
$timesheet->setProject($project1);
|
||||
|
||||
$timesheet2 = new Timesheet();
|
||||
$timesheet2
|
||||
->setBegin(new DateTime('2018-11-26 12:00:00', $timezone))
|
||||
->setEnd(clone $end)
|
||||
->setDuration(400)
|
||||
->setRate(84.75)
|
||||
->setUser($user)
|
||||
->setActivity((new Activity())->setName('bar'))
|
||||
->setProject($project2);
|
||||
$timesheet2->setBegin(new DateTime('2018-11-26 12:00:00', $timezone));
|
||||
$timesheet2->setEnd(clone $end);
|
||||
$timesheet2->setDuration(400);
|
||||
$timesheet2->setRate(84.75);
|
||||
$timesheet2->setUser($user);
|
||||
$timesheet2->setActivity((new Activity())->setName('bar'));
|
||||
$timesheet2->setProject($project2);
|
||||
|
||||
$timesheet3 = new Timesheet();
|
||||
$timesheet3
|
||||
->setBegin(new DateTime('2018-11-25 12:00:00', $timezone))
|
||||
->setEnd(clone $end)
|
||||
->setDuration(1800)
|
||||
->setRate(111.11)
|
||||
->setUser($user)
|
||||
->setActivity((new Activity())->setName('foo'))
|
||||
->setProject($project1);
|
||||
$timesheet3->setBegin(new DateTime('2018-11-25 12:00:00', $timezone));
|
||||
$timesheet3->setEnd(clone $end);
|
||||
$timesheet3->setDuration(1800);
|
||||
$timesheet3->setRate(111.11);
|
||||
$timesheet3->setUser($user);
|
||||
$timesheet3->setActivity((new Activity())->setName('foo'));
|
||||
$timesheet3->setProject($project1);
|
||||
|
||||
$timesheet4 = new Timesheet();
|
||||
$timesheet4
|
||||
->setBegin(new DateTime('2018-11-25 12:00:00', $timezone))
|
||||
->setEnd(clone $end)
|
||||
->setDuration(400)
|
||||
->setRate(1947.99)
|
||||
->setUser($user)
|
||||
->setActivity((new Activity())->setName('blub'))
|
||||
->setProject($project2);
|
||||
$timesheet4->setBegin(new DateTime('2018-11-25 12:00:00', $timezone));
|
||||
$timesheet4->setEnd(clone $end);
|
||||
$timesheet4->setDuration(400);
|
||||
$timesheet4->setRate(1947.99);
|
||||
$timesheet4->setUser($user);
|
||||
$timesheet4->setActivity((new Activity())->setName('blub'));
|
||||
$timesheet4->setProject($project2);
|
||||
|
||||
$timesheet5 = new Timesheet();
|
||||
$timesheet5
|
||||
->setBegin(new DateTime('2018-11-25 12:00:00', $timezone))
|
||||
->setEnd(clone $end)
|
||||
->setDuration(400)
|
||||
->setRate(84)
|
||||
->setUser(new User())
|
||||
->setActivity(new Activity())
|
||||
->setProject($project3);
|
||||
$timesheet5->setBegin(new DateTime('2018-11-25 12:00:00', $timezone));
|
||||
$timesheet5->setEnd(clone $end);
|
||||
$timesheet5->setDuration(400);
|
||||
$timesheet5->setRate(84);
|
||||
$timesheet5->setUser(new User());
|
||||
$timesheet5->setActivity(new Activity());
|
||||
$timesheet5->setProject($project3);
|
||||
|
||||
$entries = [$timesheet, $timesheet2, $timesheet3, $timesheet4, $timesheet5];
|
||||
|
||||
|
||||
@@ -43,7 +43,7 @@ class InvoiceModelCustomerHydratorTest extends TestCase
|
||||
'customer.vat' => '',
|
||||
'customer.vat_id' => '',
|
||||
'customer.number' => '',
|
||||
'customer.country' => null,
|
||||
'customer.country' => 'AT',
|
||||
'customer.homepage' => '',
|
||||
'customer.comment' => '',
|
||||
'customer.email' => '',
|
||||
|
||||
@@ -12,6 +12,7 @@ namespace App\Tests\Invoice\Hydrator;
|
||||
use App\Invoice\Hydrator\InvoiceModelDefaultHydrator;
|
||||
use App\Tests\Invoice\Renderer\RendererTestTrait;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use ReflectionObject;
|
||||
|
||||
/**
|
||||
* @covers \App\Invoice\Hydrator\InvoiceModelDefaultHydrator
|
||||
@@ -30,6 +31,23 @@ class InvoiceModelDefaultHydratorTest extends TestCase
|
||||
$this->assertModelStructure($result);
|
||||
}
|
||||
|
||||
public function testHydrateThrowsOnMissing(): void
|
||||
{
|
||||
$this->expectException(\InvalidArgumentException::class);
|
||||
$this->expectExceptionMessage('InvoiceModel needs a template');
|
||||
|
||||
$model = $this->getInvoiceModel();
|
||||
|
||||
$obj = new ReflectionObject($model);
|
||||
$prop = $obj->getProperty('template');
|
||||
$prop->setAccessible(true);
|
||||
$prop->setValue($model, null);
|
||||
|
||||
$sut = new InvoiceModelDefaultHydrator();
|
||||
|
||||
$sut->hydrate($model);
|
||||
}
|
||||
|
||||
protected function assertModelStructure(array $model, bool $hasProject = true): void
|
||||
{
|
||||
$keys = [
|
||||
@@ -60,6 +78,8 @@ class InvoiceModelDefaultHydratorTest extends TestCase
|
||||
'invoice.subtotal_plain',
|
||||
'template.name',
|
||||
'template.company',
|
||||
'template.country',
|
||||
'template.country_name',
|
||||
'template.address',
|
||||
'template.title',
|
||||
'template.payment_terms',
|
||||
|
||||
@@ -111,6 +111,7 @@ class DebugRendererTest extends TestCase
|
||||
'invoice.subtotal_plain',
|
||||
'template.name',
|
||||
'template.company',
|
||||
'template.country',
|
||||
'template.address',
|
||||
'template.title',
|
||||
'template.payment_terms',
|
||||
@@ -118,6 +119,7 @@ class DebugRendererTest extends TestCase
|
||||
'template.vat_id',
|
||||
'template.contact',
|
||||
'template.payment_details',
|
||||
'template.country_name',
|
||||
'query.day',
|
||||
'query.month',
|
||||
'query.month_number',
|
||||
|
||||
@@ -88,6 +88,7 @@ trait RendererTestTrait
|
||||
$customer = new Customer('customer,with/special#name');
|
||||
$customer->setAddress('Foo' . PHP_EOL . 'Street' . PHP_EOL . '1111 City');
|
||||
$customer->setCurrency('EUR');
|
||||
$customer->setCountry('AT');
|
||||
$customer->setMetaField((new CustomerMeta())->setName('foo-customer')->setValue('bar-customer')->setIsVisible(true));
|
||||
|
||||
$template = new InvoiceTemplate();
|
||||
@@ -152,61 +153,54 @@ trait RendererTestTrait
|
||||
$user2->method('getVisiblePreferences')->willReturn([$pref1, $pref2]);
|
||||
|
||||
$timesheet = new Timesheet();
|
||||
$timesheet
|
||||
->setDuration(3600)
|
||||
->setRate(293.27)
|
||||
->setUser($user1)
|
||||
->setActivity($activity)
|
||||
->setProject($project)
|
||||
->setBegin(new \DateTime('2020-12-13 14:00:00'))
|
||||
->setEnd(new \DateTime('2020-12-13 15:00:00'))
|
||||
->setMetaField((new TimesheetMeta())->setName('foo-timesheet')->setValue('bar-timesheet')->setIsVisible(true));
|
||||
$timesheet->setDuration(3600);
|
||||
$timesheet->setRate(293.27);
|
||||
$timesheet->setUser($user1);
|
||||
$timesheet->setActivity($activity);
|
||||
$timesheet->setProject($project);
|
||||
$timesheet->setBegin(new \DateTime('2020-12-13 14:00:00'));
|
||||
$timesheet->setEnd(new \DateTime('2020-12-13 15:00:00'));
|
||||
$timesheet->setMetaField((new TimesheetMeta())->setName('foo-timesheet')->setValue('bar-timesheet')->setIsVisible(true));
|
||||
|
||||
$timesheet2 = new Timesheet();
|
||||
$timesheet2
|
||||
->setDuration(400)
|
||||
->setRate(84.75)
|
||||
->setUser($user2)
|
||||
->setActivity($activity)
|
||||
->setProject($project)
|
||||
->setBegin(new \DateTime('2020-08-13 14:00:00'))
|
||||
->setEnd(new \DateTime('2020-08-13 14:06:40'))
|
||||
->setMetaField((new TimesheetMeta())->setName('foo-timesheet')->setValue('bar-timesheet'))
|
||||
->setMetaField((new TimesheetMeta())->setName('foo-timesheet2')->setValue('bar-timesheet2')->setIsVisible(true))
|
||||
;
|
||||
$timesheet2->setDuration(400);
|
||||
$timesheet2->setRate(84.75);
|
||||
$timesheet2->setUser($user2);
|
||||
$timesheet2->setActivity($activity);
|
||||
$timesheet2->setProject($project);
|
||||
$timesheet2->setBegin(new \DateTime('2020-08-13 14:00:00'));
|
||||
$timesheet2->setEnd(new \DateTime('2020-08-13 14:06:40'));
|
||||
$timesheet2->setMetaField((new TimesheetMeta())->setName('foo-timesheet')->setValue('bar-timesheet'));
|
||||
$timesheet2->setMetaField((new TimesheetMeta())->setName('foo-timesheet2')->setValue('bar-timesheet2')->setIsVisible(true));
|
||||
|
||||
$timesheet3 = new Timesheet();
|
||||
$timesheet3
|
||||
->setDuration(1800)
|
||||
->setRate(111.11)
|
||||
->setUser($user1)
|
||||
->setActivity($activity2)
|
||||
->setDescription('== jhg ljhg ') // make sure that spreadsheets don't render it as formula
|
||||
->setProject($project2)
|
||||
->setBegin(new \DateTime('2020-08-12 18:00:00'))
|
||||
->setEnd(new \DateTime('2020-08-12 18:30:00'))
|
||||
->setMetaField((new TimesheetMeta())->setName('foo-timesheet')->setValue('bar-timesheet1')->setIsVisible(true))
|
||||
;
|
||||
$timesheet3->setDuration(1800);
|
||||
$timesheet3->setRate(111.11);
|
||||
$timesheet3->setUser($user1);
|
||||
$timesheet3->setActivity($activity2);
|
||||
$timesheet3->setDescription('== jhg ljhg '); // make sure that spreadsheets don't render it as formula
|
||||
$timesheet3->setProject($project2);
|
||||
$timesheet3->setBegin(new \DateTime('2020-08-12 18:00:00'));
|
||||
$timesheet3->setEnd(new \DateTime('2020-08-12 18:30:00'));
|
||||
$timesheet3->setMetaField((new TimesheetMeta())->setName('foo-timesheet')->setValue('bar-timesheet1')->setIsVisible(true));
|
||||
|
||||
$timesheet4 = new Timesheet();
|
||||
$timesheet4
|
||||
->setDuration(400)
|
||||
->setRate(1947.99)
|
||||
->setUser($user2)
|
||||
->setActivity($activity)
|
||||
->setProject($project)
|
||||
->setBegin(new \DateTime('2020-12-13 14:00:00'))
|
||||
->setEnd(new \DateTime('2020-12-13 14:06:40'))
|
||||
->setDescription(
|
||||
"foo\n" .
|
||||
"foo\r\n" .
|
||||
'foo' . PHP_EOL .
|
||||
"bar\n" .
|
||||
"bar\r\n" .
|
||||
'Hello'
|
||||
)
|
||||
->setMetaField((new TimesheetMeta())->setName('foo-timesheet3')->setValue('bluuuub')->setIsVisible(true))
|
||||
;
|
||||
$timesheet4->setDuration(400);
|
||||
$timesheet4->setRate(1947.99);
|
||||
$timesheet4->setUser($user2);
|
||||
$timesheet4->setActivity($activity);
|
||||
$timesheet4->setProject($project);
|
||||
$timesheet4->setBegin(new \DateTime('2020-12-13 14:00:00'));
|
||||
$timesheet4->setEnd(new \DateTime('2020-12-13 14:06:40'));
|
||||
$timesheet4->setDescription(
|
||||
"foo\n" .
|
||||
"foo\r\n" .
|
||||
'foo' . PHP_EOL .
|
||||
"bar\n" .
|
||||
"bar\r\n" .
|
||||
'Hello'
|
||||
);
|
||||
$timesheet4->setMetaField((new TimesheetMeta())->setName('foo-timesheet3')->setValue('bluuuub')->setIsVisible(true));
|
||||
|
||||
$userKevin = new User();
|
||||
$userKevin->setUserIdentifier('kevin');
|
||||
@@ -214,23 +208,21 @@ trait RendererTestTrait
|
||||
$userKevin->addPreference($pref2);
|
||||
|
||||
$timesheet5 = new Timesheet();
|
||||
$timesheet5
|
||||
->setDuration(400)
|
||||
->setFixedRate(84)
|
||||
->setUser($userKevin)
|
||||
->setActivity($activity)
|
||||
->setProject($project)
|
||||
->setBegin(new \DateTime('2021-03-12 12:13:00'))
|
||||
->setEnd(new \DateTime('2021-03-12 12:17:40'))
|
||||
->setDescription(
|
||||
"foo\n" .
|
||||
"foo\r\n" .
|
||||
'foo' . PHP_EOL .
|
||||
"bar\n" .
|
||||
"bar\r\n" .
|
||||
'Hello'
|
||||
)
|
||||
;
|
||||
$timesheet5->setDuration(400);
|
||||
$timesheet5->setFixedRate(84);
|
||||
$timesheet5->setUser($userKevin);
|
||||
$timesheet5->setActivity($activity);
|
||||
$timesheet5->setProject($project);
|
||||
$timesheet5->setBegin(new \DateTime('2021-03-12 12:13:00'));
|
||||
$timesheet5->setEnd(new \DateTime('2021-03-12 12:17:40'));
|
||||
$timesheet5->setDescription(
|
||||
"foo\n" .
|
||||
"foo\r\n" .
|
||||
'foo' . PHP_EOL .
|
||||
"bar\n" .
|
||||
"bar\r\n" .
|
||||
'Hello'
|
||||
);
|
||||
|
||||
$entries = [$timesheet, $timesheet2, $timesheet3, $timesheet4, $timesheet5];
|
||||
|
||||
@@ -279,6 +271,7 @@ trait RendererTestTrait
|
||||
$user->addPreference(new UserPreference('hello', 'world'));
|
||||
|
||||
$customer = new Customer('customer,with/special#name');
|
||||
$customer->setCountry('DE');
|
||||
$customer->setCurrency('USD');
|
||||
$customer->setMetaField((new CustomerMeta())->setName('foo-customer')->setValue('bar-customer')->setIsVisible(true));
|
||||
|
||||
@@ -307,15 +300,13 @@ trait RendererTestTrait
|
||||
$user1->method('getVisiblePreferences')->willReturn([$pref1, $pref2]);
|
||||
|
||||
$timesheet = new Timesheet();
|
||||
$timesheet
|
||||
->setDuration(3600)
|
||||
->setRate(293.27)
|
||||
->setUser($user1)
|
||||
->setActivity($activity)
|
||||
->setProject($project)
|
||||
->setBegin(new \DateTime('2020-08-12 18:00:00'))
|
||||
->setEnd(new \DateTime('2021-03-12 18:30:00'))
|
||||
;
|
||||
$timesheet->setDuration(3600);
|
||||
$timesheet->setRate(293.27);
|
||||
$timesheet->setUser($user1);
|
||||
$timesheet->setActivity($activity);
|
||||
$timesheet->setProject($project);
|
||||
$timesheet->setBegin(new \DateTime('2020-08-12 18:00:00'));
|
||||
$timesheet->setEnd(new \DateTime('2021-03-12 18:30:00'));
|
||||
|
||||
$entries = [$timesheet];
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
|
||||
namespace App\Tests\Project;
|
||||
|
||||
use App\Configuration\SystemConfiguration;
|
||||
use App\Entity\Customer;
|
||||
use App\Entity\Project;
|
||||
use App\Entity\Team;
|
||||
@@ -38,7 +39,7 @@ class ProjectServiceTest extends TestCase
|
||||
private function getSut(
|
||||
?EventDispatcherInterface $dispatcher = null,
|
||||
?ValidatorInterface $validator = null,
|
||||
bool $copyTeamsOnCreate = false
|
||||
?SystemConfiguration $configuration = null
|
||||
): ProjectService {
|
||||
$repository = $this->createMock(ProjectRepository::class);
|
||||
|
||||
@@ -54,7 +55,11 @@ class ProjectServiceTest extends TestCase
|
||||
$validator->method('validate')->willReturn(new ConstraintViolationList());
|
||||
}
|
||||
|
||||
$configuration = SystemConfigurationFactory::createStub(['project' => ['copy_teams_on_create' => $copyTeamsOnCreate]]);
|
||||
if ($configuration === null) {
|
||||
$configuration = SystemConfigurationFactory::createStub(
|
||||
['project' => ['copy_teams_on_create' => false]]
|
||||
);
|
||||
}
|
||||
|
||||
return new ProjectService($repository, $configuration, $dispatcher, $validator);
|
||||
}
|
||||
@@ -151,8 +156,11 @@ class ProjectServiceTest extends TestCase
|
||||
public function testCreateNewProjectCopiesTeam(): void
|
||||
{
|
||||
$dispatcher = $this->createMock(EventDispatcherInterface::class);
|
||||
$configuration = SystemConfigurationFactory::createStub(
|
||||
['project' => ['copy_teams_on_create' => true]]
|
||||
);
|
||||
|
||||
$sut = $this->getSut($dispatcher, null, true);
|
||||
$sut = $this->getSut($dispatcher, null, $configuration);
|
||||
|
||||
$team1 = new Team('foo');
|
||||
$team2 = new Team('bar');
|
||||
@@ -176,4 +184,78 @@ class ProjectServiceTest extends TestCase
|
||||
$project = $sut->createNewProject();
|
||||
self::assertNull($project->getCustomer());
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider getTestData
|
||||
*/
|
||||
public function testProjectNumber(string $format, int|string $expected): void
|
||||
{
|
||||
$configuration = SystemConfigurationFactory::createStub([
|
||||
'project' => [
|
||||
'copy_teams_on_create' => true,
|
||||
'number_format' => $format,
|
||||
]
|
||||
]);
|
||||
|
||||
$sut = $this->getSut(null, null, $configuration);
|
||||
$project = $sut->createNewProject();
|
||||
|
||||
self::assertEquals((string) $expected, $project->getNumber());
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<int, array<int, string|\DateTime|int>>
|
||||
*/
|
||||
public static function getTestData(): array
|
||||
{
|
||||
$dateTime = new \DateTime();
|
||||
|
||||
$yearLong = (int) $dateTime->format('Y');
|
||||
$yearShort = (int) $dateTime->format('y');
|
||||
$monthLong = $dateTime->format('m');
|
||||
$monthShort = (int) $dateTime->format('n');
|
||||
$dayLong = $dateTime->format('d');
|
||||
$dayShort = (int) $dateTime->format('j');
|
||||
|
||||
return [
|
||||
// simple tests for single calls
|
||||
['{pc,1}', '2'],
|
||||
['{pc,2}', '02'],
|
||||
['{pc,3}', '002'],
|
||||
['{pc,4}', '0002'],
|
||||
['{Y}', $yearLong],
|
||||
['{y}', $yearShort],
|
||||
['{M}', $monthLong],
|
||||
['{m}', $monthShort],
|
||||
['{D}', $dayLong],
|
||||
['{d}', $dayShort],
|
||||
// number formatting (not testing the lower case versions, as the tests might break depending on the date)
|
||||
['{Y,6}', '00' . $yearLong],
|
||||
['{M,3}', '0' . $monthLong],
|
||||
['{D,3}', '0' . $dayLong],
|
||||
// increment dates
|
||||
['{YY}', $yearLong + 1],
|
||||
['{YY+1}', $yearLong + 1],
|
||||
['{YY+2}', $yearLong + 2],
|
||||
['{YY+3}', $yearLong + 3],
|
||||
['{YY-1}', $yearLong - 1],
|
||||
['{YY-2}', $yearLong - 2],
|
||||
['{YY-3}', $yearLong - 3],
|
||||
['{yy}', $yearShort + 1],
|
||||
['{yy+1}', $yearShort + 1],
|
||||
['{yy+2}', $yearShort + 2],
|
||||
['{yy+3}', $yearShort + 3],
|
||||
['{yy-1}', $yearShort - 1],
|
||||
['{yy-2}', $yearShort - 2],
|
||||
['{yy-3}', $yearShort - 3],
|
||||
['{MM}', $monthShort + 1], // cast to int removes leading zero
|
||||
['{MM+1}', $monthShort + 1], // cast to int removes leading zero
|
||||
['{MM+2}', $monthShort + 2], // cast to int removes leading zero
|
||||
['{MM+3}', $monthShort + 3], // cast to int removes leading zero
|
||||
['{DD}', $dayShort + 1], // cast to int removes leading zero
|
||||
['{DD+1}', $dayShort + 1], // cast to int removes leading zero
|
||||
['{DD+2}', $dayShort + 2], // cast to int removes leading zero
|
||||
['{DD+3}', $dayShort + 3], // cast to int removes leading zero
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -132,15 +132,13 @@ class RateCalculatorTest extends TestCase
|
||||
$activity->setProject($project);
|
||||
|
||||
$timesheet = new Timesheet();
|
||||
$timesheet
|
||||
->setEnd(new \DateTime())
|
||||
->setHourlyRate($timesheetHourly)
|
||||
->setFixedRate($timesheetFixed)
|
||||
->setActivity($activity)
|
||||
->setProject($project)
|
||||
->setDuration($duration)
|
||||
->setUser($this->getTestUser($userRate, $userInternalRate))
|
||||
;
|
||||
$timesheet->setEnd(new \DateTime());
|
||||
$timesheet->setHourlyRate($timesheetHourly);
|
||||
$timesheet->setFixedRate($timesheetFixed);
|
||||
$timesheet->setActivity($activity);
|
||||
$timesheet->setProject($project);
|
||||
$timesheet->setDuration($duration);
|
||||
$timesheet->setUser($this->getTestUser($userRate, $userInternalRate));
|
||||
|
||||
$rates = [];
|
||||
|
||||
|
||||
@@ -45,7 +45,6 @@ class DateTimeFactoryTest extends TestCase
|
||||
public function testGetStartOfMonth(): void
|
||||
{
|
||||
$expected = new DateTime('now', new DateTimeZone(self::TEST_TIMEZONE));
|
||||
|
||||
$sut = $this->createDateTimeFactory(self::TEST_TIMEZONE);
|
||||
$dateTime = $sut->getStartOfMonth();
|
||||
self::assertEquals(0, $dateTime->format('H'));
|
||||
@@ -55,12 +54,30 @@ class DateTimeFactoryTest extends TestCase
|
||||
self::assertEquals($expected->format('m'), $dateTime->format('m'));
|
||||
self::assertEquals($expected->format('Y'), $dateTime->format('Y'));
|
||||
self::assertEquals(self::TEST_TIMEZONE, $dateTime->getTimezone()->getName());
|
||||
|
||||
$dateTime = $sut->getStartOfMonth('now');
|
||||
self::assertEquals(0, $dateTime->format('H'));
|
||||
self::assertEquals(0, $dateTime->format('i'));
|
||||
self::assertEquals(0, $dateTime->format('s'));
|
||||
self::assertEquals(1, $dateTime->format('d'));
|
||||
self::assertEquals($expected->format('m'), $dateTime->format('m'));
|
||||
self::assertEquals($expected->format('Y'), $dateTime->format('Y'));
|
||||
self::assertEquals(self::TEST_TIMEZONE, $dateTime->getTimezone()->getName());
|
||||
|
||||
$expected = new DateTime('now', new DateTimeZone('Atlantic/Canary'));
|
||||
$dateTime = $sut->getStartOfMonth($expected);
|
||||
self::assertEquals(0, $dateTime->format('H'));
|
||||
self::assertEquals(0, $dateTime->format('i'));
|
||||
self::assertEquals(0, $dateTime->format('s'));
|
||||
self::assertEquals(1, $dateTime->format('d'));
|
||||
self::assertEquals($expected->format('m'), $dateTime->format('m'));
|
||||
self::assertEquals($expected->format('Y'), $dateTime->format('Y'));
|
||||
self::assertEquals(self::TEST_TIMEZONE, $dateTime->getTimezone()->getName());
|
||||
}
|
||||
|
||||
public function testGetEndOfMonth(): void
|
||||
{
|
||||
$expected = new DateTime('last day of this month', new DateTimeZone(self::TEST_TIMEZONE));
|
||||
|
||||
$sut = $this->createDateTimeFactory(self::TEST_TIMEZONE);
|
||||
$dateTime = $sut->getEndOfMonth();
|
||||
self::assertEquals(23, $dateTime->format('H'));
|
||||
@@ -70,6 +87,26 @@ class DateTimeFactoryTest extends TestCase
|
||||
self::assertEquals($expected->format('m'), $dateTime->format('m'));
|
||||
self::assertEquals($expected->format('Y'), $dateTime->format('Y'));
|
||||
self::assertEquals(self::TEST_TIMEZONE, $dateTime->getTimezone()->getName());
|
||||
|
||||
$sut = $this->createDateTimeFactory(self::TEST_TIMEZONE);
|
||||
$dateTime = $sut->getEndOfMonth('last day of this month');
|
||||
self::assertEquals(23, $dateTime->format('H'));
|
||||
self::assertEquals(59, $dateTime->format('i'));
|
||||
self::assertEquals(59, $dateTime->format('s'));
|
||||
self::assertEquals($expected->format('d'), $dateTime->format('d'));
|
||||
self::assertEquals($expected->format('m'), $dateTime->format('m'));
|
||||
self::assertEquals($expected->format('Y'), $dateTime->format('Y'));
|
||||
self::assertEquals(self::TEST_TIMEZONE, $dateTime->getTimezone()->getName());
|
||||
|
||||
$expected = new DateTime('last day of this month', new DateTimeZone('Atlantic/Canary'));
|
||||
$dateTime = $sut->getEndOfMonth($expected);
|
||||
self::assertEquals(23, $dateTime->format('H'));
|
||||
self::assertEquals(59, $dateTime->format('i'));
|
||||
self::assertEquals(59, $dateTime->format('s'));
|
||||
self::assertEquals($expected->format('d'), $dateTime->format('d'));
|
||||
self::assertEquals($expected->format('m'), $dateTime->format('m'));
|
||||
self::assertEquals($expected->format('Y'), $dateTime->format('Y'));
|
||||
self::assertEquals(self::TEST_TIMEZONE, $dateTime->getTimezone()->getName());
|
||||
}
|
||||
|
||||
public static function getStartOfWeekData()
|
||||
@@ -175,6 +212,8 @@ class DateTimeFactoryTest extends TestCase
|
||||
$sut = $this->createDateTimeFactory(self::TEST_TIMEZONE);
|
||||
$dateTime = $sut->createStartOfFinancialYear();
|
||||
$expected = $sut->createDateTime('01 january this year 00:00:00');
|
||||
|
||||
self::assertEquals(self::TEST_TIMEZONE, $dateTime->getTimezone()->getName());
|
||||
self::assertInstanceOf(DateTime::class, $dateTime);
|
||||
self::assertEquals($expected, $dateTime);
|
||||
}
|
||||
@@ -224,6 +263,7 @@ class DateTimeFactoryTest extends TestCase
|
||||
|
||||
$now = $sut->createDateTime();
|
||||
$year = $sut->createStartOfYear();
|
||||
self::assertEquals(self::TEST_TIMEZONE, $year->getTimezone()->getName());
|
||||
self::assertEquals($now->format('Y'), $year->format('Y'));
|
||||
self::assertEquals('01', $year->format('m'));
|
||||
self::assertEquals('01', $year->format('d'));
|
||||
@@ -233,6 +273,15 @@ class DateTimeFactoryTest extends TestCase
|
||||
|
||||
$begin = $sut->createDateTime('2017-12-31 23:59:59');
|
||||
$year = $sut->createStartOfYear($begin);
|
||||
self::assertEquals(self::TEST_TIMEZONE, $year->getTimezone()->getName());
|
||||
self::assertEquals('2017', $year->format('Y'));
|
||||
self::assertEquals('01', $year->format('m'));
|
||||
self::assertEquals('01', $year->format('d'));
|
||||
self::assertEquals('00:00:00', $year->format('H:i:s'));
|
||||
|
||||
$begin = new \DateTime('2017-12-01 23:59:59', new DateTimeZone('Atlantic/Canary'));
|
||||
$year = $sut->createStartOfYear($begin);
|
||||
self::assertEquals(self::TEST_TIMEZONE, $year->getTimezone()->getName());
|
||||
self::assertEquals('2017', $year->format('Y'));
|
||||
self::assertEquals('01', $year->format('m'));
|
||||
self::assertEquals('01', $year->format('d'));
|
||||
@@ -245,6 +294,7 @@ class DateTimeFactoryTest extends TestCase
|
||||
|
||||
$now = $sut->createDateTime();
|
||||
$year = $sut->createEndOfYear();
|
||||
self::assertEquals(self::TEST_TIMEZONE, $year->getTimezone()->getName());
|
||||
self::assertEquals($now->format('Y'), $year->format('Y'));
|
||||
self::assertEquals('12', $year->format('m'));
|
||||
self::assertEquals('31', $year->format('d'));
|
||||
@@ -254,9 +304,45 @@ class DateTimeFactoryTest extends TestCase
|
||||
|
||||
$begin = $sut->createDateTime('2017-12-31 23:59:59');
|
||||
$year = $sut->createEndOfYear($begin);
|
||||
self::assertEquals(self::TEST_TIMEZONE, $year->getTimezone()->getName());
|
||||
self::assertEquals('2017', $year->format('Y'));
|
||||
self::assertEquals('12', $year->format('m'));
|
||||
self::assertEquals('31', $year->format('d'));
|
||||
self::assertEquals('23:59:59', $year->format('H:i:s'));
|
||||
|
||||
$begin = new \DateTime('2017-12-01 23:59:59', new DateTimeZone('Atlantic/Canary'));
|
||||
$year = $sut->createEndOfYear($begin);
|
||||
self::assertEquals(self::TEST_TIMEZONE, $year->getTimezone()->getName());
|
||||
self::assertEquals('2017', $year->format('Y'));
|
||||
self::assertEquals('12', $year->format('m'));
|
||||
self::assertEquals('31', $year->format('d'));
|
||||
self::assertEquals('23:59:59', $year->format('H:i:s'));
|
||||
}
|
||||
|
||||
public function testCreate(): void
|
||||
{
|
||||
$sut = $this->createDateTimeFactory(self::TEST_TIMEZONE);
|
||||
$dateTime = $sut->create('2025-04-22 17:29:30');
|
||||
self::assertEquals(17, $dateTime->format('H'));
|
||||
self::assertEquals(29, $dateTime->format('i'));
|
||||
self::assertEquals(30, $dateTime->format('s'));
|
||||
self::assertEquals('22', $dateTime->format('d'));
|
||||
self::assertEquals('04', $dateTime->format('m'));
|
||||
self::assertEquals('2025', $dateTime->format('Y'));
|
||||
self::assertEquals(self::TEST_TIMEZONE, $dateTime->getTimezone()->getName());
|
||||
}
|
||||
|
||||
public function testCreateFromFormat(): void
|
||||
{
|
||||
$sut = $this->createDateTimeFactory(self::TEST_TIMEZONE);
|
||||
$dateTime = $sut->createDateTimeFromFormat('H:i:s m.d-Y', '17:29:30 04.22-2025');
|
||||
self::assertInstanceOf(DateTime::class, $dateTime);
|
||||
self::assertEquals(17, $dateTime->format('H'));
|
||||
self::assertEquals(29, $dateTime->format('i'));
|
||||
self::assertEquals(30, $dateTime->format('s'));
|
||||
self::assertEquals('22', $dateTime->format('d'));
|
||||
self::assertEquals('04', $dateTime->format('m'));
|
||||
self::assertEquals('2025', $dateTime->format('Y'));
|
||||
self::assertEquals(self::TEST_TIMEZONE, $dateTime->getTimezone()->getName());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -136,15 +136,13 @@ class RateServiceTest extends TestCase
|
||||
$activity->setProject($project);
|
||||
|
||||
$timesheet = new Timesheet();
|
||||
$timesheet
|
||||
->setEnd(self::createDateTime())
|
||||
->setHourlyRate($timesheetHourly)
|
||||
->setFixedRate($timesheetFixed)
|
||||
->setActivity($activity)
|
||||
->setProject($project)
|
||||
->setDuration($duration)
|
||||
->setUser($this->getTestUser($userRate, $userInternalRate))
|
||||
;
|
||||
$timesheet->setEnd(self::createDateTime());
|
||||
$timesheet->setHourlyRate($timesheetHourly);
|
||||
$timesheet->setFixedRate($timesheetFixed);
|
||||
$timesheet->setActivity($activity);
|
||||
$timesheet->setProject($project);
|
||||
$timesheet->setDuration($duration);
|
||||
$timesheet->setUser($this->getTestUser($userRate, $userInternalRate));
|
||||
|
||||
$rates = [];
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" version="1.2">
|
||||
<file source-language="en" target-language="zh-Hans" datatype="plaintext" original="kiosk.en.xlf">
|
||||
<file source-language="en" target-language="zh-CN" datatype="plaintext" original="kiosk.en.xlf">
|
||||
<body>
|
||||
</body>
|
||||
</file>
|
||||
@@ -1938,6 +1938,22 @@
|
||||
<source>training</source>
|
||||
<target>Fortbildung</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="rD4oQRR" resname="postcode">
|
||||
<source>Postcode</source>
|
||||
<target>Postleitzahl</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="EaYsI0E" resname="city">
|
||||
<source>City</source>
|
||||
<target>Stadt</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="y1XHR1Q" resname="address_deprecated">
|
||||
<source>address_deprecated</source>
|
||||
<target>Dieses Feld wird in Kürze entfernt. Bitte übertragen Sie die Adresse, um weiterhin gültige Rechnungen zu erzeugen (z.B. für E-Rechnungen).</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="nsbR30p" resname="sending_company">
|
||||
<source>sending_company</source>
|
||||
<target>Rechnungsabsender</target>
|
||||
</trans-unit>
|
||||
</body>
|
||||
</file>
|
||||
</xliff>
|
||||
|
||||
@@ -1938,6 +1938,22 @@
|
||||
<source>training</source>
|
||||
<target>Training</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="rD4oQRR" resname="postcode">
|
||||
<source>Postcode</source>
|
||||
<target>ZIP / Postcode</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="EaYsI0E" resname="city">
|
||||
<source>City</source>
|
||||
<target>City</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="y1XHR1Q" resname="address_deprecated">
|
||||
<source>address_deprecated</source>
|
||||
<target>This field will be removed soon. Please transfer the address to continue generating valid invoices (e.g. for e-invoicing).</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="nsbR30p" resname="sending_company">
|
||||
<source>sending_company</source>
|
||||
<target>Invoice Sender</target>
|
||||
</trans-unit>
|
||||
</body>
|
||||
</file>
|
||||
</xliff>
|
||||
|
||||
Reference in New Issue
Block a user