Пример #1
0
 def _(id, value):
     log.info(f'Update activity "{id}" status to "{status}"')
     activity = VesselActivity.objects.get(id=id)
     activity.status = status or None
     activity.save()
     return activity.to_dict(timezone="Europe/Paris",
                             include_vessel=True)
Пример #2
0
 def meme_liste(self,liste1,liste2):
     """teste si deux listes sont identiques"""
     log.info("lancement de meme liste.teste si deux listes sont identiques")
     verite = False
     if self.listes_meme_longueur(liste1,liste2):
         return self.listes_meme_contenus(liste1,liste2)
         
     else:
         return verite
Пример #3
0
            def _(id, value):

                activity = VesselActivity.objects.get(id=id)
                vessel = activity.vessel

                log.info(f'Update vessel "{vessel.id}" helico to "{obs}"')

                vessel.helico_observation = obs or None
                vessel.save()
                return activity.to_dict(timezone="Europe/Paris",
                                        include_vessel=True)
Пример #4
0
 def assertSameFileContent(self, fich1, fich2):
     #item 306
     log.info("lancement de assertSameFileContent avec {} et {}".format(fich1, fich2))
     assertion = False
     for ligne in readFichierTemporaire(fich1):
         l = readLineFichierTemporaire(fich2)
         if ligne == l:
             assertion = True
             log.info("les lignes sont similaires")
         else:
             log.error("les fichiers diffèrent: ",ligne, " vs ", l)
     return assertion
Пример #5
0
 def setSeuils(self, *args):
     """1ere resp"""
     """remplir la liste cstte de limites legales"""
     """ la liste doit etre exclusivement composee d entiers"""
     log.info(
         "lancement de Seuils.setSeuils avec pour param {}".format(args))
     print("creation d un seuil depuis", args)
     for i in args:
         if type(i) is not type(1):
             print("type(", str(i), ") vaut: ", type(i))
             print("type(1) vaut:", type(1))
             raise TypeError
     """ la liste doit etre triee"""
     self.seuils = sorted(args)
Пример #6
0
def sup25_deja_paye(heures_cp):
    log.info("appel de sup25 deja paye avec heures_cp {}".format(heures_cp))
    try:

        if heures_cp > 39:
            raise ValueError(
                'heures cp doit etre <= 39 j ai eu {} heures'.format(
                    heures_cp))
        valeur = 4 - (heures_cp * 4 / 39)
        return valeur
    except (ValueError):
        print("je passe heures cp au max soit 39. corrigez err ds cp")
        heures_cp = 39
        valeur = 4 - (heures_cp * 4 / 39)
        return valeur
Пример #7
0
        async def update_activity_status(id, status):
            """ Update ship status for the given activity """
            def _(id, value):
                log.info(f'Update activity "{id}" status to "{status}"')
                activity = VesselActivity.objects.get(id=id)
                activity.status = status or None
                activity.save()
                return activity.to_dict(timezone="Europe/Paris",
                                        include_vessel=True)

            activity = await loop.run_in_executor(None, _, id, status)
            activity['timestamp'] = pendulum.utcnow().timestamp()

            log.info(f'Update status info for activity {activity!r}')

            self.publish('smit.activity.update', activity)
            return activity
Пример #8
0
 def isSqlite3(self, filename):
     """ fich sqlite3?"""
     TAILLE_HEADER_SQLITE3 = 100
     from os.path import isfile, getsize
     if not isfile(filename):
         log.error(filename + " est pas un fich")
         return False
     if getsize(filename) < TAILLE_HEADER_SQLITE3:
         log.error("trop petit pr e fic sqlitr3")
         return False
     with open(filename, 'rb') as fd:
         header = fd.read(TAILLE_HEADER_SQLITE3)
         verite = (header[:16] == b'SQLite format 3\x00')
         if not verite:
             log.error("{}: mauvais header sqlite3".format(filename))
         else:
             log.info(
                 "fichier {} est bien de type sqlite3".format(filename))
         return verite
Пример #9
0
    def listes_meme_longueur(self,liste1=None,liste2=None):
        """teste si deux listes ont la mm longueur"""
        log.info("lancement de liste_meme_longueur avec {} et {}. teste si les deux param st des listes et ont la mm lg".format(liste1, liste2))
        self.planter_si_liste_vide(liste1,"liste1")
        self.planter_si_liste_vide(liste2,"liste2")

        
        verite = False
        if type(liste1) == type([]):
            if type(liste2) == type([]):
                verite = (len(liste1) == len(liste2))
                return verite
            else:
                print("type( ", str(liste1), "):", type(liste1))
                print("type([]): ", type([]))
                raise TypeError
        else:
            print("type( ", str(liste2), "):", type(liste2))
            print("type([]): ", type([]))
            raise TypeError
Пример #10
0
 def listes_meme_contenus(self,liste1,liste2):
     """si les deux elements sont des listes de mm lg, cherche si elles ont
     le meme contenu"""
     
     log.info("lancement de listes_meme_contenus. si les deux elements sont des listes de mm lg, cherche si elles ontle meme contenu")
     verite = True
     """ parametre: deux listes non vides"""
     """non vides"""
     if liste1 is None:
         log.critical("liste1 is none! should be list")
         raise TypeError
     if liste2 is None:
         log.critical("liste2 is none! should be list")
         raise TypeError
     
     for pos, elem in enumerate(liste1):
         if liste1[pos] != liste2[pos]:
             verite = False
             break
     return verite
Пример #11
0
        async def update_vessel_helico_obs(id, obs):
            """ Update helicopter obs for the vessel of this activity """
            def _(id, value):

                activity = VesselActivity.objects.get(id=id)
                vessel = activity.vessel

                log.info(f'Update vessel "{vessel.id}" helico to "{obs}"')

                vessel.helico_observation = obs or None
                vessel.save()
                return activity.to_dict(timezone="Europe/Paris",
                                        include_vessel=True)

            activity = await loop.run_in_executor(None, _, id, obs)
            activity['timestamp'] = pendulum.utcnow().timestamp()

            log.info(f'Update helico obs for activity {activity!r}')

            self.publish('smit.activity.update', activity)
            return activity
Пример #12
0
def gen_heures_sup_annee2(a):
    TI = [''.join(['ANNEE ', str(a)])]
    E = ['m', 'tot', '>35', '>43', '>48']
    L = list(iter_heures_sup_mois2(a))

    A = functools.reduce(somme_terme_a_terme, iter_heures_sup_mois(a),
                         [0, 0, 0, 0])
    log.debug("A {}vaut {}".format(a, A))
    log.info(TI)
    log.info(E)
    for ligne in L:
        log.info(ligne)
    log.info(["CUMUL MOIS"] + A)
    return A
Пример #13
0
def gen_heures_sup_mois2(m, a):
    TI = ["mois de {} {}".format(m, a)]
    E = ['s', 'tot', 'h>39', 'h>43', 'h>48']
    S = list(iter_heures_sup_semaines_mois2(a, m))
    M = functools.reduce(somme_terme_a_terme,
                         iter_heures_sup_semaines_mois(a, m), [0, 0, 0, 0])
    #M = ["CUMUL SEM"] + M
    log.info(TI)
    log.info(E)
    for ligne in S:
        log.info(ligne)
    log.info(["CUMUL SEM"] + M)
    log.debug("M {} de l annee {} vaut {} ".format(m, a, M))
    return [str(m), M]
Пример #14
0
    def eqv_trv_de_sup_du(mois, annee):
        ##        def eqv_trv_de_sup_sem_du(semaine, annee):
        ##            e_s = eqv_trv_de_sup_sem_du_25(semaine,annee)
        ##            + eqv_trv_de_sup_sem_du_50(semaine,annee)
        ##            + eqv_trv_de_sup_sem_du_100(semaine,annee)
        ##            return e_s
        ##        def eqv_trv_de_sup_sem_du_25(semaine,annee):
        ##            heures_effectuees_semaine = getCumulHeuresTravailleesSemaine(semaine,annee)
        ##            return bonification25(
        ##                heures_sup_25_effectuees(heures_effectuees_semaine)
        ##                )
        ##        def eqv_trv_de_sup_sem_du_50(semaine,annee):
        ##            heures_effectuees_semaine = getCumulHeuresTravailleesSemaine(semaine,annee)
        ##            return bonification50(
        ##                heures_sup_50_effectuees(heures_effectuees_semaine)
        ##                )
        ##
        ##        def eqv_trv_de_sup_sem_du_100(semaine,annee):
        ##            heures_effectuees_semaine = getCumulHeuresTravailleesSemaine(semaine,annee)
        ##            return bonification100(
        ##                heures_illegales_effectuees(heures_effectuees_semaine)
        ##                )

        eqv = 0
        import utilitaireDates
        semainesmois = list(utilitaireDates.iterSemaine(annee, mois))
        for semaine in semainesmois:
            eqv = eqv + eqv_trv_de_sup_sem_du(semaine, annee)
            phrase_debug = "eqv vaut {} lors semaine {} (sem25: {} sem50: {} sem100: {}"
            phrase_debug = phrase_debug.format(
                eqv, semaine, eqv_trv_de_sup_sem_du_25(semaine, annee),
                eqv_trv_de_sup_sem_du_50(semaine, annee),
                eqv_trv_de_sup_sem_du_100(semaine, annee))

            log.info(phrase_debug)

        return eqv
Пример #15
0
            def get_vessel(call_sign, name, draft, length, duplicates):
                """ Try to get a matching vessel """

                # get the vessel by the unique name
                if call_sign:
                    try:
                        vessel = Vessel.objects.get(call_sign=call_sign)
                        log.info(f'Known vessel: {vessel}')
                        return vessel
                    except Vessel.DoesNotExist:
                        vessel = Vessel.objects.create(
                            draft=draft,
                            length=length,
                            name=name,
                            call_sign=call_sign
                        )
                        log.info(f'New vessel: {vessel}')
                        return vessel

                # failling that, try to get the boat by the name.
                if name not in duplicates:

                    # from the boat table
                    try:
                        return Vessel.objects.get(name=name)
                    except Vessel.DoesNotExist:
                        log.info(f'New vessel: {vessel}')
                        return Vessel.objects.create(
                            draft=draft,
                            length=length,
                            name=name,
                            all_sign=call_sign
                        )
                    # or in case there are several known vessels with that
                    # name, from the most recent unique activity with this
                    # boat
                    except Vessel.MultipleObjectsReturned:
                        activity = VesselActivity.get_recent_activity_for(
                            name=name
                        )
                        if activity:
                            log.info(f'Known vessel: {activity.vessel}')
                            return activity.vessel

                return None
Пример #16
0
async def process_xml(xml):
    log.debug(f'Processing xml')
    distances = {}
    try:
        nh_settings = Settings.objects.get(active=True)
    except (Settings.DoesNotExist, Settings.MultipleObjectsReturned):
        log.error('Unable to load NH settings')
        return {}
    try:
        root = ET.fromstring(xml)
        for tag in root.findall('.//ns:ObjectData', XML_NS):
            try:
                id_tag = list(tag.findall('.//ns:Identifier', XML_NS))[0]
            except IndexError:
                continue
            try:
                call_sign = id_tag.get('Callsign').strip()
            except AttributeError:
                xmlstr = ET.tostring(id_tag, encoding='utf8', method='xml')
                log.error(f'No call sign for a vessel in this xml: {xmlstr!r}')
                continue

            try:
                pos_tag = list(tag.findall('.//ns:Pos', XML_NS))[0]
            except IndexError:
                continue
            try:
                lat = float(pos_tag.get('Lat'))
                long = float(pos_tag.get('Long'))
            except (TypeError, ValueError):
                continue

            distances[call_sign] = round(haversine(
                (nh_settings.red_dot_lat, nh_settings.red_dot_long),
                (lat, long)
            ), 2)

        try:
            log.info('Checking xml sanity. Last call sign:')
            log.info(call_sign)
        except NameError:
            log.error(f'No call signs found in xml: {xml!r}')

        log.info(f'New distances to red dot: {distances!r}')
        return distances

    except Exception as e:
        log.exception(f"Unable to read xml stream: {xml!r}")
Пример #17
0
    def run(self):
        sys.settrace(lambda *a, **k: None)

        try:
            while True:
                logger.info('{}: Start'.format(self))
                try:
                    self.running = True
                    self.callback()
                except Exception as e:
                    self.running = False
                    raise
                else:
                    self.running = False
                    logger.info('{}: Clean exit'.format(self))

        except SigFinish:
            logger.info('{}: SigFinish'.format(self))
Пример #18
0
 def planter_si_liste_vide(self,liste,nomliste):
     log.info("lancement de planter si liste vide avec {} et {}".format(liste, nomliste))
     if liste is None:
         log.critical(nomliste + " is  None. should be non empty list")
         raise TypeError
Пример #19
0
 def test_plantage_listes_memes_lg_si_param1_liste_vide(self):
     log.info("lancement de test_plantage_listes_memes_lg_si_param1_liste_vide")
     self.assertRaises(TypeError,self.listes_meme_longueur,None,[1])
Пример #20
0
async def crawl_xml(
    xml_callback=print,
    tick=10 * 60,  # 10 minutes
    max_timeout=10
):

    if not callable(xml_callback):
        raise ValueError('xml_callback must be callable')

    if not inspect.iscoroutinefunction(xml_callback):
        xml_callback = asyncio.coroutine(xml_callback)

    timeout = 1
    while True:

        try:

            try:
                nh_settings = Settings.objects.get(active=True)
            except (Settings.DoesNotExist, Settings.MultipleObjectsReturned):
                log.error('Unable to load NH settings')
                await asyncio.sleep(1)
                continue

            host = nh_settings.nh_ip_address
            port = nh_settings.nh_port
            login = nh_settings.nh_username
            pwd = nh_settings.nh_password
            tick = nh_settings.nh_refresh_rate

            log.info(f"Connection to {host}:{port}...")

            reader, writer = await asyncio.open_connection(host, port)

            with closing(writer):

                login_payload = NH_LOGIN_TEMPLATE.format(
                    login=login,
                    password=pwd
                )

                writer.write(login_payload.encode('utf8'))

                timeout = 1
                connected = True

                while connected:

                    buffer = ""
                    empty_xml = 0
                    while True:
                        log.info('Download a piece of xml.')
                        data = await reader.read(100000)
                        buffer += data.decode('utf8', errors="replace")

                        if len(buffer) > 10000000:
                            log.error('Buffer is too big. Flushing')
                            buffer = ""
                            continue

                        start = buffer.find(XML_OPENING_TAG)
                        end = buffer.find(XML_CLOSING_TAG)

                        if (start != -1 and end != -1):
                            log.info('Passing XML to callback.')
                            xml = buffer[start:end + len(XML_CLOSING_TAG)]
                            if not xml:
                                # NH has closed the socket for some reason
                                if reader.at_eof():
                                    # ask for immediat reconnection
                                    connected = False
                                    timeout = None
                                    break
                                log.error(f'XML is empty, skipping. (buffer: {buffer!r})')
                                continue



                            await xml_callback(xml)
                            break
                    else:
                        nh_settings.refresh_from_db()
                        await asyncio.sleep(nh_settings.nh_refresh_rate)
                        log.info(f'Next download in {tick}s.')
        except Exception as e:
            raise e

        if timeout is None: # requested instant reconnection before
            timeout = 1
        else:
            await asyncio.sleep(timeout)
            timeout *= 2

        if timeout > max_timeout:
            timeout = max_timeout
Пример #21
0
 def clear_old_activities():
     six_month_ago = pendulum.utcnow().add(months=-6)
     res = VesselActivity.objects.filter(modified__lt=six_month_ago).delete()
     log.info(f'Deleted old activities: {res}')
Пример #22
0
 def test_cas_heures_sup_au_premier_seuil_seuil_unique(self):
     log.info("lancement de test_cas_heures_sup_au_premier_seuil_seuil_unique")
     self.t_seuils([15,3],Seuil(15).decouper(18))
Пример #23
0
 def t_seuils(self,liste1,liste2):
     log.info("lancement de t_seuils avec: {} {}".format(liste1,liste2))
     self.assertEqual(True, self.meme_liste(liste1,liste2), '{} differe de {}'.format(liste1, liste2))
Пример #24
0
def total2():
    TI = ['TOTAL ANNEES']
    E = ['a', 'tot', '>35', '>43', '>48']
    L = list(iter_heures_sup_annees_a())

    T = functools.reduce(somme_terme_a_terme, iter_heures_sup_annees2(),
                         [0, 0, 0, 0])
    T = ['TOTAL'] + T

    log.info(TI)
    log.info(E)
    for ligne in L:
        log.info(ligne)
    log.info(T)
    log.info(T)
    log.info(
        "si l on fait un décompte qui vous est favorable (le total sur 3 ans -plus la période est longue, plus les totaux se lissent-"
    )
    log.info(
        "le total d heures supplémentaires à 25 % s'élève à {} heures".format(
            T[2]))
    log.info(
        "ce qui, comparé à 564 heures à 25% payées sur ces 3 années (47 x 4 x 3années)"
    )
    log.info(
        "représente encore {} hors bonification heures à 25% non payées. ".
        format(T[2] - 3 * 47 * 4))
    log.info("ce qui représente après bonification {} equivalent heures dûes".
             format((T[2] - 3 * 47 * 4) * 1.25))
    log.info(
        "d autre part, les heures à 50% (de 43 à 48 heures ne sont jamais rémunérées"
    )
    log.info(
        "cela représente {} hors bonification sur 3 ans jamais rémunérées".
        format(T[3]))
    log.info("soit {} heures bonifiées".format(T[3] * 1.5))
    log.info(
        "ramené en équivalent heures - bonification de 25% et 50%- cela représente {} heures dûes"
        .format(((T[2] - 3 * 47 * 4) * 1.25) + (T[3] * 1.50)))
    log.info(
        "enfin, sur ces 3 ans, {} heures ont été effectuées au-delà du maximum légal de 48 heures."
        .format(T[4]))
    log.info(
        "comment comptez vous les rémunérer? à 100% cela ajoute encore {} heures dûes"
        .format(T[4] * 2))
Пример #25
0
async def crawl_csv(
    host,
    port,
    login,
    pwd,
    path,
    csv_callback=print,
    tick=10 * 60,  # 10 minutes
    max_timeout=10
):

    if not callable(csv_callback):
        raise ValueError('csv_callback must be callable')

    if not inspect.iscoroutinefunction(csv_callback):
        csv_callback = asyncio.coroutine(csv_callback)

    timeout = 1
    while True:

        try:

            try:
                ftp_settings = Settings.objects.get(active=True)
            except (Settings.DoesNotExist, Settings.MultipleObjectsReturned):
                log.error('Unable to load ftp settings')
                await asyncio.sleep(1)
                continue

            host = ftp_settings.sirene_ftp_ip_address
            port = ftp_settings.sirene_ftp_port
            login = ftp_settings.sirene_ftp_username
            pwd = ftp_settings.sirene_ftp_password
            tick = ftp_settings.sirene_ftp_refresh_rate
            path = ftp_settings.sirene_csv_file_path

            log.info(f"Connection to {host}:{port}...")

            async with aioftp.ClientSession(host, port, login, pwd) as client:

                timeout = 1
                while True:

                    if not await client.exists(path):
                        log.error(
                            f"'{path}' can't be "
                            f"found on FTP {host}:{port}"
                        )
                    else:
                        log.info('Downloading csv.')
                        async with client.download_stream(path) as stream:
                            log.info('Passing csv to callback.')
                            await csv_callback(stream)
                            log.info('Callback ok.')

                    log.info(f'Next download in {tick}s.')
                    ftp_settings.refresh_from_db()
                    await asyncio.sleep(ftp_settings.sirene_ftp_refresh_rate)

        except AttributeError as e:

            if "'Client' object has no attribute 'stream'" in str(e):
                log.warning(
                    f"Unable to connect to FTP {host}:{port}\n"
                    f"Retrying in {timeout}s"
                )
            else:
                raise

        except aioftp.errors.StatusCodeError as e:
            if '530' in e.received_codes:
                log.error(
                    f"The login or password has been "
                    f'rejected by {host}:{port}'
                )
            else:

                log.warning(
                    f"Connection to {host}:{port} failed with: '{e}'\n"
                    f"Retrying in {timeout}s"
                )

        except ConnectionResetError:

                log.warning(
                    f"Connection to {host}:{port} lost\n"
                    f"Retrying in {timeout}s"
                )

        await asyncio.sleep(timeout)
        timeout *= 2

        if timeout > max_timeout:
            timeout = max_timeout
Пример #26
0
 def test_production_intervalles_multiples_3(self):
     log.info("lancement de test_production_intervalles_multiples_3")
     self.t_seuils([15,3,1],Seuil(15,18,19).getIntervalles())
Пример #27
0
def total3():

    TI = ['TOTAL ANNEES']
    E = ['a', 'tot', '>35', '>43', '>48']
    L = list(iter_heures_sup_annees_a())

    T = functools.reduce(somme_terme_a_terme, iter_heures_sup_annees2(),
                         [0, 0, 0, 0])
    T = ['TOTAL'] + T
    log.info(" ")
    log.info(
        "si l on arrete le décompte chaque mois, comme cela devrait etre le cas,"
    )
    log.info(
        "et qu on oppose ce qui devrait etre paye à ce qui a effectivement été payé,"
    )
    log.info(" ne décomptant que ce qui mnaque mois par mois,")
    log.info("alors on arrive au décompte suivant:")
    log.info("modifier gen_semaines pour cumul au mois soit 4h par sem trav")
    """
Пример #28
0
def prejudice():
    """hsrd = hss_effectuee - hsspayee.
       les heures négatives ?   c est le point le plus important:
       trois positions possibles:
         1) les heures sont perdues pour l employeur et le décompte se fait à la semaine, paiement au mois
         2) les heures ne sont pas perdues pour l employeur et le cumul se fait algébriquement sur le mois
         3) les heures ne sont pas perdues pour l employeur et le cumul se fait algébriquement sur l'année.
         4) il n'y a jamais de perte pour l'employeur et le compteur n est jamais perdu pour l employeur.
         je penche pour le type 3 pour l instant:
         il s'agit d une CORRECTION DU PAIEMENT REEL PAR RAPPORT A UN PAIEMENT DU
         pour qualifier un DOL
         PAR CONTRE QUEL QUE SOIT LE RESULTAT, LE COMPTEUR DE DIFF25
         EST REMIS A ZERO au 1er janvier

         des exceptions sont à prendre en compte:
         pendant certaines semaines de congés payées, on travaille.
         on est à la fois en congés et au travail.
         cela se résoud en considérant cela comme des heures supplémentaires:
         en effet, les cp sont censées se substituer à des jours de travail
         mais ils sont payés comme des jours de travail (les heures à poser
         pour un jour de cp correspond à la moyenne des heures d une semaine
         de travail normal)
       """
    """ALGO:    pour chaque semaine du mois:
        probleme | semaine à exclure | semaine à inclure
        si semaine_travaillée et semaine_cp => probleme 
        si non semaine travaillee et semeaince cp => semaine a exclure
        sinon semaine  à inclure
        pour chaque semaine à inclure du mois:
            pour chaque type_d heures sup:
                heure_sup_dues vs heures_sup_payees.
                si heures sup_dues:
                    ajouter (typeheures_sup : + heures_sup_dues)
                si heures_en_trop:
                    ajouter(typeheures_sup: cagnotte globale)
    fin_du_mois :
        pour chaque type_heures_sup:
            pour chaque_semaine:
                ajouter_type_heures_sup
            ajouter_cagnotte
            vider_cagnotte
            si_heures_sup:
                ajouter_heures_sup
        renvoyer tableau_heures_sup_mensuellesje vex une methode restant_dues qui
           permette de calculer le nombre d heures restant dues
           à 25% .
           mon employeur me paie effectivement 169 heures par mois
           dont 4 bonifiées à 25 %:
           il applique la l3121-31:
  Article L3121-31 En savoir plus sur cet article...
Modifié par LOI n°2016-1088 du 8 août 2016 - art. 8 (V)
Dans les entreprises dont la durée collective hebdomadaire de travail est supérieure
à la durée légale hebdomadaire, la rémunération mensuelle due au salarié peut être calculée
en multipliant la rémunération horaire par les cinquante-deux douzièmes de cette durée hebdomadaire de travail,
en tenant compte des majorations de salaire correspondant aux heures supplémentaires accomplies.

          cependant si dans mon contrat l'annualisaiont n'est pas valable,
          alors les 39 non plus (pas un self service ou on prend une partie
          et pas le reste)
          le raisonnement de l'avocat est de partir des 35 heures sur la base
          des art 3121-27 et 3121-28 et 29:
          1) compter la qté d heures de chaque semaine travaillée.
             si plus de 35 heures 25% dues.
           2) cumuler ca à l'année.

Article L3121-27 En savoir plus sur cet article...
Modifié par LOI n°2016-1088 du 8 août 2016 - art. 8 (V)
La durée légale de travail effectif des salariés à temps complet est fixée à trente-cinq heures par semaine.

Article L3121-28 En savoir plus sur cet article...
Modifié par LOI n°2016-1088 du 8 août 2016 - art. 8 (V)
Toute heure accomplie au delà de la durée légale hebdomadaire
ou de la durée considérée comme équivalente est une heure supplémentaire
qui ouvre droit à une majoration salariale ou, le cas échéant,
à un repos compensateur équivalent.

Article L3121-29 En savoir plus sur cet article...
Modifié par LOI n°2016-1088 du 8 août 2016 - art. 8 (V)
Les heures supplémentaires se décomptent par semaine.

Article L3121-30 En savoir plus sur cet article...
Modifié par LOI n°2016-1088 du 8 août 2016 - art. 8 (V)
Des heures supplémentaires peuvent être accomplies
dans la limite d'un contingent annuel.
Les heures effectuées au delà de ce contingent annuel
ouvrent droit à une contrepartie obligatoire sous forme de repos.

Les heures prises en compte pour le calcul du contingent
annuel d'heures supplémentaires sont celles accomplies
au delà de la durée légale.

Les heures supplémentaires ouvrant droit
au repos compensateur équivalent mentionné à l'article L. 3121-28
et celles accomplies dans les cas de travaux urgents
énumérés à l'article L. 3132-4
ne s'imputent pas sur le contingent annuel d'heures supplémentaires.

AUTRE PT DE VUE:
les heures sup dues sur un mois somment les heures sup dues des semaines terminees
elles representent apres bonification un eqv heures trav
comparable à l eqv heures trav de la bonif payée effectivement.
elles permettent donc de déterminer un préjudice.


        """

    anneesdispo = list(db.bdd().iterAnneesDispo())
    moisannee = list(range(1, 13))

    def eqv_trv_de_sup_paye_obsolete(mois, annee):
        cste_h25_payee_mois = 17.33
        return bonification25(cste_h25_payee_mois)

    def eqv_trv_de_sup_sem_paye(semaine, annee):
        heures_cp = getCumulHeuresCpSemaine(annee, semaine)
        paye_semaine = sup25_deja_paye(heures_cp)
        if heures_cp:
            phrase_cp_non_nuls = "en semaine {}, {} heures de cp ramenent les hsup payéees de 4 à {}"
            phrase_cp_non_nuls = phrase_cp_non_nuls.format(
                semaine, annee, paye_semaine)
            log.critical(phrase_cp_non_nuls)
        else:
            phrase_cp_nuls = "{} heures ont été payées à 25% au titre de la mens des heures de 35 à 39h"
            phrase_cp_nuls = phrase_cp_nuls.format(paye_semaine)
            log.debug(phrase_cp_nuls)
        return bonification25(paye_semaine)

    def eqv_trv_de_sup_paye(mois, annee):
        eqv = 0
        import utilitaireDates
        semainesmois = list(utilitaireDates.iterSemaine(annee, mois))
        for semaine in semainesmois:
            eqv = eqv + eqv_trv_de_sup_sem_paye(semaine, annee)
            phrase_debug = "eqv trv de paye vaut {} lors semaine {}"
            phrase_debug = phrase_debug.format(
                eqv_trv_de_sup_sem_paye(semaine, annee), semaine)

            log.debug(phrase_debug)

        return eqv

    def bonification25(heures):
        return heures * 1.25

    def bonification50(heures):
        return heures * 1.50

    def bonification100(heures):
        return heures * 2

    def eqv_trv_de_sup_du(mois, annee):
        ##        def eqv_trv_de_sup_sem_du(semaine, annee):
        ##            e_s = eqv_trv_de_sup_sem_du_25(semaine,annee)
        ##            + eqv_trv_de_sup_sem_du_50(semaine,annee)
        ##            + eqv_trv_de_sup_sem_du_100(semaine,annee)
        ##            return e_s
        ##        def eqv_trv_de_sup_sem_du_25(semaine,annee):
        ##            heures_effectuees_semaine = getCumulHeuresTravailleesSemaine(semaine,annee)
        ##            return bonification25(
        ##                heures_sup_25_effectuees(heures_effectuees_semaine)
        ##                )
        ##        def eqv_trv_de_sup_sem_du_50(semaine,annee):
        ##            heures_effectuees_semaine = getCumulHeuresTravailleesSemaine(semaine,annee)
        ##            return bonification50(
        ##                heures_sup_50_effectuees(heures_effectuees_semaine)
        ##                )
        ##
        ##        def eqv_trv_de_sup_sem_du_100(semaine,annee):
        ##            heures_effectuees_semaine = getCumulHeuresTravailleesSemaine(semaine,annee)
        ##            return bonification100(
        ##                heures_illegales_effectuees(heures_effectuees_semaine)
        ##                )

        eqv = 0
        import utilitaireDates
        semainesmois = list(utilitaireDates.iterSemaine(annee, mois))
        for semaine in semainesmois:
            eqv = eqv + eqv_trv_de_sup_sem_du(semaine, annee)
            phrase_debug = "eqv vaut {} lors semaine {} (sem25: {} sem50: {} sem100: {}"
            phrase_debug = phrase_debug.format(
                eqv, semaine, eqv_trv_de_sup_sem_du_25(semaine, annee),
                eqv_trv_de_sup_sem_du_50(semaine, annee),
                eqv_trv_de_sup_sem_du_100(semaine, annee))

            log.info(phrase_debug)

        return eqv

    cumul_total_posit = 0
    cumul_total_neg = 0
    cumul_total = 0
    for annee in anneesdispo:
        cumul_annuel_posit = 0
        cumul_annuel_neg = 0
        bilan_annuel = 0
        for mois in moisannee:
            cumul_mensuel_posit = 0
            cumul_mensuel_neg = 0

            p = eqv_trv_de_sup_paye(mois, annee)
            d = eqv_trv_de_sup_du(mois, annee)
            phrase_datation = "pour mois {} annee {}".format(mois, annee)
            phrase_ok_ko = phrase_datation + "\n paye {} alors que du {}".format(
                p, d)
            phrase_cumul_mensuel = "cumul mensuel de {}".format(d - p)
            if p >= d:
                log.info(phrase_ok_ko)
                cumul_mensuel_neg = d - p
                log.info(phrase_cumul_mensuel)

            else:
                log.critical(phrase_ok_ko)
                cumul_mensuel_posit = d - p
                log.critical(phrase_cumul_mensuel)
                log.critical(
                    "prejudice de {} pour le mois".format(cumul_mensuel_posit))

            cumul_annuel_posit = cumul_annuel_posit + cumul_mensuel_posit
            cumul_annuel_neg = cumul_annuel_neg + cumul_mensuel_neg
            # fin de pour chaque mois de l'année
        # debut de pour chaque année
        log.critical(
            "cumul_annuel_posit (le seul à prendre en ocmpte puisque les heures sup sont comptees à la semaine et payees au mois. on s arrete donc au décompte des mois positifs): {}"
            .format(cumul_annuel_posit))
        log.info("cumul_annuel_neg : {}".format(cumul_annuel_neg))
        log.critical("prejudice annuel (prejudice si posit) {}".format(
            cumul_annuel_posit + cumul_annuel_neg))
        cumul_total_posit = cumul_annuel_posit + cumul_total_posit
        cumul_total_neg = cumul_annuel_neg + cumul_total_neg
        # fin de pour chaque annee
    #debut de decompte final
    log.critical(
        "pour action: cumul total posit : {}".format(cumul_total_posit))
    log.info("pour info : cumul total neg: {}".format(cumul_total_neg))
    cumul_total = cumul_total_posit + cumul_total_neg
    log.critical("prejudice si chiffre positif: {}".format(cumul_total))
Пример #29
0
async def save_csv(
    stream,
    encoding='utf8',
    new_activity_delay=5 * 3600,
    timezone='Europe/Paris'
):
    now = pendulum.utcnow().timestamp()
    vessel_activities = []
    loop = asyncio.get_event_loop()
    try:

        text = await stream.read(10_000_000)
        text = text.decode(encoding=encoding, errors='replace')

        # Check if we have several vessels with the same name
        duplicate_names = {}
        for row in DictReaderStrip(io.StringIO(text)):
            name = get_text_field(row, 'NOMNAVIRE')
            duplicate_names[name] = duplicate_names.get(name, 0) + 1

        duplicate_names = {
            name: count
            for name, count in duplicate_names.items()
            if count > 1
        }

        all_call_signs = set()
        for i, row in enumerate(DictReaderStrip(io.StringIO(text))):

            vessel_activity_dict = {'timestamp': now}

            # Example of row:
            # OrderedDict([
            #   ('MOUVEMENT', 'E'),
            #   ('NUMERODEMANDE', '198678'),
            #   ('NOMNAVIRE', 'BUTES'),
            #   ('LONGUEUR', '87.84'),
            #   ('TIRANTEAU', '3.3'),
            #   ('POSTEAQUAI', ''),
            #   ('PROVENANCE', 'Warrenpoint'),
            #   ('DESTINATION', 'Sevilla'),
            #   ('DATEDEBUTMVTPREVUE', '27/05/2016 00:01'),
            #   ('NUMEROSOFI', '194323'),
            #   ('NAVIREDANGEREUX', '0'),
            #   ('CALLSIGN', 'A8UR6'),
            #   ('TYPEVTS', '4'),
            #   ('NUMEROLLOYD', '9409637'),
            #   ('BONPOURMOUVEMENT', '0'),
            #   ('OBSERVATIONS', '')
            #   ])

            call_sign = get_text_field(row, 'CALLSIGN')

            # duplicate call sign. There is nothing we can do but
            # ignore it
            if call_sign and call_sign in all_call_signs:
                log.error(f'Duplicate call sign {call_sign}')
                continue

            all_call_signs.add(call_sign)

            draft = get_num_field(row, 'TIRANTEAU')
            length = get_num_field(row, 'LONGUEUR')
            name = get_text_field(row, 'NOMNAVIRE')

            # no name and no call sign: nothing we can do
            if not call_sign and not name:
                continue

            def get_vessel(call_sign, name, draft, length, duplicates):
                """ Try to get a matching vessel """

                # get the vessel by the unique name
                if call_sign:
                    try:
                        vessel = Vessel.objects.get(call_sign=call_sign)
                        log.info(f'Known vessel: {vessel}')
                        return vessel
                    except Vessel.DoesNotExist:
                        vessel = Vessel.objects.create(
                            draft=draft,
                            length=length,
                            name=name,
                            call_sign=call_sign
                        )
                        log.info(f'New vessel: {vessel}')
                        return vessel

                # failling that, try to get the boat by the name.
                if name not in duplicates:

                    # from the boat table
                    try:
                        return Vessel.objects.get(name=name)
                    except Vessel.DoesNotExist:
                        log.info(f'New vessel: {vessel}')
                        return Vessel.objects.create(
                            draft=draft,
                            length=length,
                            name=name,
                            all_sign=call_sign
                        )
                    # or in case there are several known vessels with that
                    # name, from the most recent unique activity with this
                    # boat
                    except Vessel.MultipleObjectsReturned:
                        activity = VesselActivity.get_recent_activity_for(
                            name=name
                        )
                        if activity:
                            log.info(f'Known vessel: {activity.vessel}')
                            return activity.vessel

                return None

            vessel = await loop.run_in_executor(
                None,
                get_vessel,
                call_sign,
                name,
                draft,
                length,
                duplicate_names
            )

            if not vessel:
                log.error(f'Anonymous vessel record: {row}')

            # If we can find a vessel, we update its values
            else:

                before = repr(vessel)

                if draft and vessel.draft != draft:
                    vessel.draft = draft
                if length and vessel.length != length:
                    vessel.length = length
                if name and vessel.name != name:
                    vessel.name = name

                after = repr(vessel)

                if before != after:
                    await loop.run_in_executor(None, vessel.save)
                    log.info(f'Vessel data has changed to: {vessel!r}')

            # the serialized vessel activity is either from db
            # or, lacking from a known vessel, constructed from the
            # date from the csv
            vessel_activity = None
            if vessel:
                vessel_activity_dict['anonymous'] = False
                vessel_activity_dict.update(vessel.to_dict())
                vessel_activity = await loop.run_in_executor(
                    None,
                    vessel.get_latest_activity,
                    new_activity_delay
                )
            else:
                vessel_activity_dict['anonymous'] = True
                vessel_activity_dict['name'] = name
                vessel_activity_dict['length'] = length
                vessel_activity_dict['draft'] = draft
                vessel_activity_dict['call_sign'] = call_sign

            if not vessel_activity:
                vessel_activity = VesselActivity(vessel=vessel)

            activity_type = get_text_field(row, 'MOUVEMENT')
            vessel_activity.type = ({
                'S': 'departing',
                'E': 'incomming',
                'D': 'shifting'
            }).get(activity_type)

            vessel_activity.good_to_go = bool(get_num_field(
                row,
                'NOMBREDETUGS',
                cast=int,
                default=0)
            )

            incoming_from = get_text_field(row, 'PROVENANCE')
            vessel_activity.incoming_from = incoming_from

            leaving_to = get_text_field(row, 'DESTINATION')
            vessel_activity.leaving_to = leaving_to

            berth = get_text_field(row, 'POSTEAQUAI')
            vessel_activity.berth = berth

            services = get_text_field(row, 'DEBUTDESOPERATIONSCOMMERCIALES')
            vessel_activity.services = services or None

            vessel_activity.tugs = get_num_field(row, 'NOMBREDETUGS', int)

            try:
                date = get_text_field(row, 'DATEDEBUTMVTPREVUE') or ''
                sirene_time_estimate = pendulum.parse(
                    date,
                    tz=timezone
                )
            except (ValueError, AttributeError):
                sirene_time_estimate = None
            vessel_activity.sirene_time_estimate = sirene_time_estimate

            obs = get_text_field(row, 'OBSERVATIONS')
            vessel_activity.sirene_observation = obs

            vessel_activity.dangerous_materials = get_num_field(
                row,
                'NAVIREDANGEREUX',
                int
            )

            # we only create a vessel activity if we have a named vessel
            # since we could not get it back later anyway with it
            if vessel:
                vessel_activity.save()

            # serialized vessel activity data is completed with previous
            # data from db and the one found in the csv plus a few
            # adjustment for the front end
            vessel_activity_dict.update(vessel_activity.to_dict(timezone))

            if vessel_activity_dict['anonymous']:
                # generate a fake unique id for this name
                duplicate_index = duplicate_names.setdefault(name, 0) - 1
                unique_name = f"{name}/{duplicate_index}".encode('utf8')
                fake_id = hashlib.sha256(unique_name).hexdigest()
                duplicate_names[name] -= 1
                vessel_activity_dict['id'] = fake_id

            vessel_activities.append(vessel_activity_dict)
    except Exception as e:
        log.exception("Unable to read csv file.")

    # clear all activities older than 6 months
    def clear_old_activities():
        six_month_ago = pendulum.utcnow().add(months=-6)
        res = VesselActivity.objects.filter(modified__lt=six_month_ago).delete()
        log.info(f'Deleted old activities: {res}')
    await loop.run_in_executor(None, clear_old_activities)

    return vessel_activities