Compare commits

...

3 Commits

12 changed files with 827 additions and 135 deletions

View File

@ -9,10 +9,16 @@
This command would send an invoice for last month created from the template
file and last month report from youtrack as an email attachment.
~./rprt.php report -r~
Asks which report to print from the list of your reports and then prints out
a table with that report.
** Install/Getting started
Get ~.phar~ file, run configuration wizzard (planned for version 1.0).
Get ~.phar~ file from r, run configuration wizzard (planned for version 1.0).
Before version 1.0 is released you have to navigate into ~/app~ directory
and call command through ~.rprt.php~ file.
@ -25,6 +31,12 @@
3. You have to allow [[https://support.google.com/accounts/answer/6010255?hl=en][less secure applications]] in your gmail if you are using
that email provider.
*** Building a phar
php box: https://github.com/box-project/box
~./box.phar compile~
** Specs
A simple Console Command that prints out monthly report from youtrack.

640
app/composer.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -2,6 +2,7 @@
use function DI\create;
use function DI\get;
use function DI\factory;
use RprtCli\Commands\InvoiceCommand;
use RprtCli\Commands\ReportCommand;
@ -18,6 +19,7 @@ use RprtCli\Utils\PdfExport\PdfExportInterface;
use RprtCli\Utils\PdfExport\PdfExportService;
use RprtCli\Utils\TimeTrackingServices\YoutrackInterface;
use RprtCli\Utils\TimeTrackingServices\YoutrackService;
use Psr\Container\ContainerInterface;
# use Symfony\Component\Translation\Translator;
#use Symfony\Component\Translation\Loader\PoFileLoader;
@ -32,7 +34,13 @@ return [
'config.path' => '~/.config/rprt-cli/',
'default_locale' => 'en',
'guzzle' => get(Client::class),
'mpdf' => get(Mpdf::class),
// 'mpdf' => get(Mpdf::class),
'mpdf' => factory(function (ContainerInterface $c) {
return new Mpdf(['tempDir' => sys_get_temp_dir()]);
}),
// 'mpdf' => function () {
// return new Mpdf(['tempDir' => sys_get_temp_dir()]);
// },
ConfigurationInterface::class => get(ConfigurationService::class),
ConfigurationService::class => create()->constructor(
get('config.path'),

View File

@ -12,7 +12,7 @@ $builder = new ContainerBuilder();
$builder->addDefinitions(__DIR__ . '/dependencies.php');
$container = $builder->build();
$application = new Application();
$application = new Application('Command Line Tool to process Youtrack Reports', '0.1.0');
$invoiceCommand = $container->get(InvoiceCommand::class);
$application->add($invoiceCommand);

View File

@ -201,7 +201,7 @@ class InvoiceCommand extends Command
}
$output_path = $this->pdfExport->fromDefaultDataToPdf($nice_data);
// Notify the user where the file was generated to.
$output->writeln("The file was generated at ${output_path}.");
$output->writeln("The file was generated at <info>${output_path}</info>.");
}
// return Command::SUCCESS;
@ -209,7 +209,7 @@ class InvoiceCommand extends Command
if ($input->getOption('send') && $output_path) {
// @TODO If no output path print an error.
// Send email to configured address.
if ($recipients = $input->getOption('send-to')) {
if ($recipients = $input->getOption('recipients')) {
$this->mailer->setRecipients(explode(',', $recipients));
}
$this->mailer->sendDefaultMail($output_path);

View File

@ -199,7 +199,7 @@ class ReportCsv implements ReportCsvInterface
$table[] = ReportCsvInterface::SEPARATOR_MEDIUM;
$table[] = [null, $project, null, $project_time / 60];
$time_sum += (float) $project_time;
$all_projects[] = $project;
// $all_projects[] = $project;
// Add a sum of time for whole day.
$table[] = ReportCsvInterface::SEPARATOR_MEDIUM;
$table[] = [null, implode(', ', $all_projects), null, $time_sum/60];

View File

@ -88,7 +88,7 @@ class PdfExportService implements PdfExportInterface {
}
$table .= implode('', $rows);
$table .= '</tbody></table>';
var_dump($table);
// var_dump($table);
return $table;
}

View File

@ -115,9 +115,14 @@ class YoutrackService implements YoutrackInterface
if ($status == 409) {
sleep(3);
// @TODO Find a way to break of of loop if necessary!
$this->downloadReport($report_id);
var_dump("409 response status during download of report {$report_id}. Sleep 3 and try again.");
return $this->downloadReport($report_id);
}
}
catch (\Throwable $t) {
$status = $t->getMessage();
var_dump($status);
}
throw new \Exception("Unable to download report {$report_id}!");
}

18
box.json 100644
View File

@ -0,0 +1,18 @@
{
"main": "rprt.php",
"base-path": "app",
"compression": "GZ",
"output": "../bin/rprt-gz.phar",
"blacklist": ["config", "resources", "tests", "translations"],
"directories": ["src", "vendor"],
"files": [
"dependencies.php"
],
"finder": [
{
"name": "*.php",
"exclude": ["Tests"],
"in": "vendor"
}
]
}

View File

@ -0,0 +1,157 @@
#!/bin/bash
# Dependencies:
# getopt
# Track drunomix and kurier dailies.
# KUR-181 (everyday 9.30)
# DEV-122 (tue-fri 10.00) - TEAM-6
# DEV-360 (tracking time) - TEAM-14
# TO DO:
# - Implement track cli (WIP)
track_help () {
echo "Tracks dailies and other weekly meetings."
echo -e "\t-d|--drunomics-daily :: [TEAM-6] Drunomics daily - Tue-Fri(10.00) - 15m."
echo -e "\t-w|--drunomics-weekly :: [TEAM-1] Drunomics weekly - Mon(11.00) - 1h."
echo -e "\t-k|--kurier-daily :: [KUR-181] Kurier daily - Mon-Fri(9.30) - 15m."
echo -e "\t-o|--devops-weekly :: [DEV-1967] DevOps weekly - Mon(14.30) - 60m."
echo -e "\t-u|--drupal-weekly :: [CTB-24] Drupal weekly - Wed(14.00) - 30m."
echo -e "\t-l|--ldp-weekly :: [LDP-683] LDP weekly - Tue(11.00) - 30m."
echo -e "\t-v|--wv-weekly :: [WV-31] WV weekly - Wed(10.30) - 30m."
echo -e "\t-e|--kurier-weekly :: [KUR-181] Kurier weekly - Wed(15.00) - 1h."
echo -e "\t-p|--lupus-d-weekly :: [CTB-55] Lupus dcpld weekly- Thu(11.00) - 30m."
echo -e "\t-t|--tracking-time :: [TEAM-14] Personal time tracking - 15m."
echo -e "\t-s|--date :: Date in timestamp-miliseconds. Defaults to [\$(date +%s)000]"
echo -e "\tmissing :: Work type id. (Not supported yet)."
}
track_help_color () {
green='\033[0;32m'
cyan='\033[0;36m'
clr='\033[0m'
DAY_OF_WEEK=$(date +%u -d "@$DATE")
COLOR_TUE_FRI=$clr
COLOR_MON=$clr
COLOR_TUE=$clr
COLOR_WED=$clr
COLOR_THU=$clr
COLOR_ALL_DAYS=$green
COLOR_PERSONAL=$clr
if [ "$DAY_OF_WEEK" == "1" ] ; then
COLOR_MON=$green
COLOR_MON_2=$cyan
elif [ "$DAY_OF_WEEK" == "2" ] ; then
COLOR_TUE=$green
COLOR_TEAM6=$green
COLOR_TUE_FRI=$green
elif [ "$DAY_OF_WEEK" == "3" ] ; then
COLOR_WED=$green
COLOR_TUE_FRI=$green
elif [ "$DAY_OF_WEEK" == "4" ] ; then
COLOR_THU=$green
COLOR_TUE_FRI=$green
elif [ "$DAY_OF_WEEK" == "5" ] ; then
COLOR_TUE_FRI=$green
else
COLOR_ALL_DAYS=$clr
fi
if [ "$DEV360" == "1" ] ; then
COLOR_PERSONAL=$green
fi
echo "Tracks dailies and other weekly meetings."
echo -e "\t-w|--drunomics-weekly :: ${COLOR_MON}[TEAM-1]${clr} Drunomics weekly - ${COLOR_MON}Mon(11.00)${clr} - ${DEV46}m."
echo -e "\t-o|--devops-weekly :: ${COLOR_MON}[DEV-1967]${clr} DevOps weekly - ${COLOR_MON}Mon(14.00)${clr} - ${DEVOPS}m."
echo -e "\t-d|--drunomics-daily :: ${COLOR_TUE_FRI}[TEAM-6]${clr} Drunomics daily - ${COLOR_TUE_FRI}Tue-Fri(10.00)${clr} - ${DEV122}m."
echo -e "\t-k|--kurier-daily :: ${COLOR_ALL_DAYS}[KUR-181]${clr} Kurier daily - ${COLOR_ALL_DAYS}Mon-Fri(9.30)${clr} - ${KUR181}m."
echo -e "\t-l|--ldp-weekly :: ${COLOR_TUE}[LDP-683]${clr} LDP weekly - ${COLOR_TUE}Tue(11.00)${clr} - ${LDP683}m."
echo -e "\t-u|--drupal-weekly :: ${COLOR_WED}[CTB-24]${clr} Drupal weekly - ${COLOR_WED}Wed(14.00)${clr} - ${CTB24}m."
echo -e "\t-v|--wv-weekly :: ${COLOR_WED}[WV-31]${clr} WV weekly - ${COLOR_WED}Wed(10.30)${clr} - ${WV31}m."
echo -e "\t-e|--kurier-weekly :: ${COLOR_WED}[KUR-182]${clr} Kurier weekly - ${COLOR_WED}Wed(15.00)${clr} - ${KUR182}."
echo -e "\t-p|--lupus-d-weekly :: ${COLOR_THU}[CTB-55]${clr} Lupus dcpld weekly- ${COLOR_WED}Thu(11.00)${clr} - ${CTB55}."
echo -e "\t-t|--tracking-time :: ${COLOR_PERSONAL}[TEAM-14]${clr} Personal time tracking - 15m."
echo -e "\t-s|--date :: Date in timestamp-miliseconds. Defaults to [\$(date +%s)000]"
echo -e "\tmissing :: Work type id. (Not supported yet)."
}
DEV122=15 # now TEAM-6
DEV46=60 # now TEAM-1
KUR181=15
KUR182=60
WV31=30
LDP683=30
DEV360=0 # now TEAM-14
DEVOPS=60
CTB24=30
CTB55=30
DATE=$(date +%s)
# options may be followed by one colon to indicate they have a required argument
if ! options=$(getopt -u -o thd:w:k:e:l:v:s:o:u:p: -l help,time-tracking,drunomics-daily:,drunomics-weekly:,kurier-daily:,kurier-weekly:,ldp-weekly:,wv-weekly:,devops-weekly,drupal-weekly,lupus-d-weekly,date -- "$@")
then
# something went wrong, getopt will put out an error message for us
exit 1
fi
set -- $options
while [ $# -gt 0 ]
do
case $1 in
-t|--tracking-time) DEV360=1 ;;
-d|--drunomics-daily) DEV122=$2 ; shift ;;
-w|--drunomics-weekly) DEV46=$2 ; shift ;;
-k|--kurier-daily) KUR181=$2 ; shift ;;
-e|--kurier-weekly) KUR182=$2 ; shift ;;
-l|--ldp-weekly) LDP683=$2 ; shift ;;
-v|--wv-weekly) WV31=$2 ; shift ;;
-o|--devops-weekly) DEVOPS=$2 ; shift ;;
-u|--drupal-weekly) CTB24=$2 ; shift ;;
-p|--lupus-d-weekly) CTB55=$2 ; shift ;;
-h|--help) TRACK_HELP=1;;
-s|--date) DATE=$2 ; shift ;;
(--) shift; break;;
(-*) echo "$0: error - unrecognized option $1" 1>&2; exit 1;;
(*) break;;
esac
shift
done
if [ "$TRACK_HELP" == "1" ] ; then
track_help_color
else
DAY_OF_WEEK=$(date +%u -d "@$DATE")
if [ "$DAY_OF_WEEK" == "1" ] ; then
echo "Monday: Kurier daily, Drunomics weekly, DevOps weekly:"
/home/lio/Projects/drunomix/ytest/scripts/ytrack.sh KUR-181 $KUR181 'daily' "$(echo $DATE)000"
/home/lio/Projects/drunomix/ytest/scripts/ytrack.sh TEAM-1 $DEV46 'weekly' "$(echo $DATE)000"
/home/lio/Projects/drunomix/ytest/scripts/ytrack.sh DEV-1967 $DEVOPS 'weekly' "$(echo $DATE)000"
elif [ "$DAY_OF_WEEK" == "2" ] ; then
echo "Tuesday: Kurier daily, Drunomics daily, LDP weekly:"
/home/lio/Projects/drunomix/ytest/scripts/ytrack.sh KUR-181 $KUR181 'daily + retro' "$(echo $DATE)000"
/home/lio/Projects/drunomix/ytest/scripts/ytrack.sh TEAM-6 $DEV122 'daily' "$(echo $DATE)000"
/home/lio/Projects/drunomix/ytest/scripts/ytrack.sh LDP-683 $LDP683 'ldp weekly' "$(echo $DATE)000"
elif [ "$DAY_OF_WEEK" == "3" ] ; then
echo "Wednesday: Kurier daily, Drunomics daily, Wirtschaftsverlag weekly, Kurier weekly:"
/home/lio/Projects/drunomix/ytest/scripts/ytrack.sh KUR-181 $KUR181 'daily' "$(echo $DATE)000"
/home/lio/Projects/drunomix/ytest/scripts/ytrack.sh TEAM-6 $DEV122 'daily' "$(echo $DATE)000"
/home/lio/Projects/drunomix/ytest/scripts/ytrack.sh CTB-24 $CTB24 'drupal weekly' "$(echo $DATE)000"
/home/lio/Projects/drunomix/ytest/scripts/ytrack.sh KUR-182 $KUR182 'Kurier weekly grooming' "$(echo $DATE)000"
/home/lio/Projects/drunomix/ytest/scripts/ytrack.sh WV-31 $WV31 'weekly' "$(echo $DATE)000"
elif [ $DAY_OF_WEEK == "4" ] ; then
echo "Thursday: Kurier, Drunomics daily, Lupus Decoupled weekly:"
/home/lio/Projects/drunomix/ytest/scripts/ytrack.sh CTB-55 $CTB55 'weekly' "$(echo $DATE)000"
elif [ $DAY_OF_WEEK -gt 5 ] ; then
echo "No dailies over the weekend."
else
echo "Youtrack drunomix & kurier dailies"
/home/lio/Projects/drunomix/ytest/scripts/ytrack.sh KUR-181 $KUR181 'daily' "$(echo $DATE)000"
/home/lio/Projects/drunomix/ytest/scripts/ytrack.sh TEAM-6 $DEV122 'daily' "$(echo $DATE)000"
fi
if [ "$DEV360" == "1" ] ; then
/home/lio/Projects/drunomix/ytest/scripts/ytrack.sh TEAM-14 15 'tracking time' "$(echo $DATE)000"
fi
fi

73
scripts/ytrack.sh 100755
View File

@ -0,0 +1,73 @@
#!/bin/bash
# Usage:
# First export your youtrack api token (you can put this in .bashrc)
#
# export YTOKEN=<your-youtrack-token-created-in-yt-hub>
#
# All parameters are optional but the sort order defines priority
#
# ytrack.sh <issue-name> <time> <description> <timestamp-miliseconds>
#
# or:
#
# ytrack.sh [DEV-122] [15] [daily] [1631567581342]
#
# @TODO:
# - Figure a nice way to set type: Development(57-0), Project management, Testing & Review(57-1)...
# - Write a proper script with parameters and everything
# Development (57-0)
# Testing, Review (57-1)
track_help () {
echo "Youtrack command line tool."
echo -e "\t\$1 :: Ticket name. Defaults to [DEV-122]."
echo -e "\t\$2 :: Number of minutes. Defaults to [15]."
echo -e "\t\$3 :: Work item description. Defaults to [daily]."
echo -e "\t\$4 :: Date in timestamp-miliseconds. Defaults to [\$(date +%s)000]"
echo -e "\t\$5 :: Work type id. (Not supported yet)."
}
# FLAGS SETUP
while getopts "h" option
do
case "${option}"
in
h) TRACK_HELP=1;;
esac
done
shift $((OPTIND -1))
if [ "$TRACK_HELP" == "1" ] ; then
track_help
else
YT_ISSUE=${1:-DEV-122}
YT_MINUTES=${2:-15}
YT_TEXT=${3:-daily}
CURRENT_DATE="$(date +%s)000"
YT_DATE=${4:-$CURRENT_DATE}
YT_WORK_TYPE=${5:-null}
YT_USER_RESP=$(curl -s 'https://drunomics.myjetbrains.com/youtrack/api/admin/users/me?fields=id,mail,fullName' -H "Authorization: Bearer $YTOKEN" -H 'Cache-Control: no-cache')
YT_USER_ID=$(echo $YT_USER_RESP | jq .id)
YT_USER_ID="${YT_USER_ID:1:-1}"
YT_USER_NAME=$(echo $YT_USER_RESP | jq .fullName)
YT_ISSUE_ID=$(curl -s "https://drunomics.myjetbrains.com/youtrack/api/issues?fields=id,idReadable&query=$YT_ISSUE" -H "Authorization: Bearer $YTOKEN" -H 'Cache-Control: no-cache' -H 'Content-Type: application/json' -H 'Accept: application/json' | jq -c ".[] | select ( .idReadable == \"$YT_ISSUE\") | .id")
YT_ISSUE_ID="${YT_ISSUE_ID:1:-1}"
echo "issue: $YT_ISSUE"
echo "issue_id: $YT_ISSUE_ID"
echo "minutes: $YT_MINUTES"
echo "text: $YT_TEXT"
echo "date: $YT_DATE"
echo "user: $YT_USER_NAME"
echo "type: $YT_WORK_TYPE"
# curl -s -X POST "https://drunomics.myjetbrains.com/youtrack/api/issues/$YT_ISSUE_ID/timeTracking/workItems?fields=id,created,type(name,id),author(name,id),duration(minutes,presentation)" -H "Authorization: Bearer $YTOKEN" -H 'Cache-Control: no-cache' -d "{\"author\": {\"id\":\"$YT_USER_ID\"},\"duration\":{\"minutes\":$YT_MINUTES},\"text\":\"$YT_TEXT\",\"date\":$YT_DATE,\"type\":{\"id\":\"$YT_WORK_TYPE\"}}" -H 'Content-Type: application/json' | jq .
curl -s -X POST "https://drunomics.myjetbrains.com/youtrack/api/issues/$YT_ISSUE_ID/timeTracking/workItems?fields=id,created,type(name,id),author(name,id),duration(minutes,presentation)" -H "Authorization: Bearer $YTOKEN" -H 'Cache-Control: no-cache' -d "{\"author\": {\"id\":\"$YT_USER_ID\"},\"duration\":{\"minutes\":$YT_MINUTES},\"text\":\"$YT_TEXT\",\"date\":$YT_DATE}" -H 'Content-Type: application/json' | jq .
fi

33
todo.txt 100644
View File

@ -0,0 +1,33 @@
TODO:
- nice report selection
- clean up the config (default reports)
- Improve readme
- abstract baseCommand with some input params
- add time tracking command
- plugin system for services:
- in dependencies.php find subdependencies.php
- Create interface for 3rd party service integration and abstract class
- Create factory to add correct service of a 3rd party service to the Command
- separator constant
------------------------
- add plugin system for time tracking service
- add tests
------------------------
- question helper: https://symfony.com/doc/current/components/console/helpers/questionhelper.html
- psr-12 code check and add phpstan https://phpstan.org/user-guide/getting-started
- phing for build automation
- add ddev for dockerization
DONE:
- expenses default value
- pretify output
- rename rprt to invoice
- select report
- build phar file
- upload a phar file on repo
- create release
- clear report cache