This commit is contained in:
Cloud User
2024-06-22 18:29:45 +02:00
31 changed files with 608 additions and 295 deletions

2
.gitignore vendored
View File

@@ -375,3 +375,5 @@ media/
/vehicles/migrations_save/ /vehicles/migrations_save/
/carnet_rouge/migrations/ /carnet_rouge/migrations/
/collabs/migrations/ /collabs/migrations/
db.sqlite3
/Reskreen/my.cnf

21
Dockerfile Normal file
View File

@@ -0,0 +1,21 @@
FROM python:alpine3.19
WORKDIR /app
COPY . .
COPY crons_jobs /etc/cron.d/django_crons_jobs
RUN chmod 0644 /etc/cron.d/django_crons_jobs && crontab /etc/cron.d/django_crons_jobs && touch /var/log/cron.log
RUN apk update && apk add --no-cache mariadb-connector-c-dev && apk add --no-cache gcc musl-dev openrc
RUN pip install --no-cache-dir -r requirements.txt
RUN python manage.py makemigrations && python manage.py migrate
EXPOSE 8080
CMD ["python", "manage.py", "runserver", "0.0.0.0:8080"]
#CMD ["./startup.sh"]

7
Reskreen/my_dev.cnf Normal file
View File

@@ -0,0 +1,7 @@
[client]
database = django_dev
user = django_usr
password = YwVHV36ovBTXWugb
default-character-set = utf8
host =33.144.144.3
port =3306

View File

@@ -0,0 +1,11 @@
from rest_framework import permissions
class CustomPermission_DjangoModel_based(permissions.DjangoModelPermissions):
perms_map = {
'GET': ['%(app_label)s.view_%(model_name)s'],
'OPTIONS': ['%(app_label)s.view_%(model_name)s'],
'HEAD': ['%(app_label)s.view_%(model_name)s'],
'POST': ['%(app_label)s.add_%(model_name)s'],
'PUT': ['%(app_label)s.change_%(model_name)s'],
'PATCH': ['%(app_label)s.change_%(model_name)s'],
'DELETE': ['%(app_label)s.delete_%(model_name)s'],
}

View File

@@ -12,7 +12,7 @@ https://docs.djangoproject.com/en/4.0/ref/settings/
from pathlib import Path from pathlib import Path
import os import os
from .server_config import * from Reskreen.server_config import *
# Build paths inside the project like this: BASE_DIR / 'subdir'. # Build paths inside the project like this: BASE_DIR / 'subdir'.
BASE_DIR = Path(__file__).resolve().parent.parent BASE_DIR = Path(__file__).resolve().parent.parent
@@ -30,6 +30,8 @@ DEBUG = cfg_dev_mode
ALLOWED_HOSTS = ["rh.ambulance-clerc.ch"] ALLOWED_HOSTS = ["rh.ambulance-clerc.ch"]
if cfg_dev_mode: if cfg_dev_mode:
ALLOWED_HOSTS.append("127.0.0.1") ALLOWED_HOSTS.append("127.0.0.1")
ALLOWED_HOSTS.append("33.144.144.6")
ALLOWED_HOSTS.append("33.144.144.13")
CSRF_TRUSTED_ORIGINS = ['https://rh.ambulance-clerc.ch'] CSRF_TRUSTED_ORIGINS = ['https://rh.ambulance-clerc.ch']
@@ -37,6 +39,7 @@ CSRF_TRUSTED_ORIGINS = ['https://rh.ambulance-clerc.ch']
LOGIN_REDIRECT_URL = '/admin' LOGIN_REDIRECT_URL = '/admin'
INSTALLED_APPS = [ INSTALLED_APPS = [
'jazzmin', 'jazzmin',
'django_cron',
'django.contrib.auth', 'django.contrib.auth',
'django.contrib.contenttypes', 'django.contrib.contenttypes',
'django.contrib.sessions', 'django.contrib.sessions',
@@ -55,6 +58,20 @@ INSTALLED_APPS = [
'django_summernote', 'django_summernote',
] ]
INSTALLED_APPS += ( 'apilog.apps.ApilogConfig',)
INSTALLED_APPS += ( 'corsheaders',)
'',
#Ajout de rest_framework
INSTALLED_APPS += ('rest_framework', 'rest_framework.authtoken',)
'''REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework.authentication.TokenAuthentication', #Todo prod: replace by TokenAuthentication
),
# Autres paramètres de configuration...
}'''
LANGUAGE_CODE = 'fr-CH' LANGUAGE_CODE = 'fr-CH'
if not cfg_dev_mode: if not cfg_dev_mode:
@@ -104,6 +121,7 @@ DATA_UPLOAD_MAX_NUMBER_FIELDS = 2500
MIDDLEWARE = [ MIDDLEWARE = [
'corsheaders.middleware.CorsMiddleware',
'django.middleware.security.SecurityMiddleware', 'django.middleware.security.SecurityMiddleware',
'whitenoise.middleware.WhiteNoiseMiddleware', 'whitenoise.middleware.WhiteNoiseMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware',
@@ -117,6 +135,22 @@ MIDDLEWARE = [
'django.middleware.locale.LocaleMiddleware', 'django.middleware.locale.LocaleMiddleware',
] ]
CRON_CLASSES = [
"mycaldav.cron.InitTaskSync",
]
CORS_ALLOWED_ORIGINS = [
"http://33.144.144.13:4173",
"http://33.144.144.13:5173",
"http://33.144.144.13:3000",
]
MIDDLEWARE += ('apilog.middleware.APILogMiddleware',)
ROOT_URLCONF = 'Reskreen.urls' ROOT_URLCONF = 'Reskreen.urls'
TEMPLATES = [ TEMPLATES = [
@@ -149,7 +183,7 @@ if cfg_dev_mode:
'NAME': BASE_DIR / 'db.sqlite3', 'NAME': BASE_DIR / 'db.sqlite3',
} }
} }
''' '''
DATABASES = { DATABASES = {
'default': { 'default': {
'ENGINE': 'django.db.backends.mysql', 'ENGINE': 'django.db.backends.mysql',
@@ -163,7 +197,7 @@ else:
'default': { 'default': {
'ENGINE': 'django.db.backends.mysql', 'ENGINE': 'django.db.backends.mysql',
'OPTIONS': { 'OPTIONS': {
'read_default_file': 'my.cnf', 'read_default_file': os.path.join(BASE_DIR, 'Reskreen/my.cnf'),
}, },
} }
} }

View File

@@ -26,12 +26,15 @@ urlpatterns = [
path('accounts/', admin.site.urls), path('accounts/', admin.site.urls),
path('collabs/', include('collabs.urls')), path('collabs/', include('collabs.urls')),
path('vehicules/', include('vehicles.urls')), path('vehicules/', include('vehicles.urls')),
path('comm-opmessage/', include('comm_op.urls')),
path('caldav/', include('mycaldav.urls')), path('caldav/', include('mycaldav.urls')),
#path('collabs_hour/', include('collabs.urls')), #path('collabs_hour/', include('collabs.urls')),
path('carnet_rouge/', include('carnet_rouge.urls')), path('carnet_rouge/', include('carnet_rouge.urls')),
path('student_eval/', include('studenteval.urls')), path('student_eval/', include('studenteval.urls')),
path('summernote/', include('django_summernote.urls')), path('summernote/', include('django_summernote.urls')),
path('editor/', include('django_summernote.urls')), path('editor/', include('django_summernote.urls')),
path('api-auth/', include('rest_framework.urls', namespace='rest_framework')),
] ]
if settings.DEBUG: if settings.DEBUG:

0
apilog/__init__.py Normal file
View File

15
apilog/admin.py Normal file
View File

@@ -0,0 +1,15 @@
from django.contrib import admin
from .models import APILog
@admin.register(APILog)
class APILogAdmin(admin.ModelAdmin):
list_display = ('user', 'request_url', 'request_params', 'request_method', 'request_body', 'request_timestamp')
list_filter = ('user', 'request_method')
search_fields = ('request_url',)
ordering = ('-request_timestamp',)
actions = None
def has_delete_permission(self, request, obj=None):
return False

6
apilog/apps.py Normal file
View File

@@ -0,0 +1,6 @@
from django.apps import AppConfig
class ApilogConfig(AppConfig):
default_auto_field = 'django.db.models.BigAutoField'
name = 'apilog'

27
apilog/middleware.py Normal file
View File

@@ -0,0 +1,27 @@
from .models import APILog
class APILogMiddleware:
def __init__(self, get_response):
self.get_response = get_response
def __call__(self, request):
if not request.path.startswith('/admin'):
user = request.user if request.user.is_authenticated else None
request_url = request.path
request_params = request.GET if request.GET else None
request_method = request.method
request_body = request.body.decode('utf-8')
APILog.objects.create(user=user, request_url=request_url, request_params=request_params, request_method=request_method, request_body=request_body)
response = self.get_response(request)
return response

22
apilog/models.py Normal file
View File

@@ -0,0 +1,22 @@
from django.db import models
from django.conf import settings
from django.db.models.signals import pre_delete
from django.dispatch import receiver
class APILog(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.SET_NULL, null=True)
request_url = models.URLField()
request_params = models.CharField(max_length=255, null=True, blank=True)
request_method = models.CharField(max_length=10)
request_body = models.TextField()
request_timestamp = models.DateTimeField(auto_now_add=True)
def __str__(self):
return f"{self.user} - {self.request_url}"
@receiver(pre_delete, sender=APILog)
def prevent_delete(sender, instance, **kwargs):
# Empêchez la suppression en levant une exception, par exemple ValueError
raise ValueError("Vous n'êtes pas autorisé à supprimer cet enregistrement.")

3
apilog/tests.py Normal file
View File

@@ -0,0 +1,3 @@
from django.test import TestCase
# Create your tests here.

3
apilog/views.py Normal file
View File

@@ -0,0 +1,3 @@
from django.shortcuts import render
# Create your views here.

8
comm_op/serializers.py Normal file
View File

@@ -0,0 +1,8 @@
from rest_framework import serializers
from.models import comm_opMessage
class cl_comm_opMessage_Serializer(serializers.ModelSerializer):
class Meta:
model = comm_opMessage
fields = '__all__'

15
comm_op/urls.py Normal file
View File

@@ -0,0 +1,15 @@
from django.urls import path, include
from rest_framework import routers
from . import views
router = routers.DefaultRouter()
router.register(r'api-comm-opmessage', views.comm_opMessageViewset, basename='comm-opmessage')
app_name = "comm_opMessage"
urlpatterns = [
path('', include(router.urls)),
]

View File

@@ -1,3 +1,12 @@
from django.shortcuts import render from django.shortcuts import render
# Create your views here. from comm_op.models import *
from rest_framework import viewsets
from Reskreen.rest_permission import CustomPermission_DjangoModel_based
from .serializers import cl_comm_opMessage_Serializer
class comm_opMessageViewset(viewsets.ModelViewSet):
queryset = comm_opMessage.objects.all()
serializer_class = cl_comm_opMessage_Serializer
permission_classes = [CustomPermission_DjangoModel_based]

5
compile_and_start_cont.sh Executable file
View File

@@ -0,0 +1,5 @@
docker build -t reskreen:dev .
docker stop reskreen-validation && docker rm reskreen-validation
docker stop reskreen-validation-cron && docker rm reskreen-validation-cron
docker run -p 8080:8080 -d --name reskreen-validation -v /home/reskreen:/app/Reskreen reskreen:dev
docker run -d --name reskreen-validation-cron -v /home/reskreen:/app/Reskreen reskreen:dev crond -f

2
crons_jobs Normal file
View File

@@ -0,0 +1,2 @@
# Exécute la tâche cron toutes les heures
* * * * * cd /app && python /app/manage.py runcrons > /var/log/runcrons.log

View File

@@ -1,3 +1,8 @@
from django.contrib import admin from django.contrib import admin
from mycaldav.models import caldav_sync_manager
# Register your models here.
@admin.register(caldav_sync_manager)
class caldav_sync_managerAdmin(admin.ModelAdmin):
list_display = ('dtDate',)

View File

@@ -4,3 +4,4 @@ from django.apps import AppConfig
class CaldavConfig(AppConfig): class CaldavConfig(AppConfig):
default_auto_field = 'django.db.models.BigAutoField' default_auto_field = 'django.db.models.BigAutoField'
name = 'mycaldav' name = 'mycaldav'

22
mycaldav/cron.py Normal file
View File

@@ -0,0 +1,22 @@
from django_cron import CronJobBase, Schedule
import django
class InitTaskSync(CronJobBase):
RUN_AT_TIMES = ['07:00', '19:00']
RUN_EVERY_MIN = 1
schedule = Schedule(run_at_times=RUN_AT_TIMES,)
code = 'reskreen.init_sync_task' # Un code unique pour votre tâche cron
def do(self):
django.setup()
from mycaldav.models import caldav_sync_manager
from mycaldav.settings import CALDAV_URL,CALDAV_USER,CALDAV_PASSWORD
o_caldav_sync_management = caldav_sync_manager()
o_caldav_sync_management.init_caldav(caldav_url=CALDAV_URL, caldav_user=CALDAV_USER, caldav_password=CALDAV_PASSWORD)
o_caldav_sync_management.init_task_management()
print('Ma tâche cron s\'exécute !')

View File

@@ -1,3 +1,4 @@
from django.db import models
from datetime import datetime, timedelta, time from datetime import datetime, timedelta, time
from django.contrib.auth.models import User from django.contrib.auth.models import User
import datetime as Datetime import datetime as Datetime
@@ -17,9 +18,82 @@ import recurring_ical_events
import caldav import caldav
from mycaldav.settings import * from mycaldav.settings import *
import pytz
from dateutil.parser import parse
Key_separator = "--" Key_separator = "--"
class caldav_sync_manager(models.Model):
dtDate = models.DateField('Date_synchronized', auto_now_add=True, unique=True)
bDone = models.BooleanField("Effectuée", default=False)
dtUpdated = models.DateTimeField('date updated', auto_now=True)
dtCreated = models.DateTimeField('date published', auto_now_add=True)
def __str__(self):
return f"{self.dtDate}"
def init_caldav(self, caldav_url, caldav_user, caldav_password):
client = caldav.DAVClient(url=caldav_url, username=caldav_user, password=caldav_password)
data = client.principal()
self.a_task = data.calendar(cal_id=caldav_id["task"])
def set_today_as_synced(self):
o_new_manager = caldav_sync_manager()
o_new_manager.save()
def init_task_management(self):
today = datetime.now()
o_caldav_sync_management = caldav_sync_manager.objects.filter(dtDate=today.date())
if not o_caldav_sync_management.exists():
self.copy_caldav_data()
print(f"synced events")
else:
print("pas de copy, sync déjà fait")
def copy_caldav_data(self,):
ctx = ssl.create_default_context()
ctx.check_hostname = False
ctx.verify_mode = ssl.CERT_NONE
today = datetime.now()
seeked_date = today + relativedelta(months=1)
sync_date = today + relativedelta(months=1, days=1)
modified_url = caldav_cfg["task_config"] + f"&start={int(today.timestamp())}&end={int(sync_date.timestamp())}&expand=1"
with urllib.request.urlopen(modified_url, context=ctx) as o_url:
sabre_data = o_url.read()
events = recurring_ical_events.of(Calendar.from_ical(sabre_data)).at((seeked_date.year,seeked_date.month,seeked_date.day))
#print(f"events:{events}")
for event in events:
print(f"copy de l'événement: {event['SUMMARY']}")
_title = event["SUMMARY"] if ("SUMMARY" in event) else "Sans Titre"
_desc = event["DESCRIPTION"] if ("DESCRIPTION" in event) else ""
my_event = self.a_task.save_event(
dtstart=event["DTSTART"].dt,
dtend=event["DTEND"].dt,
summary= _title,
description= _desc,
)
self.set_today_as_synced()
# Create your models here. # Create your models here.
class cls_caldav(): class cls_caldav():
url = "" url = ""
@@ -46,21 +120,28 @@ class cls_caldav():
self.day.sort(key=lambda x: x.key, reverse=reverse) self.day.sort(key=lambda x: x.key, reverse=reverse)
self.night.sort(key=lambda x: x.key, reverse=reverse) self.night.sort(key=lambda x: x.key, reverse=reverse)
def caldav_open_url(self, days_delta, date):
def get_caldav_data(self,periode=1,calendar=None, date=None):
ctx = ssl.create_default_context() ctx = ssl.create_default_context()
ctx.check_hostname = False ctx.check_hostname = False
ctx.verify_mode = ssl.CERT_NONE ctx.verify_mode = ssl.CERT_NONE
self.clear_data() self.clear_data()
o_url = urllib.request.urlopen(self.url, context=ctx)
self.data = o_url.read() modified_url = self.url + f"&start={int((date-timedelta(days=days_delta)).timestamp())}&end={int((date +timedelta(days=days_delta)).timestamp())}&expand=1"
o_url.close() print(f"ICS CALL URL = {modified_url}")
with urllib.request.urlopen(modified_url, context=ctx) as o_url:
self.data = o_url.read()
return self.data
def get_caldav_data(self,periode=1,calendar=None, date=None):
if date is None: if date is None:
date = datetime.now() date = datetime.now()
self.caldav_open_url(days_delta=periode,date=date)
today = (date.year,date.month,date.day) today = (date.year,date.month,date.day)
@@ -81,11 +162,29 @@ class cls_caldav():
events = recurring_ical_events.of(Calendar.from_ical(self.data)).between(today,endweek) events = recurring_ical_events.of(Calendar.from_ical(self.data)).between(today,endweek)
self.parse_data(events) self.parse_data(events)
def convert_to_gmt1(self, dt):
gmt1_tz = pytz.timezone('Europe/Paris')
try:
if hasattr(dt,"tzinfo") and dt.tzinfo is not None:
# Convertir l'objet datetime en GMT+1
# Utilisez le nom de votre fuseau horaire GMT+1
dt_gmt1 = dt.astimezone(gmt1_tz)
else:
# L'objet datetime est naïf, ajouter l'information de fuseau horaire GMT+1
utc_tz = pytz.utc
dt_utc = utc_tz.localize(dt)
dt_gmt1 = dt_utc.astimezone(gmt1_tz)
return dt_gmt1
except:
return dt
def parse_data(self, events): def parse_data(self, events):
desired_timezone = pytz.timezone('Europe/Paris')
for event in events: for event in events:
item = _caldav_item() item = _caldav_item()
item.name = event["SUMMARY"] item.name = event["SUMMARY"]
item.uiid = event["UID"] item.uuid = f"{event['UID']}"
if Key_separator in item.name: if Key_separator in item.name:
arr = item.name.split(Key_separator) arr = item.name.split(Key_separator)
item.key = arr[0] item.key = arr[0]
@@ -107,12 +206,14 @@ class cls_caldav():
item.team_2_chef = True item.team_2_chef = True
item.team_2 = item.team_2.replace("#", "") item.team_2 = item.team_2.replace("#", "")
if "DESCRIPTION" in event.keys(): if "DESCRIPTION" in event.keys():
item.desc = event["DESCRIPTION"] item.desc = f"{event['DESCRIPTION']}"
if "#" in item.desc:
if "#Fait" in item.desc:
item.done = True item.done = True
if "#Fait" in item.desc: item.desc = item.desc.replace("#Fait", "")
item.desc = item.desc.replace("#Fait", "")
if '{href=' in item.desc: if '{href=' in item.desc:
temp_str = item.desc.split('{href=')[1] temp_str = item.desc.split('{href=')[1]
@@ -120,10 +221,18 @@ class cls_caldav():
item.href = temp_str item.href = temp_str
item.desc = item.desc.replace("{href=" + item.href + "}","") item.desc = item.desc.replace("{href=" + item.href + "}","")
item.dtstart = event["DTSTART"].dt.strftime("%d.%m.%Y %H:%M")
item.dtstamp = int(event["DTSTART"].dt.strftime("%Y%m%d%H%M")) desired_timezone = pytz.timezone('Europe/Paris')
datetime_obj = parse(event["DTSTART"].dt.strftime("%d.%m.%Y %H:%M"))
gmt1_datetime = datetime_obj.astimezone(desired_timezone)
print(f"gmt= {self.convert_to_gmt1( event['DTSTART'].dt)}")
item.dtstart = self.convert_to_gmt1( event['DTSTART'].dt).strftime("%d.%m.%Y %H:%M")
item.dtstamp = int(self.convert_to_gmt1( event['DTSTART'].dt).strftime("%Y%m%d%H%M"))
#print(item.dtstamp) #print(item.dtstamp)
item.dtend = event["DTEND"].dt.strftime("%d.%m.%Y %H:%M") item.dtend = self.convert_to_gmt1( event['DTEND'].dt).strftime("%d.%m.%Y %H:%M")
item.format_str_date() item.format_str_date()
@@ -155,14 +264,18 @@ class cls_caldav_client():
caldav_password = "Agendamc144" caldav_password = "Agendamc144"
caldav_agenda_config_url = caldav_cfg["task_config"] caldav_agenda_config_url = caldav_cfg["task_config"]
events = None events = None
def __init__(self):
self.client = caldav.DAVClient(url=self.caldav_url, username=self.caldav_user, password=self.caldav_password)
self.data = self.client.principal()
def init_caldav(self, caldav_url, caldav_user, caldav_password):
client = caldav.DAVClient(url=caldav_url, username=caldav_user, password=caldav_password)
self.data = client.principal()
for cal in self.data.calendars(): for cal in self.data.calendars():
print(f"name: {cal.name}({cal.url})") print(f"name: {cal.name}({cal.url})")
@@ -176,7 +289,6 @@ class cls_caldav_client():
self.a_rh = self.data.calendar(cal_id=caldav_id["rh"]) self.a_rh = self.data.calendar(cal_id=caldav_id["rh"])
self.a_manif = self.data.calendar(cal_id=caldav_id["manif"]) self.a_manif = self.data.calendar(cal_id=caldav_id["manif"])
#self.get_events_by_date(self.a_team)
def get_event_by_uuid(self,calandar,uuid): def get_event_by_uuid(self,calandar,uuid):
event = calandar.object_by_uid(uid=uuid) event = calandar.object_by_uid(uid=uuid)
return event return event
@@ -199,36 +311,9 @@ class cls_caldav_client():
summary=event.vobject_instance.vevent.summary.value, summary=event.vobject_instance.vevent.summary.value,
description=_desc, description=_desc,
) )
event.delete() event.delete()
def init_task_management(self):
print("pass copy task process")
try:
with open(os.path.join("mycaldav", "last_sync_config.bin"), "rb") as file:
array = pickle.load(file)
except:
array = {"year": 0, "month": 0}
print("Erreur lecture fichier config")
if array["month"] == datetime.now().month:
if array["year"] == datetime.now().year:
print("pas de copy, sync déjà fait")
else:
self.copy_caldav_data(self.a_task)
else:
self.copy_caldav_data(self.a_task)
self.clear_all_events_by_Date(self.a_task)
def add_event_in_calandar(self, calandar):
my_event = calandar.save_event(
dtstart=datetime(2022, 6, 30, 12),
dtend=datetime(2022, 6, 30, 13),
summary="Do the needful",
)
def get_events_by_date(self,calandar,date=None ): def get_events_by_date(self,calandar,date=None ):
if date is None: if date is None:
date = datetime.now() date = datetime.now()
@@ -297,126 +382,33 @@ class cls_caldav_client():
def copy_caldav_data(self, calandar=None):
ctx = ssl.create_default_context()
ctx.check_hostname = False
ctx.verify_mode = ssl.CERT_NONE
o_url = urllib.request.urlopen(self.caldav_agenda_config_url, context=ctx)
data = o_url.read()
o_url.close()
now = f"01.{datetime.now().month}.{datetime.now().year}"
next_month = datetime.strptime(f"1.{datetime.today().month}.{datetime.today().year}","%d.%m.%Y") + relativedelta(months=1)
next_month = (next_month.year, next_month.month, next_month.day)
today = (datetime.now().year, datetime.now().month, 1)
print(f"today:{today}")
print(f"next:{next_month}")
events = None
events = recurring_ical_events.of(Calendar.from_ical(data)).between(today, next_month)
cur_events = calandar.date_search(start=datetime(today[0],today[1],today[2]), end=datetime(next_month[0],next_month[1],next_month[2]), expand=True)
for event in events:
print(f"copy de l'événement: {event['SUMMARY']}")
_title = event["SUMMARY"] if ("SUMMARY" in event) else "Sans Titre"
_desc = event["DESCRIPTION"] if ("DESCRIPTION" in event) else ""
my_event = calandar.save_event(
dtstart=event["DTSTART"].dt,
dtend=event["DTEND"].dt,
summary= _title,
description= _desc,
)
with open(os.path.join("mycaldav", "last_sync_config.bin"), "wb") as file:
array = {"year":datetime.now().year, "month":datetime.now().month}
pickle.dump(array, file)
def clear_all_events_by_Date(self, calandar):
events = calandar.date_search(start=datetime(2000, 1, 1), end=datetime.now() - relativedelta(years=1), expand=True)
for e in events:
e.delete()
#print(events)
def reformat_all_events(self,calandar):
events = calandar.date_search(start=datetime(2023, 1, 1), end=datetime.now() + relativedelta(years=1),
expand=True)
for event in events:
summary = event.vobject_instance.vevent.summary.value
print(f"test summary {summary}")
if "----" in summary:
summary = summary.replace("----", Key_separator)
print(f"reformat: [{summary}]")
event.vobject_instance.vevent.summary.value = summary
event.save()
elif "--" in summary:
pass
elif "-" in summary:
summary = summary.replace("-",Key_separator)
print(f"reformat: [{summary}]")
event.vobject_instance.vevent.summary.value = summary
event.save()
def change_utc_to_zurich_all_events(self,calandar):
events = calandar.date_search(start=datetime(2023, 4, 1), end=datetime.now() + relativedelta(years=1),
expand=True)
for event in events:
start = event.vobject_instance.vevent.dtstart.value
end = start + relativedelta(day=1)
if start.hour < 12:
new_start = datetime(start.year, start.month, start.day,7,0,0, tzinfo = pytz.timezone("Europe/Zurich"))
new_end = datetime(start.year, start.month, start.day, 19, 0, 0, tzinfo=pytz.timezone("Europe/Zurich"))
elif start.hour > 12:
new_start = datetime(start.year, start.month, start.day,19,0,0, tzinfo = pytz.timezone("Europe/Zurich"))
new_end = datetime(start.year, start.month,start.day, 23, 59, 0, tzinfo=pytz.timezone("Europe/Zurich"))
event.vobject_instance.vevent.dtstart.value = new_start
event.vobject_instance.vevent.dtend.value = new_end
if new_end<new_start :
print(f"{new_start}>{new_end}")
print("ERROR")
event.vobject_instance.vevent.dtend.value = new_start
event.save()
class _caldav_item(): class _caldav_item():
key = "" def __init__(self, key="", name="", desc="", dtstart=None, str_start_date="",
name = "" str_start_time="", dtend=None, str_end_date="", str_end_time="",
desc = "" dtstamp=None, done=False, href="", uuid="", team_1="",
dtstart = None team_2="", team_1_chef=False, team_2_chef=False,
str_start_date = "" team_transfert=False, team_manif=False):
str_start_time = "" self.key = key
dtend = None self.name = name
str_end_date = "" self.desc = desc
str_end_time = "" self.dtstart = dtstart
dtstamp = None self.str_start_date = str_start_date
done = False self.str_start_time = str_start_time
href = "" self.dtend = dtend
uiid = "" self.str_end_date = str_end_date
team_1 = "" self.str_end_time = str_end_time
team_2 = "" self.dtstamp = dtstamp
team_1_chef = False self.done = done
team_2_chef = False self.href = href
team_transfert = False self.uuid = uuid
team_manif = False self.team_1 = team_1
self.team_2 = team_2
self.team_1_chef = team_1_chef
self.team_2_chef = team_2_chef
self.team_transfert = team_transfert
self.team_manif = team_manif
def format_str_date(self): def format_str_date(self):
self.str_start_date = datetime.strptime(self.dtstart,"%d.%m.%Y %H:%M").strftime("%d.%m") self.str_start_date = datetime.strptime(self.dtstart,"%d.%m.%Y %H:%M").strftime("%d.%m")
@@ -427,3 +419,24 @@ class _caldav_item():
from rest_framework import serializers
class CalDavItemSerializer(serializers.Serializer):
key = serializers.CharField()
name = serializers.CharField()
desc = serializers.CharField(allow_blank=True)
dtstart = serializers.CharField()
str_start_date = serializers.CharField()
str_start_time = serializers.CharField()
dtend = serializers.CharField()
str_end_date = serializers.CharField()
str_end_time = serializers.CharField()
done = serializers.BooleanField()
href = serializers.CharField(allow_blank=True)
uuid = serializers.CharField()
team_1 = serializers.CharField(allow_blank=True)
team_2 = serializers.CharField(allow_blank=True)
team_1_chef = serializers.BooleanField()
team_2_chef = serializers.BooleanField()
team_transfert = serializers.BooleanField()
team_manif = serializers.BooleanField()

View File

@@ -13,3 +13,8 @@ for key,value in caldav_id.items():
caldav_cfg[key] = f"https://sync.infomaniak.com/calendars/AA01593/{value}?export" caldav_cfg[key] = f"https://sync.infomaniak.com/calendars/AA01593/{value}?export"
CALDAV_URL = "https://sync.infomaniak.com"
CALDAV_USER = 'AA01593' #agenda@ambulance-clerc.ch
CALDAV_PASSWORD = "Agendamc144"

View File

@@ -7,13 +7,13 @@ from . import views
app_name = "mycaldav" app_name = "mycaldav"
urlpatterns = [ urlpatterns = [
path('task', views.view_task_caldav, name='view_task_caldav'), path('task', views.view_task_caldav, name='view_task_caldav'),
path('task/edit/<str:uuid>', views.view_task_edit_caldav, name='view_task_edit_caldav'), path('task/edit', views.view_task_edit_caldav, name='view_task_edit_caldav'),
path('vhc', views.view_vhc_caldav, name='view_vhc_caldav'), path('vhc', views.view_vhc_caldav, name='view_vhc_caldav'),
path('vhc/edit/<str:uuid>', views.view_vhc_edit_caldav, name='view_vhc_edit_caldav'), path('vhc/edit', views.view_vhc_edit_caldav, name='view_vhc_edit_caldav'),
path('rh', views.view_rh_caldav, name='view_rh_caldav'), path('rh', views.view_rh_caldav, name='view_rh_caldav'),
path('road', views.view_road_caldav, name='view_road_caldav'), path('road', views.view_road_caldav, name='view_road_caldav'),
path('op', views.view_op_caldav, name='view_op_caldav'), path('op', views.view_op_caldav, name='view_op_caldav'),
path('op/edit/<str:uuid>', views.view_op_edit_caldav, name='view_op_edit_caldav'), path('op/edit', views.view_op_edit_caldav, name='view_op_edit_caldav'),
path('team', views.view_team_caldav, name='view_team_caldav'), path('team', views.view_team_caldav, name='view_team_caldav'),
path('manif', views.view_manif_caldav, name='view_manif_caldav'), path('manif', views.view_manif_caldav, name='view_manif_caldav'),
path('team_pdf', views.view_team_pdf_caldav, name='view_team_pdf_caldav'), path('team_pdf', views.view_team_pdf_caldav, name='view_team_pdf_caldav'),

View File

@@ -1,4 +1,6 @@
from django.http import HttpResponse import json
from django.http import HttpResponse, JsonResponse
from django.http import FileResponse from django.http import FileResponse
from django.shortcuts import render from django.shortcuts import render
from django.views import generic from django.views import generic
@@ -19,130 +21,203 @@ from mycaldav.settings import *
from mycaldav.export_team_pdf import * from mycaldav.export_team_pdf import *
from comm_op.models import comm_opMessage from comm_op.models import comm_opMessage
class caldav_item:
def __init__(self): from rest_framework.response import Response
self.uuid = "" from rest_framework import status
self.name = "" from rest_framework.decorators import api_view
self.desc = ""
self.key = "" from mycaldav.models import CalDavItemSerializer, _caldav_item
self.done = False from mycaldav.settings import CALDAV_URL,CALDAV_USER,CALDAV_PASSWORD
self.href = "#"
self.str_start_date = "" import logging
self.str_end_date = ""
logger = logging.getLogger(__name__)
def formatResponseArray(o_caldav, inverted=False):
try:
if inverted:
o_caldav.items.reverse()
o_caldav.day.reverse()
o_caldav.night.reverse()
# Serialize data
serializer_items = CalDavItemSerializer(data=[item.__dict__ for item in o_caldav.items], many=True)
serializer_day = CalDavItemSerializer(data=[item.__dict__ for item in o_caldav.day], many=True)
serializer_night = CalDavItemSerializer(data=[item.__dict__ for item in o_caldav.night], many=True)
@xframe_options_exempt # Check validation and print errors
validate_and_log(serializer_items, "items")
validate_and_log(serializer_day, "day")
validate_and_log(serializer_night, "night")
response_data = {
"items": serializer_items.data,
"day": serializer_day.data,
"night": serializer_night.data,
}
response_status = status.HTTP_200_OK
except Exception as e:
logger.error(f"An error occurred: {e}")
response_data = {"error": "An error occurred while processing the request."}
response_status = status.HTTP_500_INTERNAL_SERVER_ERROR
return {"data":response_data, "status": response_status}
def validate_and_log(serializer, label):
if not serializer.is_valid():
print(f"Validation Error {label}: {serializer.errors}")
@api_view(['GET'])
def view_task_caldav(request): def view_task_caldav(request):
o_caldav = cls_caldav(url=caldav_cfg["task"]) o_caldav = cls_caldav(url=caldav_cfg["task"])
o_caldav.get_caldav_data() o_caldav.get_caldav_data()
template = loader.get_template("task/task.html") '''
context = {'latest_task_list':o_caldav.day, 'night_task_list': o_caldav.night} o_caldav_sync_management = caldav_sync_manager()
'''DEPRECATED o_caldav_sync_management.init_caldav(caldav_url=CALDAV_URL, caldav_user=CALDAV_USER, caldav_password=CALDAV_PASSWORD)
if (datetime.today().day == 1) and 2==1: o_caldav_sync_management.init_task_management()
myClient = cls_caldav_client() '''
myClient.init_task_management()'''
return HttpResponse(template.render(context,request))
@xframe_options_exempt response = formatResponseArray(o_caldav)
def view_task_edit_caldav(request, uuid): return Response(response["data"], status=response["status"])
print(uuid)
@api_view(['POST'])
def view_task_edit_caldav(request):
data = json.loads(request.body.decode('utf-8'))
uuid = data.get('uuid', None)
if uuid is None:
# Gérer le cas où l'UUID n'est pas fourni dans les données JSON
return JsonResponse({'error': 'UUID non fourni dans les données JSON'}, status=400)
myClient = cls_caldav_client() myClient = cls_caldav_client()
myClient.mark_as_done_task(calandar=myClient.a_task,uuid=uuid) myClient.init_caldav(caldav_url=CALDAV_URL, caldav_user=CALDAV_USER, caldav_password=CALDAV_PASSWORD)
return view_task_caldav(request) myClient.mark_as_done_task(calandar=myClient.a_task,uuid=uuid)
return JsonResponse({'sucsess': 'UUID marqué à done'}, status=200)
def view_op_edit_caldav(request, uuid): @api_view(['POST'])
print(uuid) def view_op_edit_caldav(request):
data = json.loads(request.body.decode('utf-8'))
uuid = data.get('uuid', None)
if uuid is None:
# Gérer le cas où l'UUID n'est pas fourni dans les données JSON
return JsonResponse({'error': 'UUID non fourni dans les données JSON'}, status=400)
object = comm_opMessage.objects.get(pk=uuid) object = comm_opMessage.objects.get(pk=uuid)
object.bDone = True object.bDone = True
object.dtEnd = datetime.today() object.dtEnd = datetime.today()
object.save() object.save()
return view_op_caldav(request) return JsonResponse({'sucsess': 'UUID marqué à done'}, status=200)
@api_view(['POST'])
def view_vhc_edit_caldav(request, uuid): def view_vhc_edit_caldav(request):
print(uuid) data = json.loads(request.body.decode('utf-8'))
uuid = data.get('uuid', None)
if uuid is None:
# Gérer le cas où l'UUID n'est pas fourni dans les données JSON
return JsonResponse({'error': 'UUID non fourni dans les données JSON'}, status=400)
myClient = cls_caldav_client() myClient = cls_caldav_client()
myClient.init_caldav(caldav_url=CALDAV_URL, caldav_user=CALDAV_USER, caldav_password=CALDAV_PASSWORD)
myClient.mark_as_done_task(calandar=myClient.a_vhc,uuid=uuid) myClient.mark_as_done_task(calandar=myClient.a_vhc,uuid=uuid)
return view_vhc_caldav(request) return JsonResponse({'sucsess': 'UUID marqué à done'}, status=200)
@xframe_options_exempt @api_view(['GET'])
def view_vhc_caldav(request): def view_vhc_caldav(request):
o_caldav = cls_caldav(url=caldav_cfg["vhc"]) o_caldav = cls_caldav(url=caldav_cfg["vhc"])
o_caldav.get_caldav_data(periode=2) o_caldav.get_caldav_data(periode=2)
template = loader.get_template("vhc/vhc_view.html")
context = {'latest_task_list': o_caldav.items}
return HttpResponse(template.render(context, request))
@xframe_options_exempt response = formatResponseArray(o_caldav)
return Response(response["data"], status=response["status"])
@api_view(['GET'])
def view_rh_caldav(request): def view_rh_caldav(request):
o_caldav = cls_caldav(url=caldav_cfg["rh"]) o_caldav = cls_caldav(url=caldav_cfg["rh"])
o_caldav.get_caldav_data(periode=2) o_caldav.get_caldav_data(periode=2)
template = loader.get_template("rh/rh_view.html")
context = {'latest_task_list': o_caldav.items[::-1], 'today': datetime.today().strftime('%d.%m')}
return HttpResponse(template.render(context, request))
@xframe_options_exempt response = formatResponseArray(o_caldav,inverted=False)
return Response(response["data"], status=response["status"])
@api_view(['GET'])
def view_road_caldav(request): def view_road_caldav(request):
o_caldav = cls_caldav(url=caldav_cfg["road"]) o_caldav = cls_caldav(url=caldav_cfg["road"])
o_caldav.get_caldav_data(periode=2) o_caldav.get_caldav_data(periode=2)
template = loader.get_template("road/road_view.html") response = formatResponseArray(o_caldav, inverted=True)
context = {'latest_task_list': o_caldav.items[::-1]} return Response(response["data"], status=response["status"])
return HttpResponse(template.render(context, request))
@xframe_options_exempt
def view_op_caldav(request): def close_old_op_message():
old_items = comm_opMessage.objects.filter(bDone=False, dtEnd__lte=datetime.today() - timedelta(days=1)) old_items = comm_opMessage.objects.filter(bDone=False, dtEnd__lte=datetime.today() - timedelta(days=1))
for old_item in old_items: for old_item in old_items:
old_item.bDone = True old_item.bDone = True
old_item.save() old_item.save()
@api_view(['GET'])
def view_op_caldav(request):
close_old_op_message()
o_items = comm_opMessage.objects.filter(Q(dtStart__lte= datetime.today() + timedelta(days=1)) & ( Q(dtEnd__gte=datetime.today()) | Q(dtEnd__isnull=True))) o_items = comm_opMessage.objects.filter(Q(dtStart__lte= datetime.today() + timedelta(days=1)) & ( Q(dtEnd__gte=datetime.today()) | Q(dtEnd__isnull=True)))
all_items = [] all_items = []
for item in o_items: for item in o_items:
temp_item = caldav_item() temp_item = _caldav_item()
temp_item.uuid = item.uuid temp_item.uuid = f"{item.uuid}"
temp_item.name = item.sTitle temp_item.name = item.sTitle
temp_item.desc = item.sDesc temp_item.desc = item.sDesc
temp_item.key = item.sKey temp_item.key = item.sKey
temp_item.done = item.bDone temp_item.done = item.bDone
temp_item.str_start_date = str(item.dtStart.day) + "." + str(item.dtStart.month) temp_item.str_start_date = str(item.dtStart.strftime('%d')) + "." + str(item.dtStart.strftime('%m'))
if item.dtEnd != None: if item.dtEnd != None:
temp_item.str_end_date = str(item.dtEnd.day) + "." + str(item.dtEnd.month) temp_item.str_end_date = str(item.dtEnd.strftime('%d')) + "." + str(item.dtEnd.strftime('%m'))
else: else:
temp_item.str_end_date = None temp_item.str_end_date = None
all_items.append(temp_item) all_items.append(temp_item)
template = loader.get_template("op/op_view.html") try:
context = {'latest_task_list': all_items} serializer = CalDavItemSerializer(data=all_items, many=True)
return HttpResponse(template.render(context, request)) if serializer.is_valid():
print("Serialized Data:", serializer.data)
else:
print("Validation Error:", serializer.errors)
@xframe_options_exempt except Exception as e:
logger.error(f"An error occurred: {e}")
return Response({"error": "An error occurred while processing the request."},
status=status.HTTP_500_INTERNAL_SERVER_ERROR)
return Response({"items":serializer.data})
@api_view(['GET'])
def view_team_caldav(request): def view_team_caldav(request):
#Change timezone #Change timezone
myclient = cls_caldav_client()
#myclient.reformat_all_events(myclient.a_team)
#myclient.change_utc_to_zurich_all_events(myclient.a_team)
#myclient.reformat_all_events(myclient.a_task_config)
#myclient.change_utc_to_zurich_all_events(myclient.a_task)
o_caldav = cls_caldav(url=caldav_cfg["team"]) o_caldav = cls_caldav(url=caldav_cfg["team"])
o_caldav.get_caldav_data(periode=3) o_caldav.get_caldav_data(periode=3)
template = loader.get_template("team/team_view.html") template = loader.get_template("team/team_view.html")
o_caldav.sort_array_by_key(True) o_caldav.sort_array_by_key(True)
context = {'latest_task_list': o_caldav.day, 'night_task_list': o_caldav.night, 'today': datetime.today().strftime('%d.%m'),'yesterday': (datetime.today() + timedelta(days=-1)).strftime('%d.%m'),'tomorow': (datetime.today() + timedelta(days=+1)).strftime('%d.%m')} response = formatResponseArray(o_caldav)
return HttpResponse(template.render(context, request)) additional_data = {
'today': datetime.today().strftime('%d.%m'),
'yesterday': (datetime.today() + timedelta(days=-1)).strftime('%d.%m'),
'tomorrow': (datetime.today() + timedelta(days=1)).strftime('%d.%m')
}
response["data"].update(additional_data)
return Response(response["data"], status=response["status"])
@xframe_options_exempt
@api_view(['GET'])
def view_manif_caldav(request): def view_manif_caldav(request):
o_caldav = cls_caldav(url=caldav_cfg["manif"]) o_caldav = cls_caldav(url=caldav_cfg["manif"])
o_caldav.get_caldav_data(periode=1) o_caldav.get_caldav_data(periode=1)
template = loader.get_template("manif/manif_view.html")
o_caldav.sort_array_by_key(True) o_caldav.sort_array_by_key(True)
context = {'latest_task_list': o_caldav.items, 'night_task_list': o_caldav.night, 'today': datetime.today().strftime('%d.%m')}
return HttpResponse(template.render(context, request)) response = formatResponseArray(o_caldav)
return Response(response["data"], status=response["status"])
@xframe_options_exempt @xframe_options_exempt
def view_team_pdf_caldav(request): def view_team_pdf_caldav(request):
@@ -153,6 +228,7 @@ def view_team_pdf_caldav(request):
start = datetime.strptime(request.GET['dt'], "%d.%m.%Y") start = datetime.strptime(request.GET['dt'], "%d.%m.%Y")
myClient = cls_caldav_client() myClient = cls_caldav_client()
myClient.init_caldav(caldav_url=CALDAV_URL, caldav_user=CALDAV_USER, caldav_password=CALDAV_PASSWORD)
render_pdf(o_caldav, caldavClient=myClient, date=start) render_pdf(o_caldav, caldavClient=myClient, date=start)
return FileResponse(open('mycaldav/export.pdf', 'rb'), as_attachment=False, content_type='application/pdf') return FileResponse(open('mycaldav/export.pdf', 'rb'), as_attachment=False, content_type='application/pdf')

View File

@@ -1,57 +1,5 @@
arabic-reshaper==2.1.3
asgiref==3.7.2
asn1crypto==1.5.1
Brotli==1.0.9
caldav==0.9.1
certifi==2021.10.8
cffi==1.15.0
charset-normalizer==2.0.12
click==8.1.3
colorama==0.4.4
cryptography==37.0.1
cssselect2==0.4.1
Django Django
django-admin-rangefilter django-admin-rangefilter
fpdf==1.7.2
future==0.18.2
html5lib==1.1
icalendar==4.0.9
idna==3.3
lxml
# mysqlclient==2.1.0
oscrypto==1.3.0
pdfkit==1.0.0
Pillow==9.0.1
pycparser==2.21
pydyf==0.1.2
pyHanko==0.13.1
pyhanko-certvalidator==0.19.5
PyPDF3==1.0.6
pyphen==0.12.0
python-bidi==0.4.2
python-dateutil==2.8.2
pytz==2022.1
pytz-deprecation-shim==0.1.0.post0
PyYAML==6.0
qrcode==7.3.1
recurring-ical-events==1.0.2b0
reportlab==3.6.9
requests==2.27.1
six==1.16.0
sqlparse==0.4.2
svglib==1.2.1
tinycss2==1.1.1
tqdm==4.64.0
tzdata==2021.5
tzlocal==4.2
uritools==4.0.0
urllib3==1.26.9
vobject==0.9.6.1
weasyprint==54.1
webencodings==0.5.1
x-wr-timezone==0.0.5
xhtml2pdf==0.2.7
zopfli==0.1.9
django-autologin django-autologin
django-summernote django-summernote
django-jazzmin django-jazzmin
@@ -59,3 +7,15 @@ django-default-language
gunicorn gunicorn
whitenoise whitenoise
django-filter django-filter
djangorestframework
mysqlclient
pyocclient
django-cors-headers
pytz
python-dateutil
icalendar
recurring-ical-events
caldav
xhtml2pdf
fpdf
django-cron

7
startup.sh Executable file
View File

@@ -0,0 +1,7 @@
# startup.sh
# make sure errors stop execution
set -e
# start the cronjob
crond -f -l 8 &
# start nextjs using our own command from package.json...
python /app/manage.py runserver 0.0.0.0:8080

14
vehicles/serializers.py Normal file
View File

@@ -0,0 +1,14 @@
from django.contrib.auth.models import User, Group
from rest_framework import serializers
from.models import Vehicles_infos, Vehicles
class cl_Vehicles_Serializer(serializers.ModelSerializer):
class Meta:
model = Vehicles
fields = '__all__'
class cl_Vehicles_infos_Serializer(serializers.ModelSerializer):
class Meta:
model = Vehicles_infos
fields = '__all__'

View File

@@ -1,14 +1,17 @@
from django.urls import path from django.urls import path, include
from rest_framework import routers
from . import views from . import views
router = routers.DefaultRouter()
router.register(r'api-vehicle', views.VehicleViewset, basename='vehicle')
app_name = "vehicles" app_name = "vehicles"
urlpatterns = [ urlpatterns = [
path('vhc', views.view_vhc, name='view_vhc'), path('vhc', views.view_vhc, name='view_vhc'),
path('peremptions', views.view_peremptions, name='view_peremptions'), path('peremptions', views.view_peremptions, name='view_peremptions'),
path('', include(router.urls)),

View File

@@ -6,6 +6,20 @@ from django.template import loader
from django.views.decorators.clickjacking import xframe_options_exempt from django.views.decorators.clickjacking import xframe_options_exempt
from vehicles.models import * from vehicles.models import *
from rest_framework import viewsets
from Reskreen.rest_permission import CustomPermission_DjangoModel_based
from .serializers import cl_Vehicles_Serializer, cl_Vehicles_infos_Serializer
class VehicleViewset(viewsets.ModelViewSet):
queryset = Vehicles.objects.all()
serializer_class = cl_Vehicles_Serializer
permission_classes = [CustomPermission_DjangoModel_based]
class VehicleViewset(viewsets.ModelViewSet):
queryset = Vehicles.objects.all()
serializer_class = cl_Vehicles_Serializer
permission_classes = [CustomPermission_DjangoModel_based]
@xframe_options_exempt @xframe_options_exempt
def view_vhc(request): def view_vhc(request):