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
def get_usergroups(request): """ Get usergroups for a username """ serializer = serializers.GetUsergroupsSerializer(data=request.query_params) serializer.is_valid( raise_exception=True) # log.critical(serializer.errors) try: dolibarr = DolibarrAPI(api_key=request.user.profile.dolibarr_token) user_results = dolibarr.get(model='users', sqlfilters="login='******'".format( request.query_params['username'])) user_id = [ item for item in user_results if item['login'] == request.query_params['username'] ][0]['id'] except DolibarrAPIException: return Response({'error': 'Unable to connect to Dolibarr!'}, status=status.HTTP_400_BAD_REQUEST) except (KeyError, IndexError): return Response({'error': 'Unable to get user ID from your username!'}, status=status.HTTP_400_BAD_REQUEST) return Response(dolibarr.get(model='users/{}/groups'.format(user_id)))
def verify_usergroup(request): """ Verify that username is in a usergroup """ serializer = serializers.VerifyUsergroupSerializer(data=request.query_params) serializer.is_valid(raise_exception=True) # log.critical(serializer.errors) try: dolibarr = DolibarrAPI(api_key=request.query_params['api_key']) try: # validate (or not) the fact that our "username" variable is an email validate_email(request.query_params['username']) user_results = dolibarr.get(model='members', email=request.query_params['username']) user_data = [item for item in user_results if item['email'] == request.query_params['username']][0] if not user_data: return Response({'error': 'Unable to get user ID from your username!'}, status=status.HTTP_400_BAD_REQUEST) user_results = dolibarr.get(model='users', login=user_data['login']) user_id = [item for item in user_results if item['email'] == request.query_params['username']][0]['id'] except forms.ValidationError: user_results = dolibarr.get(model='users', login=request.query_params['username']) user_id = [item for item in user_results if item['login'] == request.query_params['username']][0]['id'] except DolibarrAPIException: return Response({'error': 'Unable to connect to Dolibarr!'}, status=status.HTTP_400_BAD_REQUEST) except (KeyError, IndexError): return Response({'error': 'Unable to get user ID from your username!'}, status=status.HTTP_400_BAD_REQUEST) usergroups_res = dolibarr.get(model='users/{}/groups'.format(user_id)) usergroups_ids = [item['id'] for item in usergroups_res] try: group_constant_id = str(settings.DOLIBARR_CONSTANTS['groups'][request.query_params['usergroup']]) except KeyError: return Response(status=status.HTTP_204_NO_CONTENT) if group_constant_id in usergroups_ids: return Response('OK') else: return Response(status=status.HTTP_204_NO_CONTENT)
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'])
def get_user_data(request): """ Get user data for a user. """ serializer = serializers.GetUserDataSerializer(data=request.query_params) serializer.is_valid( raise_exception=True) # log.critical(serializer.errors) try: username = serializer.data['username'] except KeyError: username = str(request.user) try: dolibarr = DolibarrAPI(api_key=request.user.profile.dolibarr_token) user_results = dolibarr.get(model='users', sqlfilters="login='******'".format(username)) user_data = [ item for item in user_results if item['login'] == username ][0] except DolibarrAPIException: return Response({'error': 'Unable to connect to Dolibarr!'}, status=status.HTTP_400_BAD_REQUEST) except IndexError: return Response({'error': 'Unable to get user data from this user!'}, status=status.HTTP_400_BAD_REQUEST) return Response(user_data)
def refuse_cgu(request): try: dolibarr = DolibarrAPI(api_key=request.user.profile.dolibarr_token) member_data = dolibarr.get(model='members', sqlfilters="login='******'".format( request.user))[0] data = {'array_options': member_data['array_options']} data['array_options'].update( {'options_accepte_cgu_eusko_numerique': False}) dolibarr.put(model='members/{}'.format(member_data['id']), data=data) # Activate user pre-selected language activate(member_data['array_options']['options_langue']) # Translate subject & body for this email subject = _('Refus des CGU') body = render_to_string('mails/refuse_cgu.txt', {'user': member_data}) sendmail_euskalmoneta(subject=subject, body=body) return Response({'status': 'OK'}) except (DolibarrAPIException, KeyError, IndexError): return Response({'error': 'Unable to update CGU field!'}, status=status.HTTP_400_BAD_REQUEST)
def countries(request): """ Get the list of countries. """ dolibarr = DolibarrAPI(api_key=request.user.profile.dolibarr_token) return Response( dolibarr.get(model='setup/dictionary/countries', lang='fr_FR'))
def countries(request): """ Get the list of countries. """ if request.user.is_authenticated: dolibarr = DolibarrAPI(api_key=request.user.profile.dolibarr_token) else: dolibarr = DolibarrAPI() dolibarr.login(login=settings.APPS_ANONYMOUS_LOGIN, password=settings.APPS_ANONYMOUS_PASSWORD) # On récupère la liste de tous les pays indiqués comme actifs dans # Dolibarr, on ne garde que l'identifiant et le nom de chaque pays, # et on trie la liste par ordre alphabétique, à l'exception de la # France qui est placée en premier. countries = dolibarr.get(model='setup/dictionary/countries', lang='fr_FR', limit='0', sqlfilters='active=1') france_id = next(c for c in countries if c['label'] == 'France')['id'] countries = [{ 'id': c['id'], 'label': c['label'] } for c in countries if c['label'] != 'France'] countries.sort(key=lambda c: c['label']) countries.insert(0, {'id': france_id, 'label': 'France'}) return Response(countries)
def get_username_from_username_or_email(username_or_email): username = '' try: # validate (or not) the fact that our "username_or_email" variable is an email validate_email(username_or_email) # we detected that our "username_or_email" variable is an email, # we try to find the user that has this email (there must be exactly one) try: dolibarr = DolibarrAPI() dolibarr_anonymous_token = dolibarr.login(login=settings.APPS_ANONYMOUS_LOGIN, password=settings.APPS_ANONYMOUS_PASSWORD, reset=True) user_results = dolibarr.get(model='users', sqlfilters="email='{}'".format(username_or_email), api_key=dolibarr_anonymous_token) matching_users = [item for item in user_results if item['email'] == username_or_email] if matching_users and len(matching_users) == 1: username = matching_users[0]['login'] except (DolibarrAPIException, KeyError, IndexError): pass except forms.ValidationError: # we detected that our "username_or_email" variable is NOT an email so it's a username username = username_or_email log.debug('get_username_from_username_or_email({}) -> {}'.format(username_or_email, username)) return username
def towns_by_zipcode(request): """ List all towns, filtered by a zipcode. """ search = request.GET.get('zipcode', '') if not search: return Response({'error': 'Zipcode must not be empty'}, status=status.HTTP_400_BAD_REQUEST) dolibarr = DolibarrAPI(api_key=request.user.profile.dolibarr_token) return Response(dolibarr.get(model='towns', zipcode=search))
class BaseAPIView(viewsets.ViewSet): 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() def list(self, request, *args, **kwargs): objects = self.dolibarr.get( model=self.model, api_key=request.user.profile.dolibarr_token) paginator = CustomPagination() result_page = paginator.paginate_queryset(objects, request) serializer = MemberSerializer(result_page, many=True) return paginator.get_paginated_response(serializer.data) def retrieve(self, request, pk=None): return Response( self.dolibarr.get(model=self.model, id=pk, api_key=request.user.profile.dolibarr_token)) def create(self, request): pass def update(self, request, pk=None): pass def partial_update(self, request, pk=None): pass def destroy(self, request, pk): return Response( self.dolibarr.delete(model=self.model, id=pk, api_key=request.user.profile.dolibarr_token))
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))
def accept_cgu(request): try: dolibarr = DolibarrAPI(api_key=request.user.profile.dolibarr_token) member_data = dolibarr.get(model='members', login=str(request.user))[0] data = {'array_options': member_data['array_options']} data['array_options'].update( {'options_accepte_cgu_eusko_numerique': True}) dolibarr.patch(model='members/{}'.format(member_data['id']), data=data) return Response({'status': 'OK'}) except (DolibarrAPIException, KeyError, IndexError): return Response({'error': 'Unable to update CGU field!'}, status=status.HTTP_400_BAD_REQUEST)
def associations(request): """ List all associations, and if you want, you can filter them. """ dolibarr = DolibarrAPI(api_key=request.user.profile.dolibarr_token) results = dolibarr.get(model='associations') approved = request.GET.get('approved', '') if approved: # We want to filter out the associations that doesn't have the required sponsorships filtered_results = [item for item in results if int(item['nb_parrains']) >= settings.MINIMUM_PARRAINAGES_3_POURCENTS] return Response(filtered_results) else: return Response(results)
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))
def towns_by_zipcode(request): """ List all towns, filtered by a zipcode. """ search = request.GET.get('zipcode', '') if not search: return Response({'error': 'Zipcode must not be empty'}, status=status.HTTP_400_BAD_REQUEST) if request.user.is_authenticated: dolibarr = DolibarrAPI(api_key=request.user.profile.dolibarr_token) else: dolibarr = DolibarrAPI() dolibarr.login(login=settings.APPS_ANONYMOUS_LOGIN, password=settings.APPS_ANONYMOUS_PASSWORD) return Response( dolibarr.get(model='setup/dictionary/towns', zipcode=search))
def login(request): """ User login from dolibarr """ serializer = serializers.LoginSerializer(data=request.data) serializer.is_valid( raise_exception=True) # log.critical(serializer.errors) try: dolibarr = DolibarrAPI() try: # validate (or not) the fact that our "username" variable is an email validate_email(request.data['username']) # we detected that our "username" variable is an email, we try to connect to dolibarr with it dolibarr_anonymous_token = dolibarr.login( login=settings.APPS_ANONYMOUS_LOGIN, password=settings.APPS_ANONYMOUS_PASSWORD) user_results = dolibarr.get( model='members', sqlfilters="email='{}' and statut=1".format( request.data['username']), api_key=dolibarr_anonymous_token) user_data = [ item for item in user_results if item['email'] == request.data['username'] ][0] if not user_data: raise AuthenticationFailed() login = user_data['login'] token = dolibarr.login(login=user_data['login'], password=request.data['password']) except forms.ValidationError: # we detected that our "username" variable is NOT an email login = request.data['username'] token = dolibarr.login(login=request.data['username'], password=request.data['password']) except (DolibarrAPIException, KeyError, IndexError): raise AuthenticationFailed() return Response({'auth_token': token, 'login': login})
def associations(request): """ List all associations, and if you want, you can filter them. """ if request.user.is_authenticated: dolibarr = DolibarrAPI(api_key=request.user.profile.dolibarr_token) else: dolibarr = DolibarrAPI() dolibarr.login(login=settings.APPS_ANONYMOUS_LOGIN, password=settings.APPS_ANONYMOUS_PASSWORD) associations = dolibarr.get(model='associations') associations.sort(key=lambda a: a['nom']) approved = request.GET.get('approved', '') if approved: # We want to filter out the associations that doesn't have the required sponsorships associations = [ asso for asso in associations if int(asso['nb_parrains']) >= settings.MINIMUM_PARRAINAGES_3_POURCENTS ] return Response(associations)
def create(self, request): """ Créer un mandat. C'est le créditeur qui crée le mandat, en donnant le numéro de compte du débiteur. """ serializer = self.get_serializer(data=request.data) serializer.is_valid(raise_exception=True) numero_compte_debiteur = serializer.validated_data['numero_compte_debiteur'] # Le créditeur est l'utilisateur courant. On récupère son numéro de compte dans Cyclos. numero_compte_crediteur = get_current_user_account_number(request) # Si ce mandat existe déjà, on renvoie simplement OK. try: mandat = Mandat.objects.get(numero_compte_crediteur=numero_compte_crediteur, numero_compte_debiteur=numero_compte_debiteur) if mandat: serializer = self.get_serializer(mandat) return Response(serializer.data, status=status.HTTP_200_OK) except Mandat.DoesNotExist: pass # Le mandat n'existe pas, on va le créer. 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) # Pour avoir le nom du débiteur, on fait une recherche dans Cyclos par son numéro de compte. data = cyclos.post(method='user/search', data={'keywords': numero_compte_debiteur}) if data['result']['totalCount'] == 0: return Response({'error': _("Ce numéro de compte n'existe pas")}, status=status.HTTP_422_UNPROCESSABLE_ENTITY) debiteur = data['result']['pageItems'][0] # Enregistrement du mandat en base de données. mandat = serializer.save( nom_debiteur=debiteur['display'], numero_compte_crediteur=numero_compte_crediteur, nom_crediteur=cyclos.user_profile['result']['display'] ) # Notification par email au débiteur. debiteur_dolibarr = dolibarr.get(model='members', sqlfilters="login='******'".format(debiteur['shortDisplay']))[0] # Activation de la langue choisie par l'adhérent et traduction du sujet et du corps de l'email. activate(debiteur_dolibarr['array_options']['options_langue']) subject = _("Compte Eusko : demande d'autorisation de prélèvements") body = render_to_string('mails/demande_autorisation_prelevements.txt', {'user': debiteur_dolibarr, 'crediteur': cyclos.user_profile['result']['display']}) sendmail_euskalmoneta(subject=subject, body=body, to_email=debiteur_dolibarr['email']) # Le mandat créé est envoyé dans la réponse. serializer = self.get_serializer(mandat) return Response(serializer.data, status=status.HTTP_201_CREATED)
def first_connection(request): """ First connection """ serializer = serializers.FirstConnectionSerializer(data=request.data) serializer.is_valid( raise_exception=True) # log.critical(serializer.errors) try: dolibarr = DolibarrAPI() dolibarr_token = dolibarr.login( login=settings.APPS_ANONYMOUS_LOGIN, password=settings.APPS_ANONYMOUS_PASSWORD) valid_login = Member.validate_num_adherent(request.data['login']) try: dolibarr.get(model='users', login=request.data['login'], api_key=dolibarr_token) return Response({'error': 'User already exist!'}, status=status.HTTP_201_CREATED) except DolibarrAPIException: pass if valid_login: # We want to search in members by login (N° Adhérent) response = dolibarr.get(model='members', login=request.data['login'], api_key=dolibarr_token) user_data = [ item for item in response if item['login'] == request.data['login'] ][0] if user_data['email'] == request.data['email']: # We got a match! # We need to mail a token etc... payload = { 'login': request.data['login'], 'aud': 'guest', 'iss': 'first-connection', 'jti': str(uuid4()), 'iat': datetime.utcnow(), 'nbf': datetime.utcnow(), 'exp': datetime.utcnow() + timedelta(hours=1) } jwt_token = jwt.encode(payload, settings.JWT_SECRET) confirm_url = '{}/valide-premiere-connexion?token={}'.format( settings.CEL_PUBLIC_URL, jwt_token.decode("utf-8")) # Activate user pre-selected language activate(user_data['array_options']['options_langue']) # Translate subject & body for this email subject = _('Première connexion à votre compte en ligne Eusko') body = render_to_string('mails/first_connection.txt', { 'token': confirm_url, 'user': user_data }) sendmail_euskalmoneta(subject=subject, body=body, to_email=request.data['email']) return Response({'member': 'OK'}) else: return Response(status=status.HTTP_400_BAD_REQUEST) else: return Response( { 'error': 'You need to provide a *VALID* login parameter! (Format: E12345)' }, status=status.HTTP_400_BAD_REQUEST) except (DolibarrAPIException, KeyError, IndexError): return Response({'error': 'Unable to get user data for this login!'}, status=status.HTTP_400_BAD_REQUEST)
def user_rights(request): # Get useful data from Cyclos for this user try: res = {'username': str(request.user)} 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) user_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 user_data['result']['group'][ 'id'] in group_constants_without_account: res.update({'has_account_eusko_numerique': False}) elif user_data['result']['group'][ 'id'] in group_constants_with_account: res.update({'has_account_eusko_numerique': True}) else: raise PermissionDenied() # Member Display name res.update({'display_name': user_data['result']['name']}) except (CyclosAPIException, KeyError): raise PermissionDenied() # Get useful data from Dolibarr for this user try: dolibarr = DolibarrAPI(api_key=request.user.profile.dolibarr_token) member_data = dolibarr.get(model='members', login=str(request.user))[0] # return Response(member_data) now = arrow.now('Europe/Paris') try: end_date_arrow = arrow.get( member_data['datefin']).to('Europe/Paris') except arrow.parser.ParserError: end_date_arrow = now res.update({ 'member_type': member_data['type'], 'has_valid_membership': True if end_date_arrow > now else False, 'lang': member_data['array_options']['options_langue'] if member_data['array_options']['options_langue'] else 'fr', 'has_accepted_cgu': True if member_data['array_options']['options_accepte_cgu_eusko_numerique'] else False }) except (DolibarrAPIException, KeyError): raise PermissionDenied() return Response(res)
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)
def depot_eusko_numerique(request): """ depot-eusko-numerique """ 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.DepotEuskoNumeriqueSerializer(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'] # Retour des Eusko billets retour_eusko_billets_data = { 'type': str(settings.CYCLOS_CONSTANTS['payment_types']['depot_de_billets']), 'amount': request.data['amount'], # montant saisi '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 }, ], 'description': 'Dépôt - {} - {}'.format(request.data['member_login'], member_name), } cyclos.post(method='payment/perform', data=retour_eusko_billets_data) # Crédit du compte Eusko numérique du prestataire depot_eusko_numerique_data = { 'type': str(settings.CYCLOS_CONSTANTS['payment_types']['credit_du_compte']), 'amount': request.data['amount'], # montant saisi 'currency': str(settings.CYCLOS_CONSTANTS['currencies']['eusko']), 'from': 'SYSTEM', 'to': member_cyclos_id, # ID de l'adhérent 'customValues': [ { 'field': str(settings.CYCLOS_CONSTANTS['transaction_custom_fields']['bdc']), 'linkedEntityValue': cyclos.user_bdc_id, # ID de l'utilisateur Bureau de change }, ], 'description': 'Dépôt', } cyclos.post(method='payment/perform', data=depot_eusko_numerique_data) return Response(depot_eusko_numerique_data)
def sortie_retour_eusko(request): """ sortie_retour_eusko """ serializer = serializers.SortieRetourEuskoSerializer(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) try: dolibarr = DolibarrAPI(api_key=request.user.profile.dolibarr_token) bdc_code = request.data['login_bdc'] bdc_name = dolibarr.get(model='users', sqlfilters="login='******'".format(bdc_code))[0]['lastname'] except DolibarrAPIException: return Response({'error': 'Unable to connect to Dolibarr!'}, status=status.HTTP_400_BAD_REQUEST) except (IndexError, KeyError): return Response({'error': 'Unable to get user data from your user!'}, status=status.HTTP_400_BAD_REQUEST) for payment in request.data['selected_payments']: try: adherent_id = [ value['linkedEntityValue']['id'] for value in payment['customValues'] if value['field']['id'] == str(settings.CYCLOS_CONSTANTS['transaction_custom_fields']['adherent']) and value['field']['internalName'] == 'adherent' ][0] except (KeyError, IndexError): return Response({'error': 'Unable to get adherent_id from one of your selected_payments!'}, status=status.HTTP_400_BAD_REQUEST) # Enregistrer les retours d'eusko sortie_retour_eusko_data = { 'type': str(settings.CYCLOS_CONSTANTS['payment_types']['sortie_retours_eusko_bdc']), 'amount': payment['amount'], # montant de l'opération correspondante 'currency': str(settings.CYCLOS_CONSTANTS['currencies']['eusko']), 'from': cyclos.user_bdc_id, # ID de l'utilisateur Bureau de change 'to': 'SYSTEM', # System account 'customValues': [ { 'field': str(settings.CYCLOS_CONSTANTS['transaction_custom_fields']['adherent']), 'linkedEntityValue': adherent_id, # ID de l'adhérent }, { 'field': str(settings.CYCLOS_CONSTANTS['transaction_custom_fields']['porteur']), 'linkedEntityValue': request.data['porteur'] # ID du porteur }, ], # "Sortie retour d'eusko - Bxxx - Nom du BDC # Opération de Z12345 - Nom du prestataire" -> description du payment initial 'description': 'Sortie retours eusko - {} - {}\n{}'.format( bdc_code, bdc_name, payment['description']) } cyclos.post(method='payment/perform', data=sortie_retour_eusko_data) # Passer tous les paiements à l'origine du dépôt à l'état "Remis à Euskal Moneta" transfer_change_status_data = { 'transfer': payment['id'], # ID du paiement (récupéré dans l'historique) 'newStatus': str(settings.CYCLOS_CONSTANTS['transfer_statuses']['remis_a_euskal_moneta']) } cyclos.post(method='transferStatus/changeStatus', data=transfer_change_status_data) return Response(request.data)
def cash_deposit(request): """ cash_deposit """ serializer = serializers.CashDepositSerializer(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) try: dolibarr = DolibarrAPI(api_key=request.user.profile.dolibarr_token) bdc_code = request.data['login_bdc'] bdc_name = dolibarr.get(model='users', sqlfilters="login='******'".format(bdc_code))[0]['lastname'] except DolibarrAPIException: return Response({'error': 'Unable to connect to Dolibarr!'}, status=status.HTTP_400_BAD_REQUEST) except (IndexError, KeyError): return Response({'error': 'Unable to get user data from your user!'}, status=status.HTTP_400_BAD_REQUEST) if request.data['mode'] == 'cash-deposit': payment_type = str(settings.CYCLOS_CONSTANTS['payment_types']['remise_d_euro_en_caisse']) currency = str(settings.CYCLOS_CONSTANTS['currencies']['euro']) description = "Remise d'espèces - {} - {}".format(bdc_code, bdc_name) elif request.data['mode'] == 'sortie-caisse-eusko': try: porteur = request.data['porteur'] except KeyError: return Response({'error': 'Porteur parameter is incorrect!'}, status=status.HTTP_400_BAD_REQUEST) payment_type = str(settings.CYCLOS_CONSTANTS['payment_types']['sortie_caisse_eusko_bdc']) currency = str(settings.CYCLOS_CONSTANTS['currencies']['eusko']) description = 'Sortie caisse eusko - {} - {}'.format(bdc_code, bdc_name) else: return Response({'error': 'Mode parameter is incorrect!'}, status=status.HTTP_400_BAD_REQUEST) # Enregistrer la remise d'espèces cash_deposit_data = { 'type': payment_type, 'amount': request.data['deposit_amount'], # montant total calculé 'currency': currency, 'from': cyclos.user_bdc_id, # ID de l'utilisateur Bureau de change 'to': 'SYSTEM', # System account 'description': description } if request.data['mode'] == 'sortie-caisse-eusko': cash_deposit_data.update({'customValues': [ { 'field': str(settings.CYCLOS_CONSTANTS['transaction_custom_fields']['porteur']), 'linkedEntityValue': porteur # ID du porteur }, ]}) cyclos.post(method='payment/perform', data=cash_deposit_data) for payment in request.data['selected_payments']: # Passer tous les paiements à l'origine du dépôt à l'état "Remis à Euskal Moneta" transfer_change_status_data = { 'transfer': payment['id'], # ID du paiement (récupéré dans l'historique) 'newStatus': str(settings.CYCLOS_CONSTANTS['transfer_statuses']['remis_a_euskal_moneta']) } cyclos.post(method='transferStatus/changeStatus', data=transfer_change_status_data) return Response(cash_deposit_data)
def euskokart_update_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) serializer = serializers.UpdatePinSerializer(data=request.data) serializer.is_valid( raise_exception=True) # log.critical(serializer.errors) query_data = { 'user': cyclos.user_id, 'type': str(settings.CYCLOS_CONSTANTS['password_types']['pin']), 'newPassword': serializer.data['pin1'], 'confirmNewPassword': serializer.data['pin2'] } try: query_data.update({'oldPassword': serializer.data['ex_pin']}) mode = 'modifiy' except KeyError: mode = 'add' try: cyclos.post(method='password/change', data=query_data) except CyclosAPIException: return Response({'error': 'Unable to set your pin code!'}, status=status.HTTP_401_UNAUTHORIZED) try: dolibarr = DolibarrAPI(api_key=request.user.profile.dolibarr_token) response = dolibarr.get(model='members', login=str(request.user)) # Activate user pre-selected language activate(response[0]['array_options']['options_langue']) if mode == 'modifiy': subject = _('Modification du code secret de votre euskokart') response_data = {'status': 'Pin modified!'} elif mode == 'add': subject = _('Choix du code secret de votre euskokart') response_data = {'status': 'Pin added!'} body = render_to_string('mails/euskokart_update_pin.txt', { 'mode': mode, 'user': response[0] }) sendmail_euskalmoneta(subject=subject, body=body, to_email=response[0]['email']) except DolibarrAPIException as e: return Response( { 'error': 'Unable to resolve user in dolibarr! error : {}'.format(e) }, status=status.HTTP_400_BAD_REQUEST) except Exception as e: return Response({'error': 'Unable to send mail! error : {}'.format(e)}, status=status.HTTP_400_BAD_REQUEST) return Response(response_data, status=status.HTTP_202_ACCEPTED)
def members_cel_subscription(request): serializer = serializers.MembersSubscriptionSerializer(data=request.data) serializer.is_valid( raise_exception=True) # log.critical(serializer.errors) try: dolibarr = DolibarrAPI(api_key=request.user.profile.dolibarr_token) member = dolibarr.get(model='members', login=str(request.user)) except DolibarrAPIException as e: return Response( { 'error': 'Unable to resolve user in dolibarr! error : {}'.format(e) }, status=status.HTTP_400_BAD_REQUEST) current_member = dolibarr.get(model='members', id=member[0]['id']) 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) if current_member['type'].lower() == 'particulier': member_name = '{} {}'.format(current_member['firstname'], current_member['lastname']) else: member_name = current_member['company'] try: data = cyclos.post(method='user/search', data={'keywords': 'Z00001'}) euskal_moneta_cyclos_id = data['result']['pageItems'][0]['id'] except (KeyError, IndexError, CyclosAPIException) as e: log.critical(e) return Response({'error': str(e)}, status=status.HTTP_400_BAD_REQUEST) query_data = { 'type': str(settings.CYCLOS_CONSTANTS['payment_types'] ['virement_inter_adherent']), 'amount': serializer.data['amount'], 'currency': str(settings.CYCLOS_CONSTANTS['currencies']['eusko']), 'from': cyclos.user_id, 'to': euskal_moneta_cyclos_id, 'description': 'Cotisation - {} - {}'.format(current_member['login'], member_name), } cyclos.post(method='payment/perform', data=query_data) # Register new subscription data_res_subscription = { 'start_date': serializer.data['start_date'].strftime('%s'), 'end_date': serializer.data['end_date'].strftime('%s'), 'amount': serializer.data['amount'], 'label': serializer.data['label'] } try: res_id_subscription = dolibarr.post( model='members/{}/subscriptions'.format(member[0]['id']), data=data_res_subscription) except Exception as e: log.critical("data_res_subscription: {}".format(data_res_subscription)) log.critical(e) return Response({'error': str(e)}, status=status.HTTP_400_BAD_REQUEST) if str(res_id_subscription) == '-1': return Response({'data returned': str(res_id_subscription)}, status=status.HTTP_409_CONFLICT) # Register new payment payment_account = 4 payment_type = 'VIR' data_res_payment = { 'date': arrow.now('Europe/Paris').timestamp, 'type': payment_type, 'label': serializer.data['label'], 'amount': serializer.data['amount'] } model_res_payment = 'accounts/{}/lines'.format(payment_account) try: res_id_payment = dolibarr.post(model=model_res_payment, data=data_res_payment) 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 = dolibarr.patch(model=model_link_sub_payment, data=data_link_sub_payment) 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[0]['firstname'], member[0]['lastname']), 'type': 'member', 'url_id': member[0]['id'], 'url': '{}/adherents/card.php?rowid={}'.format(settings.DOLIBARR_PUBLIC_URL, member[0]['id']) } model_link_payment_member = 'accounts/{}/lines/{}/links'.format( payment_account, res_id_payment) try: res_id_link_payment_member = dolibarr.post( model=model_link_payment_member, data=data_link_payment_member) 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) 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 } return Response(res, status=status.HTTP_201_CREATED)
def country_by_id(request, id): """ Get country by ID. """ dolibarr = DolibarrAPI(api_key=request.user.profile.dolibarr_token) return Response(dolibarr.get(model='countries', id=id, lang='fr_FR'))
def validate_first_connection(request): """ validate_first_connection """ serializer = serializers.ValidFirstConnectionSerializer(data=request.data) serializer.is_valid( raise_exception=True) # log.critical(serializer.errors) try: token_data = jwt.decode(request.data['token'], settings.JWT_SECRET, issuer='first-connection', audience='guest') except jwt.InvalidTokenError: return Response({'error': 'Unable to read token!'}, status=status.HTTP_400_BAD_REQUEST) try: dolibarr = DolibarrAPI() dolibarr_token = dolibarr.login( login=settings.APPS_ANONYMOUS_LOGIN, password=settings.APPS_ANONYMOUS_PASSWORD) # We check if the user already exist, if he already exist we return a 400 try: dolibarr.get(model='users', login=token_data['login'], api_key=dolibarr_token) return Response({'error': 'User already exist!'}, status=status.HTTP_201_CREATED) except DolibarrAPIException: pass # 1) Créer une réponse à une SecurityQuestion (créer aussi une SecurityAnswer). if serializer.data.get('question_id', False): # We got a question_id q = models.SecurityQuestion.objects.get( id=serializer.data['question_id']) elif serializer.data.get('question_text', False): # We didn't got a question_id, but a question_text: we need to create a new SecurityQuestion object q = models.SecurityQuestion.objects.create( question=serializer.data['question_text']) else: return Response( { 'status': ('Error: You need to provide at least one thse two fields: ' 'question_id or question_text') }, status=status.HTTP_400_BAD_REQUEST) res = models.SecurityAnswer.objects.create(owner=token_data['login'], question=q) res.set_answer(raw_answer=serializer.data['answer']) res.save() if not res: Response({'error': 'Unable to save security answer!'}, status=status.HTTP_400_BAD_REQUEST) # 2) Dans Dolibarr, créer un utilisateur lié à l'adhérent member = dolibarr.get(model='members', login=token_data['login'], api_key=dolibarr_token) create_user = '******'.format(member[0]['id']) create_user_data = {'login': token_data['login']} # user_id will be the ID for this new user user_id = dolibarr.post(model=create_user, data=create_user_data, api_key=dolibarr_token) # 3) Dans Dolibarr, ajouter ce nouvel utilisateur dans le groupe "Adhérents" user_group_model = 'users/{}/setGroup/{}'.format( user_id, settings.DOLIBARR_CONSTANTS['groups']['adherents']) user_group_res = dolibarr.get(model=user_group_model, api_key=dolibarr_token) if not user_group_res == 1: raise EuskalMonetaAPIException # 4) Dans Cyclos, activer l'utilisateur cyclos = CyclosAPI(mode='login') cyclos_token = cyclos.login(auth_string=b64encode( bytes( '{}:{}'.format(settings.APPS_ANONYMOUS_LOGIN, settings.APPS_ANONYMOUS_PASSWORD), 'utf-8')).decode('ascii')) cyclos_user_id = cyclos.get_member_id_from_login( member_login=token_data['login'], token=cyclos_token) active_user_data = { 'user': cyclos_user_id, # ID de l'utilisateur 'status': 'ACTIVE' } cyclos.post(method='userStatus/changeStatus', data=active_user_data, token=cyclos_token) # 5) Dans Cyclos, initialiser le mot de passe d'un utilisateur password_data = { 'user': cyclos_user_id, # ID de l'utilisateur 'type': str(settings.CYCLOS_CONSTANTS['password_types']['login_password']), 'newPassword': request.data['new_password'], # saisi par l'utilisateur 'confirmNewPassword': request.data['confirm_password'], # saisi par l'utilisateur } cyclos.post(method='password/change', data=password_data, token=cyclos_token) return Response({'status': 'success'}) except (EuskalMonetaAPIException, DolibarrAPIException, CyclosAPIException, KeyError, IndexError): return Response({'error': 'Unable to get user data for this login!'}, status=status.HTTP_400_BAD_REQUEST)