Giter Club home page Giter Club logo

timed-backend's People

Contributors

andreabettich avatar anehx avatar aziiee avatar c0rydoras avatar czosel avatar dependabot-preview[bot] avatar dependabot[bot] avatar derrabauke avatar fugal-dy avatar hairmare avatar johnl17 avatar karras avatar marcaurele avatar michaelimfeld avatar open-dynamix avatar paraenggu avatar pyup-bot avatar sbor23 avatar sliverc avatar strixbe avatar tk0e avatar tongpu avatar trowik avatar velrest avatar winged avatar winpat avatar yelinz avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

timed-backend's Issues

Replace uses of str.format with fstrings

Currently we still have str.format, this can be replaced with the more readable f-strings

str.format

class Attendance(models.Model):
    """Attendance model.

    An attendance is a timespan in which a user was present at work.
    Timespan should not be time zone aware hence splitting into date and
    from resp. to time fields.
    """

    date = models.DateField()
    from_time = models.TimeField()
    to_time = models.TimeField()
    user = models.ForeignKey(
        settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name="attendances"
    )

    def __str__(self) -> str:
        """Represent the model as a string."""
        return "{}: {} {} - {}".format(
            self.user,
            self.date.strftime("%Y-%m-%d"),
            self.from_time.strftime("%H:%M"),
            self.to_time.strftime("%H:%M"),
        )

f-string

class Attendance(models.Model):
    """Attendance model.

    An attendance is a timespan in which a user was present at work.
    Timespan should not be time zone aware hence splitting into date and
    from resp. to time fields.
    """

    date = models.DateField()
    from_time = models.TimeField()
    to_time = models.TimeField()
    user = models.ForeignKey(
        settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name="attendances"
    )

    def __str__(self) -> str:
        """Represent the model as a string."""
        return f"{self.user}: {self.date.strftime('%Y-%m-%d')} {self.from_time.strftime('%H:%M')} - {self.to_time.strftime('%H:%M')}"

f-string and without strftime

class Attendance(models.Model):
    """Attendance model.

    An attendance is a timespan in which a user was present at work.
    Timespan should not be time zone aware hence splitting into date and
    from resp. to time fields.
    """

    date = models.DateField()
    from_time = models.TimeField()
    to_time = models.TimeField()
    user = models.ForeignKey(
        settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name="attendances"
    )

    def __str__(self) -> str:
        """Represent the model as a string."""
        return f"{self.user}: {self.date:%Y-%m-%d} {self.from_time:%H:%M} - {self.to_time:%H:%M}"

Export Metrics

We should expose application metrics to help us pinpoint performance or other issues.

The way to go seems to be django-prometheus. The Prometheus metrics will integrate nicely with the Kube Prometheus Stack that is available for this on production.

Apart from exposing metrics in the backend we will also want to configure a PodMonitor to scrape them in the corresponding Helm chart.

  • django-prometheus
  • PodMonitor

Drop CustomerPassword

S324:

timed/subscription/admin.py:27:38: S324 Probable use of insecure hash functions in hashlib: md5 | 25 | password = self.cleaned_data.get("password") 26 | if password is not None: 27 | self.instance.password = hashlib.md5(password.encode()).hexdigest() | ^^^^^^^^^^^ S324 28 | return super().save(commit=commit) |

class CustomerPassword(models.Model):
    """Password per customer used for login into SySupport portal.

    Password are only hashed with md5. This model will be obsolete
    once customer center will go live.
    """

Can this be dropped, respectively ignored and dropped in a separate PR?
Since https://github.com/adfinis/customer-center does exist

I'm not 100% if this is still in use or not. It looks like it was part of the old SySupport portal and might have been replaced with a proper solution when the portal was migrated to being an Ember based frontend.

If this is in fact the case then we should create an issue to track the codes removal. Maybe @winged or @trowik know if it's still needed?

I'm also not 100% sure, but I'd say it's safe to remove it in another PR.

Originally posted by @trowik in #1049 (comment)

Replace raw Content-Disposition header creation with util

In Django 4.2 there is django.utils.http.content_disposition_header() which can help us ensure that the headers are RFC 6266 compliant.

Previous Code

response["Content-Disposition"] = f"attachment; filename={name}"

New Code

from django.utils.http import content_disposition_header

response["Content-Disposition"] = content_disposition_header(as_attachment=True, filename=name)

I'm not sure if this is the canonical way to call it, but it does add unicode support to the filename and hides some implementation specifics.

I'm not sure if its worth it, so feel free to close this if you don't think it is.

Originally posted by @hairmare in #1072 (comment)

Add "Auto-Submitted" mail header to mail notifications

Timed generates notification e-mails such as "Verification of reports". Those mails may lead to bounces in case one has an e-mail auto-responder active (such as out-of-office notifications), replying to a non-existing sender address (such as [email protected]).

To prevent auto responders from replying to notifications, the Auto-Submitted: mail header should be included in such e-mails.

Quoting RFC 3834:

The purpose of the Auto-Submitted header field is to indicate that the message was originated by an automatic process, or an automatic responder, rather than by a human; and to facilitate automatic filtering of messages from signal paths for which automatically generated messages and automatic responses are not desirable.
[...]
Automatic responses SHOULD NOT be issued in response to any message which contains an Auto-Submitted header field (see below), where that field has any value other than "no".

I hope that I opened this feature request issue on the correct repository, otherwise feel free to move it.

Improve configuration

I took a look at your instructions for installation, settings.py and #8
I believe this can be improved.

Further lecture: https://12factor.net/config

Environment variables

You use a single .env file.
I would define .env-files for each environment: .env.development, .env.test, .env.build etc.
Each of them contains the configuration settings for each environment.
To avoid repeating the configuration definitions, a .env.base may be defined, the more specific .env.* files then define a more specific set of settings.
I would use .env just to override the configuration settings of the other files (and for production - i.e. there should be no .env.production).
Also add a .env.template which contains the required configuration variables to deploy the application, to simplify operations' tasks (when creating the .env.production).
I would also use dotenv to load these environment variables.

Modes

It would be great if the settings for each environment were kept in classes using django classy settings.
Then you can define the settings required in production only in the production class (for instance a sentry backend).
This also allows to set defaults per environment (like the secret key, the database host, etc.) in the class - yet I do not recommend to do so and rather keep the settings in the environment specific .env-file (read further lecture).

User assignment on various objects

We should have users assigned on various objects, to allow some more elaborate permissions and planning functions.

  • Customers: Assigned users should then also be able to create / manage projects for this customer
  • Projects: Assigned users should be able to manage tasks
  • Tasks: Assigned users can be used for "light-weight" resource planning.

Ideally, I think each assignment should contain a "role" or "type" field to describe the relation (such as "manager", or "resource"). This way, one could be assigned to a project as a resource for planning purposes, or as a manager for permission purposes.

In a first step, only the assignment should be done - the permissions would probably best be done in a separate PR / feature.

bug: remaining effort on initial report creation is buggy

Scenario

Create a report and add an estimated remaining effort to it.

Expected behavior

It updates the remaining effort of the certain task in the statistics view.

Actual behavior

After submitting the report the remaining effort does not update in stats view. But after editing the rem. effort and saving the report again in the timesheet, it will update the values in the stats view.

The attributes are fine in both requests to the backend. I suspect that a the POST and PATCH requests have different handling of the remaining effort attribute. Maybe the POST does not properly trigger the update?
image

Introduce type hinting

The code should provide type hints where they make sense without overloading the code with hard to maintain typing information.

Ruff has ignore-untyped rules that we actived, in several cases satisfying the rules with some simple hints will improve the code base and further aid modern IDEs.

PEPs

Tracking of remaining effort

We propose to add the possibility to track remaining effort estimates on Timed Tasks while right next to the field where spent time is tracked (to save horizontal space, "Not billable" and "Needs review" would be replaced by icon buttons).
1-tracking

Using this information, we can add the total remaining effort to project tooltips and task tooltips.
3-task tooltip2
2-project tooltip

Provided that everyone working on a project updates the remaining effort estimates on the tasks they are working on, the project tooltip yields an always up-to-date remaining effort estimate. The "statistics" page of timed can then be extended to show the budget (red dashed line), spent time (blue bar) and remaining effort estimate (shallow red or green bar).
4-statistics

Since the remaining effort estimates are only useful for some projects (flat fee or cost ceiling, medium to large size), we'd add a setting to the "Projects" screen of timed where PMs can activate / deactivate the function on a per-project basis (default setting: deactivated). For projects without activated remaining effort tracking the extra field in the tracking screen would not be displayed.

What goals are to be achieved

  • PMs can react earlier when budget overshoot becomes apparent -> easier to take appropriate measures (e.g. talk to customer)
  • More transparency: Everyone in the company can see if specific projects are "on track" without having to talk to the PM

bug: reschedule reports leads to 500 error

Rescheduling reports from one day to another leads to a 500 error on the /api/v1/reports/40 endpoint.

Latest version (rc10)

The logs from the backend container display the following:

backend_1   | Internal Server Error: /api/v1/reports/40
backend_1   | Traceback (most recent call last):
backend_1   |   File "/usr/local/lib/python3.9/site-packages/django/core/handlers/exception.py", line 47, in inner
backend_1   |     response = get_response(request)
backend_1   |   File "/usr/local/lib/python3.9/site-packages/django/core/handlers/base.py", line 181, in _get_response
backend_1   |     response = wrapped_callback(request, *callback_args, **callback_kwargs)
backend_1   |   File "/usr/local/lib/python3.9/site-packages/django/views/decorators/csrf.py", line 54, in wrapped_view
backend_1   |     return view_func(*args, **kwargs)
backend_1   |   File "/usr/local/lib/python3.9/site-packages/rest_framework/viewsets.py", line 125, in view
backend_1   |     return self.dispatch(request, *args, **kwargs)
backend_1   |   File "/usr/local/lib/python3.9/site-packages/rest_framework/views.py", line 509, in dispatch
backend_1   |     response = self.handle_exception(exc)
backend_1   |   File "/usr/local/lib/python3.9/site-packages/rest_framework/views.py", line 469, in handle_exception
backend_1   |     self.raise_uncaught_exception(exc)
backend_1   |   File "/usr/local/lib/python3.9/site-packages/rest_framework/views.py", line 480, in raise_uncaught_exception
backend_1   |     raise exc
backend_1   |   File "/usr/local/lib/python3.9/site-packages/rest_framework/views.py", line 506, in dispatch
backend_1   |     response = handler(request, *args, **kwargs)
backend_1   |   File "/usr/local/lib/python3.9/site-packages/rest_framework/mixins.py", line 82, in partial_update
backend_1   |     return self.update(request, *args, **kwargs)
backend_1   |   File "/app/timed/tracking/views.py", line 177, in update
backend_1   |     tasks.notify_user_rejected_report(instance, request.user)
backend_1   |   File "/app/timed/tracking/tasks.py", line 96, in notify_user_rejected_report
backend_1   |     _send_notification_emails([user_changes], reviewer, True)
backend_1   |   File "/app/timed/tracking/tasks.py", line 42, in _send_notification_emails
backend_1   |     connection.send_messages(messages)
backend_1   |   File "/usr/local/lib/python3.9/site-packages/django/core/mail/backends/smtp.py", line 102, in send_messages
backend_1   |     new_conn_created = self.open()
backend_1   |   File "/usr/local/lib/python3.9/site-packages/django/core/mail/backends/smtp.py", line 67, in open
backend_1   |     self.connection.starttls(keyfile=self.ssl_keyfile, certfile=self.ssl_certfile)
backend_1   |   File "/usr/local/lib/python3.9/smtplib.py", line 771, in starttls
backend_1   |     raise SMTPNotSupportedError(
backend_1   | smtplib.SMTPNotSupportedError: STARTTLS extension not supported by server.
backend_1   | 500 PATCH /api/v1/reports/40 (172.24.0.1) 346.06ms

@trowik This seems to be connected to the rejected report feature.

editing rejected report results in weird mail

Issue

At first I had a Report actually rejected and got this mail:

Some of your reports have been rejected by a reviewer. Please get in contact
with them to clarify the reports. Most likely, you will just need to move
the reports to the correct project / task.

Reviewer: <Actualy Reviewer>


Date: mm/dd/yyyy
Duration: 7:00 (h:mm)
Task: x > y > z
Comment: <comment>
---

Then after i edited the Report i got this mail:

Some of your reports have been rejected by a reviewer. Please get in contact
with them to clarify the reports. Most likely, you will just need to move
the reports to the correct project / task.

Reviewer: <Myself>


Date: mm/dd/yyyy
Duration: 7:00 (h:mm)
Task: x > y > z
Comment: <edited comment>
---

After every edit i got another mail, where I am marked as the reviewer.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.