Example #1
0
    def create(self, request):
        data = request.data
        serializer = MemberSerializer(data=data)
        if serializer.is_valid():
            data = Member.validate_data(data)
        else:
            log.critical(serializer.errors)
            return Response({'error': 'Oops! Something is wrong in your request data: {}'.format(serializer.errors)},
                            status=status.HTTP_400_BAD_REQUEST)

        log.info('posted data: {}'.format(data))

        # #841 : We need to connect to Cyclos before doing Dolibarr calls, making sure Cyclos token is still valid.
        # This way, we avoid creating a member in Dolibarr if it's not the case.
        try:
            self.cyclos = CyclosAPI(token=request.user.profile.cyclos_token, mode='bdc')
        except CyclosAPIException:
            return Response({'error': 'Unable to connect to Cyclos!'}, status=status.HTTP_400_BAD_REQUEST)

        # Dolibarr: Register member
        response_obj = self.dolibarr.post(model=self.model, data=data, api_key=request.user.profile.dolibarr_token)
        log.info(response_obj)

        # Cyclos: Register member
        create_user_data = {
            'group': str(settings.CYCLOS_CONSTANTS['groups']['adherents_sans_compte']),
            'name': '{} {}'.format(data['firstname'], data['lastname']),
            'username': data['login'],
            'skipActivationEmail': True,
        }
        self.cyclos.post(method='user/register', data=create_user_data)

        return Response(response_obj, status=status.HTTP_201_CREATED)
Example #2
0
    def create(self, request):
        data = request.data
        serializer = MemberSerializer(data=data)
        if serializer.is_valid():
            data = Member.validate_data(data)
        else:
            log.critical(serializer.errors)
            return Response(
                {
                    'error':
                    'Oops! Something is wrong in your request data: {}'.format(
                        serializer.errors)
                },
                status=status.HTTP_400_BAD_REQUEST)

        log.info('posted data: {}'.format(data))

        # #841 : We need to connect to Cyclos before doing Dolibarr calls, making sure Cyclos token is still valid.
        # This way, we avoid creating a member in Dolibarr if it's not the case.
        try:
            self.cyclos = CyclosAPI(token=request.user.profile.cyclos_token,
                                    mode='bdc')
        except CyclosAPIException:
            return Response({'error': 'Unable to connect to Cyclos!'},
                            status=status.HTTP_400_BAD_REQUEST)

        # Dolibarr: Register member
        response_obj = self.dolibarr.post(
            model=self.model,
            data=data,
            api_key=request.user.profile.dolibarr_token)
        log.info(response_obj)

        # Cyclos: Register member
        create_user_data = {
            'group':
            str(settings.CYCLOS_CONSTANTS['groups']['adherents_sans_compte']),
            'name':
            '{} {}'.format(data['firstname'], data['lastname']),
            'username':
            data['login'],
            'skipActivationEmail':
            True,
        }
        self.cyclos.post(method='user/register', data=create_user_data)

        if data['email']:
            # Activate user pre-selected language
            # TODO: Ask member for his prefered lang
            # activate(data['options_langue'])

            # Translate subject & body for this email
            subject = _('Votre adhésion à Euskal Moneta')
            body = render_to_string('mails/create_member.txt', {'user': data})

            sendmail_euskalmoneta(subject=subject,
                                  body=body,
                                  to_email=data['email'])

        return Response(response_obj, status=status.HTTP_201_CREATED)
Example #3
0
def authenticate(username, password):
    user = None

    username = get_username_from_username_or_email(username)
    if not username:
        raise AuthenticationFailed()

    try:
        dolibarr = DolibarrAPI()
        dolibarr_token = dolibarr.login(login=username,
                                        password=password,
                                        reset=True)
    except (DolibarrAPIException):
        raise AuthenticationFailed()

    try:
        cyclos = CyclosAPI(mode='login')
        cyclos_token = cyclos.login(auth_string=b64encode(
            bytes('{}:{}'.format(username, password), 'utf-8')).decode(
                'ascii'))
    except CyclosAPIException:
        raise AuthenticationFailed()

    try:
        user_results = dolibarr.get(model='users',
                                    sqlfilters="login='******'".format(username),
                                    api_key=dolibarr_token)
        dolibarr_user = [
            item for item in user_results if item['login'] == username
        ][0]
    except (DolibarrAPIException, KeyError, IndexError):
        raise AuthenticationFailed()

    user, created = User.objects.get_or_create(username=username)

    user_profile = user.profile
    user_profile.cyclos_token = cyclos_token
    user_profile.dolibarr_token = dolibarr_token

    # if there is a member linked to this user, load it in order to retrieve its company name
    user_profile.companyname = ''
    if dolibarr_user['fk_member']:
        try:
            member = dolibarr.get(model='members',
                                  id=dolibarr_user['fk_member'],
                                  api_key=dolibarr_token)
            if member['company']:
                user_profile.companyname = member['company']
        except DolibarrAPIException:
            pass

    try:
        user_profile.firstname = dolibarr_user['firstname']
        user_profile.lastname = dolibarr_user['lastname']
    except KeyError:
        raise AuthenticationFailed()

    user_profile.save()

    return user
Example #4
0
def has_account(request):

    try:
        cyclos = CyclosAPI(token=request.user.profile.cyclos_token, mode='cel')

        # Determine whether or not our user is an "utilisateur" or a "prestataire"
        group_constants_without_account = [
            str(settings.CYCLOS_CONSTANTS['groups']['adherents_sans_compte'])
        ]

        group_constants_with_account = [
            str(settings.CYCLOS_CONSTANTS['groups']['adherents_prestataires']),
            str(settings.CYCLOS_CONSTANTS['groups']['adherents_utilisateurs'])
        ]

        # Fetching info for our current user (we look for his groups)
        data = cyclos.post(method='user/load',
                           data=[cyclos.user_id],
                           token=request.user.profile.cyclos_token)

        # Determine whether or not our user is part of the appropriate group
        if data['result']['group']['id'] in group_constants_without_account:
            return Response({'status': False})
        elif data['result']['group']['id'] in group_constants_with_account:
            return Response({'status': True})
        else:
            raise PermissionDenied()
    except KeyError:
        raise PermissionDenied()
Example #5
0
def change_password(request):
    """
    change_password
    """
    serializer = serializers.ChangePasswordSerializer(data=request.data)
    serializer.is_valid(raise_exception=True)  # log.critical(serializer.errors)

    try:
        cyclos_mode = request.data['cyclos_mode']
    except KeyError:
        cyclos_mode = 'bdc'

    try:
        cyclos = CyclosAPI(token=request.user.profile.cyclos_token, mode=cyclos_mode)
    except CyclosAPIException:
        return Response({'error': 'Unable to connect to Cyclos!'}, status=status.HTTP_400_BAD_REQUEST)

    # password/change
    change_password_data = {
        'user': cyclos.user_id,  # ID de l'utilisateur
        'type': str(settings.CYCLOS_CONSTANTS['password_types']['login_password']),
        'oldPassword': request.data['old_password'],  # saisi par l'utilisateur
        'newPassword': request.data['new_password'],  # saisi par l'utilisateur
        'confirmNewPassword': request.data['confirm_password'],  # saisi par l'utilisateur
    }

    return Response(cyclos.post(method='password/change', data=change_password_data))
Example #6
0
def dedicated_accounts_summaries(request):
    """
    Accounts summaries for dedicated accounts.
    """
    try:
        cyclos = CyclosAPI(token=request.user.profile.cyclos_token, mode='gi_bdc')
    except CyclosAPIException:
        return Response({'error': 'Unable to connect to Cyclos!'}, status=status.HTTP_400_BAD_REQUEST)

    query_data = []
    # Compte dédié Eusko billet: compte_dedie_eusko_billet
    # Compte dédié Eusko numérique: compte_dedie_eusko_numerique
    query_data_billet = [str(settings.CYCLOS_CONSTANTS['users']['compte_dedie_eusko_billet']), None]
    query_data.extend(cyclos.post(method='account/getAccountsSummary', data=query_data_billet)['result'])

    query_data_numerique = [str(settings.CYCLOS_CONSTANTS['users']['compte_dedie_eusko_numerique']), None]
    query_data.extend(cyclos.post(method='account/getAccountsSummary', data=query_data_numerique)['result'])

    res = {}
    filter_keys = ['compte_dedie_eusko_billet', 'compte_dedie_eusko_numerique']
    for filter_key in filter_keys:
        data = [item
                for item in query_data
                if item['owner']['id'] == str(settings.CYCLOS_CONSTANTS['users'][filter_key])][0]

        res[filter_key] = {}
        res[filter_key]['id'] = data['id']
        res[filter_key]['balance'] = float(data['status']['balance'])
        res[filter_key]['currency'] = data['currency']['symbol']
        res[filter_key]['type'] = {'name': data['type']['name'], 'id': filter_key}

    return Response(res)
Example #7
0
def export_rie_adherent(request):
    serializer = serializers.ExportRIESerializer(data=request.query_params)
    serializer.is_valid(raise_exception=True)

    try:
        cyclos = CyclosAPI(token=request.user.profile.cyclos_token, mode='cel')
    except CyclosAPIException:
        return Response({'error': 'Unable to connect to Cyclos!'},
                        status=status.HTTP_400_BAD_REQUEST)
    query_data = [cyclos.user_id, None]
    accounts_summaries_data = cyclos.post(method='account/getAccountsSummary',
                                          data=query_data)

    for account in (accounts_summaries_data['result']):
        if account['number'] == request.query_params['account']:
            # add loop to context to display rie 6 times
            context = {'account': account, 'loop': range(0, 3)}
            response = wkhtmltopdf_views.PDFTemplateResponse(
                request=request, context=context, template="summary/rie.html")
            pdf_content = response.rendered_content

            headers = {
                'Content-Disposition': 'filename="pdf_id.pdf"',
                'Content-Length': len(pdf_content),
            }

            return Response(pdf_content, headers=headers)
Example #8
0
def accounts_summaries(request, login_bdc=None):
    """
    List all accounts_summaries for this BDC user.
    """
    cyclos_mode = 'gi_bdc' if login_bdc else 'bdc'

    try:
        cyclos = CyclosAPI(token=request.user.profile.cyclos_token, mode=cyclos_mode, login_bdc=login_bdc)
    except CyclosAPIException:
        return Response({'error': 'Unable to connect to Cyclos!'}, status=status.HTTP_400_BAD_REQUEST)

    # account/getAccountsSummary
    query_data = [cyclos.user_bdc_id, None]  # ID de l'utilisateur Bureau de change
    accounts_summaries_data = cyclos.post(method='account/getAccountsSummary', data=query_data)

    # Stock de billets: stock_de_billets_bdc
    # Caisse euros: caisse_euro_bdc
    # Caisse eusko: caisse_eusko_bdc
    # Retour eusko: retours_d_eusko_bdc
    res = {}
    filter_keys = ['stock_de_billets_bdc', 'caisse_euro_bdc', 'caisse_eusko_bdc', 'retours_d_eusko_bdc']

    for filter_key in filter_keys:
        data = [item
                for item in accounts_summaries_data['result']
                if item['type']['id'] == str(settings.CYCLOS_CONSTANTS['account_types'][filter_key])][0]

        res[filter_key] = {}
        res[filter_key]['id'] = data['id']
        res[filter_key]['balance'] = float(data['status']['balance'])
        res[filter_key]['currency'] = data['currency']['symbol']
        res[filter_key]['type'] = {'name': data['type']['name'], 'id': filter_key}

    return Response(res)
Example #9
0
def notifier_crediteur(request, mandat, template):
    """
    Envoi d'une notification par email au créditeur.
    """
    # On cherche le créditeur dans Cyclos par son numéro de compte, pour avoir son numéro d'adhérent, puis on
    # charge les informations de cet adhérent dans Dolibarr et enfin, on lui envoie un email.
    try:
        dolibarr = DolibarrAPI(api_key=request.user.profile.dolibarr_token)
    except DolibarrAPIException:
        return Response({'error': 'Unable to connect to Dolibarr!'}, status=status.HTTP_400_BAD_REQUEST)
    try:
        cyclos = CyclosAPI(token=request.user.profile.cyclos_token, mode='cel')
    except CyclosAPIException:
        return Response({'error': 'Unable to connect to Cyclos!'}, status=status.HTTP_400_BAD_REQUEST)
    data = cyclos.post(method='user/search',
                       data={'keywords': mandat.numero_compte_crediteur})
    crediteur = data['result']['pageItems'][0]
    crediteur_dolibarr = dolibarr.get(model='members',
                                      sqlfilters="login='******'".format(crediteur['shortDisplay']))[0]
    # Activation de la langue choisie par l'adhérent et traduction du sujet et du corps de l'email.
    activate(crediteur_dolibarr['array_options']['options_langue'])
    subject = _("Compte Eusko : demande d'autorisation de prélèvements")
    body = render_to_string('mails/{}.txt'.format(template),
                            {'user': crediteur_dolibarr,
                             'debiteur': mandat.nom_debiteur})
    # Envoi de l'email
    sendmail_euskalmoneta(subject=subject, body=body, to_email=crediteur_dolibarr['email'])
Example #10
0
def system_accounts_summaries(request):
    """
    List all system_accounts_summaries.
    """
    try:
        cyclos = CyclosAPI(token=request.user.profile.cyclos_token, mode='gi_bdc')
    except CyclosAPIException:
        return Response({'error': 'Unable to connect to Cyclos!'}, status=status.HTTP_400_BAD_REQUEST)

    # account/getAccountsSummary
    query_data = ['SYSTEM', None]
    accounts_summaries_data = cyclos.post(method='account/getAccountsSummary', data=query_data)

    # Stock de billets: stock_de_billets
    # Compte de transit: compte_de_transit
    res = {}
    filter_keys = ['stock_de_billets', 'compte_de_transit']
    for filter_key in filter_keys:
        data = [item
                for item in accounts_summaries_data['result']
                if item['type']['id'] == str(settings.CYCLOS_CONSTANTS['account_types'][filter_key])][0]

        res[filter_key] = {}
        res[filter_key]['id'] = data['id']
        res[filter_key]['balance'] = float(data['status']['balance'])
        res[filter_key]['currency'] = data['currency']['symbol']
        res[filter_key]['type'] = {'name': data['type']['name'], 'id': filter_key}

    return Response(res)
Example #11
0
def reconvert_eusko(request):
    """
    Transfer d'eusko entre compte de particulier.
    """
    try:
        cyclos = CyclosAPI(token=request.user.profile.cyclos_token, mode='cel')
    except CyclosAPIException:
        return Response({'error': 'Unable to connect to Cyclos!'},
                        status=status.HTTP_400_BAD_REQUEST)

    serializer = serializers.ReconvertEuskoSerializer(data=request.data)
    serializer.is_valid(
        raise_exception=True)  # log.critical(serializer.errors)

    # payment/perform
    query_data = {
        'type':
        str(settings.CYCLOS_CONSTANTS['payment_types']
            ['reconversion_numerique']),
        'amount':
        serializer.data['amount'],
        'currency':
        str(settings.CYCLOS_CONSTANTS['currencies']['eusko']),
        'from':
        serializer.data['debit'],
        'to':
        'SYSTEM',
        'description':
        serializer.data['description'],
    }

    return Response(cyclos.post(method='payment/perform', data=query_data))
Example #12
0
def one_time_transfer(request):
    """
    Transfer d'eusko entre compte d'adhérent.
    """
    try:
        cyclos = CyclosAPI(token=request.user.profile.cyclos_token, mode='cel')
    except CyclosAPIException:
        return Response({'error': 'Unable to connect to Cyclos!'},
                        status=status.HTTP_400_BAD_REQUEST)
    serializer = serializers.OneTimeTransferSerializer(data=request.data)
    serializer.is_valid(
        raise_exception=True)  # log.critical(serializer.errors)

    # payment/perform
    query_data = {
        'type':
        str(settings.CYCLOS_CONSTANTS['payment_types']
            ['virement_inter_adherent']),
        'amount':
        serializer.data['amount'],
        'currency':
        str(settings.CYCLOS_CONSTANTS['currencies']['eusko']),
        'from':
        serializer.data['debit'],
        'to':
        serializer.data['beneficiaire'],
        'description':
        serializer.data['description'],
    }

    return Response(cyclos.post(method='payment/perform', data=query_data))
Example #13
0
    def __init__(self, **kwargs):
        self.__dict__.update(kwargs)
        self.cyclos = CyclosAPI()

        try:
            if self.model:
                self.dolibarr = DolibarrAPI(model=self.model)
        except AttributeError:
            self.dolibarr = DolibarrAPI()
Example #14
0
def get_current_user_account_number(request):
    """
    Renvoie le numéro de compte de l'utilisateur courant (i.e. l'utilisateur qui a fait la requête).
    """
    try:
        cyclos = CyclosAPI(token=request.user.profile.cyclos_token, mode='cel')
    except CyclosAPIException:
        return Response({'error': 'Unable to connect to Cyclos!'}, status=status.HTTP_400_BAD_REQUEST)
    accounts_summaries_data = cyclos.post(method='account/getAccountsSummary', data=[cyclos.user_id, None])
    return accounts_summaries_data['result'][0]['number']
Example #15
0
def euskokart_pin(request):
    try:
        cyclos = CyclosAPI(token=request.user.profile.cyclos_token, mode='cel')
    except CyclosAPIException:
        return Response({'error': 'Unable to connect to Cyclos!'},
                        status=status.HTTP_400_BAD_REQUEST)
    response = cyclos.post(method='password/getData', data=cyclos.user_id)
    pin_code = [
        p for p in response['result']['passwords'] if p['type']['id'] == str(
            settings.CYCLOS_CONSTANTS['password_types']['pin'])
    ][0]
    return Response(pin_code['status'])
Example #16
0
def account_summary_for_adherents(request):

    try:
        cyclos = CyclosAPI(token=request.user.profile.cyclos_token, mode='cel')
    except CyclosAPIException:
        return Response({'error': 'Unable to connect to Cyclos!'},
                        status=status.HTTP_400_BAD_REQUEST)

    query_data = [cyclos.user_id, None]

    accounts_summaries_data = cyclos.post(method='account/getAccountsSummary',
                                          data=query_data)
    return Response(accounts_summaries_data)
Example #17
0
def change_euro_eusko(request):
    """
    Change d'€ en eusko pour un adhérent via un BDC.
    """
    try:
        cyclos = CyclosAPI(token=request.user.profile.cyclos_token, mode='bdc')
    except CyclosAPIException:
        return Response({'error': 'Unable to connect to Cyclos!'}, status=status.HTTP_400_BAD_REQUEST)

    serializer = serializers.ChangeEuroEuskoSerializer(data=request.data)
    serializer.is_valid(raise_exception=True)  # log.critical(serializer.errors)

    member_cyclos_id = cyclos.get_member_id_from_login(request.data['member_login'])

    try:
        dolibarr = DolibarrAPI(api_key=request.user.profile.dolibarr_token)
        dolibarr_member = dolibarr.get(model='members', sqlfilters="login='******'".format(request.data['member_login']))[0]
    except DolibarrAPIException:
        return Response({'error': 'Unable to connect to Dolibarr!'}, status=status.HTTP_400_BAD_REQUEST)
    except IndexError:
        return Response({'error': 'Unable to fetch Dolibarr data! Maybe your credentials are invalid!?'},
                        status=status.HTTP_400_BAD_REQUEST)

    if dolibarr_member['type'].lower() == 'particulier':
        member_name = '{} {}'.format(dolibarr_member['firstname'], dolibarr_member['lastname'])
    else:
        member_name = dolibarr_member['company']

    # payment/perform
    query_data = {
        'type': str(settings.CYCLOS_CONSTANTS['payment_types']['change_billets_versement_des_euro']),
        'amount': request.data['amount'],
        'currency': str(settings.CYCLOS_CONSTANTS['currencies']['euro']),
        'from': 'SYSTEM',
        'to': cyclos.user_bdc_id,  # ID de l'utilisateur Bureau de change
        'customValues': [
            {
                'field': str(settings.CYCLOS_CONSTANTS['transaction_custom_fields']['adherent']),
                'linkedEntityValue': member_cyclos_id  # ID de l'adhérent
            },
            {
                'field': str(settings.CYCLOS_CONSTANTS['transaction_custom_fields']['mode_de_paiement']),
                'enumeratedValues': request.data['payment_mode']  # ID du mode de paiement (chèque ou espèces)
            },
        ],
        # "Change - E12345 - Nom de l'adhérent - Mode de paiement"
        'description': 'Change billets - {} - {} - {}'.format(
            request.data['member_login'], member_name, request.data['payment_mode_name']),
    }

    return Response(cyclos.post(method='payment/perform', data=query_data))
Example #18
0
def euskokart_unblock(request):
    serializer = serializers.EuskokartLockSerializer(data=request.query_params)
    serializer.is_valid(raise_exception=True)

    try:
        cyclos = CyclosAPI(token=request.user.profile.cyclos_token, mode='cel')
    except CyclosAPIException:
        return Response({'error': 'Unable to connect to Cyclos!'},
                        status=status.HTTP_400_BAD_REQUEST)

    query_data = [serializer.data['id']]

    euskokart_data = cyclos.post(method='token/unblock', data=query_data)
    return Response(euskokart_data)
Example #19
0
def payments_available_for_adherents(request):

    serializer = serializers.HistorySerializer(data=request.query_params)
    serializer.is_valid(raise_exception=True)

    try:
        cyclos = CyclosAPI(token=request.user.profile.cyclos_token, mode='cel')
    except CyclosAPIException:
        return Response({'error': 'Unable to connect to Cyclos!'},
                        status=status.HTTP_400_BAD_REQUEST)

    begin_date = serializer.data['begin'].replace(hour=0, minute=0,
                                                  second=0).isoformat()
    end_date = serializer.data['end'].replace(hour=23, minute=59,
                                              second=59).isoformat()

    query_data = [cyclos.user_id, end_date]
    accounts_summaries_data = cyclos.post(method='account/getAccountsSummary',
                                          data=query_data)

    search_history_data = {
        'orderBy': 'DATE_DESC',
        'pageSize': 1000,  # maximum pageSize: 1000
        'currentPage': 0,
        'period': {
            'begin': begin_date,
            'end': end_date,
        },
    }
    try:
        search_history_data.update(
            {'account': request.query_params['account']})
    except KeyError:
        search_history_data.update({
            'account':
            accounts_summaries_data['result'][0]['status']['accountId']
        })
    try:
        search_history_data.update(
            {'description': request.query_params['description']})
    except KeyError:
        pass

    accounts_history_res = cyclos.post(method='account/searchAccountHistory',
                                       data=search_history_data)
    return Response([
        accounts_history_res,
        accounts_summaries_data['result'][0]['status']['balance']
    ])
Example #20
0
def reconversion(request):
    """
    Reconversion eusko en euros pour un adhérent (prestataire) via un BDC.
    """
    try:
        cyclos = CyclosAPI(token=request.user.profile.cyclos_token, mode='bdc')
    except CyclosAPIException:
        return Response({'error': 'Unable to connect to Cyclos!'}, status=status.HTTP_400_BAD_REQUEST)

    serializer = serializers.ReconversionSerializer(data=request.data)
    serializer.is_valid(raise_exception=True)  # log.critical(serializer.errors)

    try:
        dolibarr = DolibarrAPI(api_key=request.user.profile.dolibarr_token)
        dolibarr_member = dolibarr.get(model='members', sqlfilters="login='******'".format(request.data['member_login']))[0]
    except DolibarrAPIException:
        return Response({'error': 'Unable to connect to Dolibarr!'}, status=status.HTTP_400_BAD_REQUEST)
    except IndexError:
        return Response({'error': 'Unable to fetch Dolibarr data! Maybe your credentials are invalid!?'},
                        status=status.HTTP_400_BAD_REQUEST)

    if dolibarr_member['type'].lower() == 'particulier':
        return Response({'error': 'Forbidden, reconversion is not available for non-business members!'},
                        status=status.HTTP_403_FORBIDDEN)

    member_cyclos_id = cyclos.get_member_id_from_login(request.data['member_login'])

    # payment/perform
    query_data = {
        'type': str(settings.CYCLOS_CONSTANTS['payment_types']['reconversion_billets_versement_des_eusko']),
        'amount': request.data['amount'],
        'currency': str(settings.CYCLOS_CONSTANTS['currencies']['eusko']),
        'from': 'SYSTEM',
        'to': cyclos.user_bdc_id,  # ID de l'utilisateur Bureau de change
        'customValues': [
            {
                'field': str(settings.CYCLOS_CONSTANTS['transaction_custom_fields']['adherent']),
                'linkedEntityValue': member_cyclos_id  # ID de l'adhérent
            },
            {
                'field': str(settings.CYCLOS_CONSTANTS['transaction_custom_fields']['numero_de_facture']),
                'stringValue': request.data['facture']  # ID Facture
            },
        ],
        'description': 'Reconversion - {} - {}'.format(request.data['member_login'], dolibarr_member['company']),
    }

    return Response(cyclos.post(method='payment/perform', data=query_data))
Example #21
0
def payments_available_for_entree_stock(request):
    """
    payments_available_for_entree_stock
    """
    serializer = serializers.PaymentsAvailableEntreeStockSerializer(data=request.query_params)
    serializer.is_valid(raise_exception=True)  # log.critical(serializer.errors)

    try:
        login_bdc = request.query_params['login_bdc']
        cyclos_mode = 'gi_bdc'
    except KeyError:
        login_bdc = None
        cyclos_mode = 'bdc'

    try:
        cyclos = CyclosAPI(token=request.user.profile.cyclos_token, mode=cyclos_mode, login_bdc=login_bdc)
    except CyclosAPIException:
        return Response({'error': 'Unable to connect to Cyclos!'}, status=status.HTTP_400_BAD_REQUEST)

    # account/searchAccountHistory
    search_history_data = {
        'account': str(settings.CYCLOS_CONSTANTS['system_accounts']['compte_de_transit']),
        'orderBy': 'DATE_DESC',
        'direction': 'CREDIT',
        'fromNature': 'SYSTEM',
        'statuses': [
            str(settings.CYCLOS_CONSTANTS['transfer_statuses']['a_rapprocher'])
        ],
        'pageSize': 1000,  # maximum pageSize: 1000
        'currentPage': 0,
    }
    accounts_summaries_res = cyclos.post(method='account/searchAccountHistory', data=search_history_data)

    # Filter out the results that are not "Sortie coffre" and items that are not for this BDC
    accounts_summaries_data = [
        item
        for item in accounts_summaries_res['result']['pageItems']
        for value in item['customValues']
        if item['type']['id'] == str(settings.CYCLOS_CONSTANTS['payment_types']['sortie_coffre']) and
        value['field']['internalName'] == 'bdc' and
        value['linkedEntityValue']['id'] == cyclos.user_bdc_id
    ]

    return Response(accounts_summaries_data)
Example #22
0
def euskokart_list(request):
    try:
        cyclos = CyclosAPI(token=request.user.profile.cyclos_token, mode='cel')
    except CyclosAPIException:
        return Response({'error': 'Unable to connect to Cyclos!'},
                        status=status.HTTP_400_BAD_REQUEST)

    query_data = [
        str(settings.CYCLOS_CONSTANTS['tokens']['carte_nfc']), cyclos.user_id
    ]

    euskokart_data = cyclos.post(method='token/getListData', data=query_data)
    try:
        euskokart_res = [item for item in euskokart_data['result']['tokens']]
    except KeyError:
        return Response({'error': 'Unable to fetch euskokart data!'},
                        status=status.HTTP_500_INTERNAL_SERVER_ERROR)

    return Response(euskokart_res)
Example #23
0
    def create(self, request, *args, **kwargs):
        """
        Créer un bénéficiaire en donnant son numéro de compte.
        """
        serializer = self.get_serializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        cyclos_account_number = serializer.validated_data[
            'cyclos_account_number']

        # Si ce bénéficiaire existe déjà, on renvoie simplement OK.
        try:
            beneficiaire = Beneficiaire.objects.get(
                owner=self.request.user,
                cyclos_account_number=cyclos_account_number)
            if beneficiaire:
                serializer = self.get_serializer(beneficiaire)
                return Response(serializer.data, status=status.HTTP_200_OK)
        except Beneficiaire.DoesNotExist:
            pass

        # Le bénéficiaire n'existe pas, on va le créer.
        # On cherche dans Cyclos l'utilisateur correspondant au numéro de compte du bénéficiaire à créer.
        try:
            cyclos = CyclosAPI(token=request.user.profile.cyclos_token,
                               mode='cel')
        except CyclosAPIException:
            return Response({'error': 'Unable to connect to Cyclos!'},
                            status=status.HTTP_400_BAD_REQUEST)
        data = cyclos.post(method='user/search',
                           data={'keywords': cyclos_account_number})
        if data['result']['totalCount'] == 0:
            return Response({'error': _("Ce numéro de compte n'existe pas")},
                            status=status.HTTP_422_UNPROCESSABLE_ENTITY)
        cyclos_user = data['result']['pageItems'][0]

        # Enregistrement du bénéficiaire en base de données.
        beneficiaire = serializer.save(owner=str(request.user),
                                       cyclos_id=cyclos_user['id'],
                                       cyclos_name=cyclos_user['display'])

        # Le bénéficiaire créé est envoyé dans la réponse.
        serializer = self.get_serializer(beneficiaire)
        return Response(serializer.data, status=status.HTTP_201_CREATED)
Example #24
0
def porteurs_eusko(request):
    """
    List porteurs d'euskos.
    """
    try:
        cyclos = CyclosAPI(token=request.user.profile.cyclos_token)
    except CyclosAPIException:
        return Response({'error': 'Unable to connect to Cyclos!'},
                        status=status.HTTP_400_BAD_REQUEST)

    # user/search for group = 'Porteurs'
    porteurs_data = cyclos.post(
        method='user/search',
        data={'groups': [settings.CYCLOS_CONSTANTS['groups']['porteurs']]})
    res = [{
        'label': item['display'],
        'value': item['id']
    } for item in porteurs_data['result']['pageItems']]

    return Response(res)
Example #25
0
def sortie_stock(request):
    """
    Enregistre une sortie dans le stock billets d'un BDC.
    """

    serializer = serializers.SortieStockBDCSerializer(data=request.data)
    serializer.is_valid(raise_exception=True)  # log.critical(serializer.errors)

    try:
        login_bdc = request.data['login_bdc']
        cyclos_mode = 'gi_bdc'
    except KeyError:
        login_bdc = None
        cyclos_mode = 'bdc'

    try:
        cyclos = CyclosAPI(token=request.user.profile.cyclos_token, mode=cyclos_mode, login_bdc=login_bdc)
    except CyclosAPIException:
        return Response({'error': 'Unable to connect to Cyclos!'}, status=status.HTTP_400_BAD_REQUEST)

    # payment/perform
    query_data = {
        'type': str(settings.CYCLOS_CONSTANTS['payment_types']['sortie_stock_bdc']),
        'amount': request.data['amount'],
        'currency': str(settings.CYCLOS_CONSTANTS['currencies']['eusko']),
        'from': cyclos.user_bdc_id,  # ID de l'utilisateur Bureau de change
        'to': 'SYSTEM',
        'customValues': [
            {
                'field': str(settings.CYCLOS_CONSTANTS['transaction_custom_fields']['porteur']),
                'linkedEntityValue': request.data['porteur']  # ID du porteur
            },
        ],
        'description': request.data['description'],
    }

    return Response(cyclos.post(method='payment/perform', data=query_data))
Example #26
0
    def search(self, request, *args, **kwargs):
        query = request.query_params.get('number', False)
        res = None
        if not query or len(query) != 9:
            return exceptions.ParseError()

        try:
            cyclos = CyclosAPI(token=request.user.profile.cyclos_token,
                               mode='cel')

            # user/search by account number only
            data = cyclos.post(
                method='user/search',
                data={'keywords': str(request.query_params['number'])})

            res = [{
                'label': item['display'],
                'id': item['id']
            } for item in data['result']['pageItems']][0]
        except (KeyError, IndexError, CyclosAPIException):
            Response(status=status.HTTP_204_NO_CONTENT)

        return Response(res) if res else Response(
            status=status.HTTP_204_NO_CONTENT)
Example #27
0
def deposit_banks(request):
    """
    List available banks.
    """
    try:
        cyclos = CyclosAPI(token=request.user.profile.cyclos_token)
    except CyclosAPIException:
        return Response({'error': 'Unable to connect to Cyclos!'},
                        status=status.HTTP_400_BAD_REQUEST)

    # user/search for group = 'Banques de dépot'
    banks_data = cyclos.post(
        method='user/search',
        data={
            'groups':
            [settings.CYCLOS_CONSTANTS['groups']['banques_de_depot']]
        })
    res = [{
        'label': item['display'],
        'value': item['id'],
        'shortLabel': item['shortDisplay']
    } for item in banks_data['result']['pageItems']]

    return Response(res)
Example #28
0
def deposit_banks_summaries(request):
    """
    Accounts summaries for deposit banks.
    """
    try:
        cyclos = CyclosAPI(token=request.user.profile.cyclos_token, mode='gi_bdc')
    except CyclosAPIException:
        return Response({'error': 'Unable to connect to Cyclos!'}, status=status.HTTP_400_BAD_REQUEST)

    # user/search for group = 'Banques de dépot'
    banks_data = cyclos.post(method='user/search',
                             data={'groups': [settings.CYCLOS_CONSTANTS['groups']['banques_de_depot']]})
    bank_names = [{'label': item['display'], 'value': item['id'], 'shortLabel': item['shortDisplay']}
                  for item in banks_data['result']['pageItems']]

    res = {}
    for bank in bank_names:
        bank_user_query = {
            'keywords': bank['shortLabel'],  # shortLabel = shortDisplay from Cyclos
        }
        try:
            bank_user_data = cyclos.post(method='user/search', data=bank_user_query)['result']['pageItems'][0]

            bank_account_query = [bank_user_data['id'], None]
            bank_data = cyclos.post(method='account/getAccountsSummary', data=bank_account_query)['result'][0]
        except (KeyError, IndexError):
                    return Response({'error': 'Unable to get bank data for one of the depositbank!'},
                                    status=status.HTTP_500_INTERNAL_SERVER_ERROR)

        res[bank['shortLabel']] = bank
        res[bank['shortLabel']]['balance'] = float(bank_data['status']['balance'])
        res[bank['shortLabel']]['currency'] = bank_data['currency']['symbol']
        res[bank['shortLabel']]['type'] = {'name': bank_data['type']['name'],
                                           'id': bank_data['type']['id']}

    return Response(res)
Example #29
0
    def create(self, request):
        data = request.data
        dolibarr_token = request.user.profile.dolibarr_token
        log.info("data: {}".format(data))
        serializer = MembersSubscriptionsSerializer(data=data)
        if not serializer.is_valid():
            log.critical("serializer.errors: {}".format(serializer.errors))
            return Response({'error': 'Oops! Something is wrong in your request data: {}'.format(serializer.errors)},
                            status=status.HTTP_400_BAD_REQUEST)

        member_id = data.get('member_id', '')
        if not member_id:
            log.critical('A member_id must be provided!')
            return Response({'error': 'A member_id must be provided!'}, status=status.HTTP_400_BAD_REQUEST)

        # #841 : We need to connect to Cyclos before doing Dolibarr calls, making sure Cyclos token is still valid.
        # This way, we avoid creating a subscription in Dolibarr if it's not the case.
        try:
            self.cyclos = CyclosAPI(token=request.user.profile.cyclos_token, mode='bdc')
        except CyclosAPIException:
            return Response({'error': 'Unable to connect to Cyclos!'}, status=status.HTTP_400_BAD_REQUEST)

        try:
            member = self.dolibarr.get(model='members', id=member_id, api_key=dolibarr_token)
        except DolibarrAPIException as e:
            log.critical("member_id: {}".format(member_id))
            log.critical(e)
            log.critical('This member_id was not found in the database!')
            return Response({'error': 'This member_id was not found in the database!'},
                            status=status.HTTP_400_BAD_REQUEST)

        data['start_date'] = Subscription.calculate_start_date(member['datefin'])
        data['end_date'] = Subscription.calculate_end_date(data['start_date'])
        data['label'] = Subscription.calculate_label(data['end_date'])

        log.info("data after: {}".format(data))

        # Register new subscription
        data_res_subscription = {'start_date': data['start_date'], 'end_date': data['end_date'],
                                 'amount': data['amount'], 'label': data['label']}
        self.model = self.model.replace('%_%', member_id)
        try:
            res_id_subscription = self.dolibarr.post(
                model=self.model, data=data_res_subscription, api_key=dolibarr_token)

            log.info("res_id_subscription: {}".format(res_id_subscription))
        except DolibarrAPIException as e:
            log.critical("model: {}".format(self.model))
            log.critical("data_res_subscription: {}".format(data_res_subscription))
            log.critical(e)
            return Response({'error': str(e)}, status=status.HTTP_400_BAD_REQUEST)

        # Register new payment
        payment_account, payment_type, payment_label = Subscription.account_and_type_from_payment_mode(data['payment_mode']) # noqa
        if not payment_account or not payment_type:
            log.critical('This payment_mode is invalid!')
            return Response({'error': 'This payment_mode is invalid!'}, status=status.HTTP_400_BAD_REQUEST)

        data_res_payment = {'date': arrow.now('Europe/Paris').timestamp, 'type': payment_type,
                            'label': data['label'], 'amount': data['amount']}
        model_res_payment = 'bankaccounts/{}/lines'.format(payment_account)
        try:
            res_id_payment = self.dolibarr.post(
                model=model_res_payment, data=data_res_payment, api_key=dolibarr_token)

            log.info("res_id_payment: {}".format(res_id_payment))
        except DolibarrAPIException as e:
            log.critical("model: {}".format(model_res_payment))
            log.critical("data_res_payment: {}".format(data_res_payment))
            log.critical(e)
            return Response({'error': str(e)}, status=status.HTTP_400_BAD_REQUEST)

        # Link this new subscription with this new payment
        data_link_sub_payment = {'fk_bank': res_id_payment}
        model_link_sub_payment = 'subscriptions/{}'.format(res_id_subscription)
        try:
            res_id_link_sub_payment = self.dolibarr.put(
                model=model_link_sub_payment, data=data_link_sub_payment, api_key=dolibarr_token)

            log.info("res_id_link_sub_payment: {}".format(res_id_link_sub_payment))
        except DolibarrAPIException as e:
            log.critical("model: {}".format(model_link_sub_payment))
            log.critical("data_link_sub_payment: {}".format(data_link_sub_payment))
            log.critical(e)
            return Response({'error': str(e)}, status=status.HTTP_400_BAD_REQUEST)

        # Link this payment with the related-member
        data_link_payment_member = {'label': '{} {}'.format(member['firstname'], member['lastname']),
                                    'type': 'member', 'url_id': member_id,
                                    'url': '{}/adherents/card.php?rowid={}'.format(
                                        settings.DOLIBARR_PUBLIC_URL, member_id)}
        model_link_payment_member = 'bankaccounts/{}/lines/{}/links'.format(payment_account, res_id_payment)
        try:
            res_id_link_payment_member = self.dolibarr.post(
                model=model_link_payment_member, data=data_link_payment_member,
                api_key=dolibarr_token)

            log.info("res_id_link_payment_member: {}".format(res_id_link_payment_member))
        except DolibarrAPIException as e:
            log.critical("model: {}".format(model_link_payment_member))
            log.critical("data_link_payment_member: {}".format(data_link_payment_member))
            log.critical(e)
            return Response({'error': str(e)}, status=status.HTTP_400_BAD_REQUEST)

        current_member = self.dolibarr.get(model='members', id=member_id, api_key=dolibarr_token)
        res = {'id_subscription': res_id_subscription,
               'id_payment': res_id_payment,
               'link_sub_payment': res_id_link_sub_payment,
               'id_link_payment_member': res_id_link_payment_member,
               'member': current_member}

        if current_member['type'].lower() in ('particulier', 'touriste'):
            member_name = '{} {}'.format(current_member['firstname'], current_member['lastname'])
        else:
            member_name = current_member['company']

        # Get Cyclos member and create it if it does not exist.
        try:
            member_cyclos_id = self.cyclos.get_member_id_from_login(current_member['login'])
        except CyclosAPIException:
            log.debug("Member not found in Cyclos, will create it.")
            create_user_data = {
                'group': str(settings.CYCLOS_CONSTANTS['groups']['adherents_sans_compte']),
                'name': '{} {}'.format(current_member['firstname'], current_member['lastname']),
                'username': current_member['login'],
                'skipActivationEmail': True,
            }
            log.debug("create_user_data = {}".format(create_user_data))
            response_data = self.cyclos.post(method='user/register', data=create_user_data)
            member_cyclos_id = response_data['result']['user']['id']
        log.debug("member_cyclos_id = {}".format(member_cyclos_id))

        # Cyclos: Register member subscription payment
        query_data = {}

        if 'Eusko' in data['payment_mode']:
            query_data.update(
                {'type': str(settings.CYCLOS_CONSTANTS['payment_types']['cotisation_en_eusko']),
                 'currency': str(settings.CYCLOS_CONSTANTS['currencies']['eusko']),
                 'customValues': [
                    {'field': str(settings.CYCLOS_CONSTANTS['transaction_custom_fields']['adherent']),
                     'linkedEntityValue': member_cyclos_id}],
                 'description': 'Cotisation - {} - {}'.format(
                    current_member['login'], member_name),
                 })
            currency = 'eusko'
        elif 'Euro' in data['payment_mode']:
            query_data.update(
                {'type': str(settings.CYCLOS_CONSTANTS['payment_types']['cotisation_en_euro']),
                 'currency': str(settings.CYCLOS_CONSTANTS['currencies']['euro']),
                 'customValues': [
                    {'field': str(settings.CYCLOS_CONSTANTS['transaction_custom_fields']['adherent']),
                     'linkedEntityValue': member_cyclos_id},
                    {'field': str(settings.CYCLOS_CONSTANTS['transaction_custom_fields']['mode_de_paiement']),
                     'enumeratedValues': data['cyclos_id_payment_mode']}],
                 'description': 'Cotisation - {} - {} - {}'.format(
                    current_member['login'], member_name, payment_label),
                 })
            currency = '€'
        else:
            return Response({'error': 'This payment_mode is invalid!'}, status=status.HTTP_400_BAD_REQUEST)

        query_data.update({
            'amount': data['amount'],
            'from': 'SYSTEM',
            'to': self.cyclos.user_bdc_id,  # ID de l'utilisateur Bureau de change
        })

        self.cyclos.post(method='payment/perform', data=query_data)

        return Response(res, status=status.HTTP_201_CREATED)
Example #30
0
def retrait_eusko_numerique(request):
    """
    Retrait eusko: numerique vers billets
    """
    try:
        cyclos = CyclosAPI(token=request.user.profile.cyclos_token, mode='bdc')
    except CyclosAPIException:
        return Response({'error': 'Unable to connect to Cyclos!'}, status=status.HTTP_400_BAD_REQUEST)

    serializer = serializers.RetraitEuskoNumeriqueSerializer(data=request.data)
    serializer.is_valid(raise_exception=True)  # log.critical(serializer.errors)

    member_cyclos_id = cyclos.get_member_id_from_login(request.data['member_login'])

    try:
        dolibarr = DolibarrAPI(api_key=request.user.profile.dolibarr_token)
        dolibarr_member = dolibarr.get(model='members', sqlfilters="login='******'".format(request.data['member_login']))[0]
    except DolibarrAPIException:
        return Response({'error': 'Unable to connect to Dolibarr!'}, status=status.HTTP_400_BAD_REQUEST)
    except IndexError:
        return Response({'error': 'Unable to fetch Dolibarr data! Maybe your credentials are invalid!?'},
                        status=status.HTTP_400_BAD_REQUEST)

    if dolibarr_member['type'].lower() == 'particulier':
        member_name = '{} {}'.format(dolibarr_member['firstname'], dolibarr_member['lastname'])
    else:
        member_name = dolibarr_member['company']

    # Verify whether or not member account has enough money
    member_account_summary_query = [member_cyclos_id, None]  # ID de l'adhérent
    member_account_summary_res = cyclos.post(method='account/getAccountsSummary', data=member_account_summary_query)

    try:
        if (member_account_summary_res['result'][0]['type']['id'] !=
           str(settings.CYCLOS_CONSTANTS['account_types']['compte_d_adherent'])):
            return Response({'error': "Unable to fetch account data!"},
                            status=status.HTTP_500_INTERNAL_SERVER_ERROR)
    except (KeyError, IndexError):
        return Response({'error': "Unable to fetch account data!"},
                        status=status.HTTP_500_INTERNAL_SERVER_ERROR)

    try:
        if float(member_account_summary_res['result'][0]['status']['balance']) < float(request.data['amount']):
            return Response({'error': "error-member-not-enough-money"})
    except (KeyError, IndexError):
        return Response({'error': "Unable to fetch account data!"},
                        status=status.HTTP_500_INTERNAL_SERVER_ERROR)

    # Verify whether or not bdc cash stock have enough money
    bdc_account_summary_query = [cyclos.user_bdc_id, None]  # ID de l'utilisateur Bureau de change
    bdc_account_summary_res = cyclos.post(method='account/getAccountsSummary', data=bdc_account_summary_query)

    bdc_account_summary_data = [
        item
        for item in bdc_account_summary_res['result']
        if item['type']['id'] == str(settings.CYCLOS_CONSTANTS['account_types']['stock_de_billets_bdc'])][0]

    if float(bdc_account_summary_data['status']['balance']) < float(request.data['amount']):
        return Response({'error': "error-bureau-not-enough-money"})

    # Débit du compte
    debit_compte_data = {
        'type': str(settings.CYCLOS_CONSTANTS['payment_types']['retrait_du_compte']),
        'amount': request.data['amount'],  # montant saisi
        'currency': str(settings.CYCLOS_CONSTANTS['currencies']['eusko']),
        'from': member_cyclos_id,  # ID de l'adhérent
        'to': 'SYSTEM',
        'customValues': [
            {
                'field': str(settings.CYCLOS_CONSTANTS['transaction_custom_fields']['bdc']),
                'linkedEntityValue': cyclos.user_bdc_id,  # ID de l'utilisateur Bureau de change
            },
        ],
        'description': 'Retrait',
    }
    cyclos.post(method='payment/perform', data=debit_compte_data)

    # Retrait des billets
    retrait_billets_data = {
        'type': str(settings.CYCLOS_CONSTANTS['payment_types']['retrait_de_billets']),
        'amount': request.data['amount'],  # montant saisi
        'currency': str(settings.CYCLOS_CONSTANTS['currencies']['eusko']),
        'from': cyclos.user_bdc_id,  # ID de l'utilisateur Bureau de change
        'to': 'SYSTEM',
        'customValues': [
            {
                'field': str(settings.CYCLOS_CONSTANTS['transaction_custom_fields']['adherent']),
                'linkedEntityValue': member_cyclos_id,  # ID de l'adhérent
            },
        ],
        'description': 'Retrait - {} - {}'.format(request.data['member_login'], member_name),
    }
    cyclos.post(method='payment/perform', data=retrait_billets_data)

    return Response(retrait_billets_data)