def post(self, request): serializer = AllowedGuaranteeRequestSerializer(data=request.data) if serializer.is_valid(): allowed = serializer.validated_data['allow_public_guarantees'] circle, member = Circle.objects.get( circle_acc_number=serializer. validated_data['circle_acc_number']), request.user.member if allowed == 'true': try: circle_member = CircleMember.objects.get(circle=circle, member=member) CircleMember.objects.filter( circle=circle, member=member).update( allow_public_guarantees_request=True) AllowedGuarantorRequest.objects.filter( circle_member=circle_member).delete() except Exception as e: print(str(e)) CircleMember.objects.filter( circle=circle, member=member).update( allow_public_guarantees_request=False) data = { "status": 0, "message": "Unable to change allowed guarantees setting" } return Response(data, status=status.HTTP_200_OK) fcm_data = { "request_type": "UPDATE_ALLOW_GUARANTOR_REQUEST", "circle_acc_number": circle.circle_acc_number, "phone_number": member.phone_number, "allow_guarantor_request": True } fcm_instance = fcm_utils.Fcm() registration_ids = fcm_instance.get_circle_members_token( circle, member) fcm_instance.data_push("multiple", registration_ids, fcm_data) print(fcm_data) updating_loan_limit.delay(circle.id, member.id) data = {"status": 1} return Response(data, status=status.HTTP_200_OK) fcm_instance = fcm_utils.Fcm() registration_ids = fcm_instance.get_circle_members_token( circle, member) fcm_data = { "request_type": "UPDATE_ALLOW_GUARANTOR_REQUEST", "circle_acc_number": circle.circle_acc_number, "phone_number": member.phone_number, "allow_guarantor_request": False } fcm_instance.data_push("multiple", registration_ids, fcm_data) print(fcm_data) updating_loan_limit.delay(circle.id, member.id) CircleMember.objects.filter( circle=circle, member=member).update(allow_public_guarantees_request=False) data = {"status": 1} return Response(data, status=status.HTTP_200_OK) data = {"status": 0, "message": serializer.errors} return Response(data, status=status.HTTP_200_OK)
def send_chat_to_all_members(message, message_channel): if message_channel == 1: instance = fcm_utils.Fcm() device_tokens = Member.objects.all().values_list('device_token', flat=True) fcm_data = { 'request_type': 'REPLY_TO_CHAT', 'sender': 'Opencircles', 'body': message, 'time_sent': datetime.datetime.now().strftime('%Y-%m-%d %H-%m-%s') } members = Member.objects.all() for obj in members: Chat(sender='Opencircles', recipient='SELF', body=message, owner=obj, time_chat_sent=datetime.datetime.now(), has_been_responded_to=True).save() try: instance.data_push("multiple", device_tokens, fcm_data) return True except: return False else: member_phone_numbers = Member.objects.all().values_list( 'phone_number', flat=True) phone_numbers = ','.join(member_phone_numbers) print(phone_numbers) response, unsent = sms_utils.Sms().sendmultiplesms( phone_numbers, message) return response
def delete_inactive_circles(self): current_time = datetime.datetime.now().date() initiated_time = current_time - relativedelta(days=90) circles = CircleModel.objects.filter( ~Q(time_initiated__range=[initiated_time, current_time]) & Q(is_active=False)) # for every circle to be deleted get the circle members circle_members = CircleMember.objects.filter(circle__in=circles) # for every circle member get their shares member_shares = Shares.objects.filter(circle_member__in=circle_members) # for every shares get the transaction association circle_transactions = IntraCircleShareTransaction.objects.filter( shares__in=member_shares) # loop through the transaction list for circle_transaction in circle_transactions: member = circle_transaction.shares.circle_member.member print("{} {} {}".format(member.user.first_name, member.user.last_name, member.national_id)) wallet = member.wallet amount = circle_transaction.num_of_shares wallet_balance = wallet_utils.Wallet().calculate_wallet_balance( wallet) + amount trxt_desc = "Circle {} has been deactivated due to inactivity. " \ "Your savings of {} {} have been unlocked. " \ "New wallet balance is {} {}".format(circle_transaction.shares.circle_member.circle.circle_name, member.currency, amount, member.currency, wallet_balance) time_processed = datetime.datetime.now() print(trxt_desc) circle_transaction.transaction_type = "WITHDRAW" circle_transaction.transaction_desc = trxt_desc trxt_code = "RT" + circle_transaction.transaction_code circle_transaction.save() transaction = Transactions.objects.create( wallet=circle_transaction.shares.circle_member.member.wallet, transaction_type='CREDIT', transaction_time=time_processed, transaction_desc=trxt_desc, transaction_amount=amount, transaction_code=trxt_code, source="shares") instance = fcm_utils.Fcm() registration_id = circle_transaction.shares.circle_member.member.device_token serializer = WalletTransactionsSerializer(transaction) fcm_data = { "request_type": "WALLET_TO_MPESA_TRANSACTION", "transaction": serializer.data } print(fcm_data) instance.data_push("single", registration_id, fcm_data) for circle in circles: circle.delete()
def reply_to_chat(chat_id, body): body = body.strip() if len(body) == 0: return False in_reply_to_chat = Chat.objects.get(id=chat_id) member = in_reply_to_chat.owner try: Chat(sender='Opencircles', recipient='SELF', body=body, owner=member, time_chat_sent=datetime.datetime.now(), has_been_responded_to=True).save() in_reply_to_chat.has_been_responded_to = True in_reply_to_chat.save() instance = fcm_utils.Fcm() registration_id = member.device_token fcm_data = { 'request_type': 'REPLY_TO_CHAT', 'sender': 'Opencircles', 'body': body, 'time_sent': datetime.datetime.now().strftime('%Y-%m-%d %H-%m-%s') } instance.data_push("single", registration_id, fcm_data) return True except Exception as exp: print(exp) return False
def send_single_chat(message, member, message_channel): try: if message_channel == 1: Chat(sender='Opencircles', recipient='SELF', body=message, owner=member, time_chat_sent=datetime.datetime.now(), has_been_responded_to=True).save() instance = fcm_utils.Fcm() registration_id = member.device_token fcm_data = { 'request_type': 'REPLY_TO_CHAT', 'sender': 'Opencircles', 'body': message, 'time_sent': datetime.datetime.now().strftime('%Y-%m-%d %H-%m-%s') } instance.data_push("single", registration_id, fcm_data) return True else: print(member.phone_number) print(message) response = sms_utils.Sms().sendsms(member.phone_number, message) return response except Exception as exp: print(exp) return False
def commit_mpesa_c2b_transaction(mpesa_transaction): trx_code = mpesa_transaction['transaction_code'] amount = mpesa_transaction['amount'] trx_time = mpesa_transaction['time'] response_json = json.loads(mpesa_transaction['response']) bill_ref_number = response_json['BillRefNumber'] msisdn = response_json['MSISDN'] c2b_first_name = response_json['FirstName'] c2b_middle_name = response_json['MiddleName'] sms = Sms() member_phone_number = sms.format_phone_number(bill_ref_number) mpesa_trx_obj = AdminMpesaTransaction_logs.objects.get( TransactioID=trx_code.strip()) if Member.objects.filter(phone_number=member_phone_number).exists( ) and mpesa_trx_obj.is_committed is False: member = Member.objects.get(phone_number=member_phone_number) wallet = Wallet.objects.get(member=member) try: wallet_utils = WalletUtils() new_balance = wallet_utils.calculate_wallet_balance() + amount trx_obj = Transactions() trx_obj.transaction_type = 'CREDIT' trx_obj.transaction_time = trx_time trx_obj.transaction_desc = """ {} confirmed. You have received KES {} from {} {} {} via M-PESA at {}. New wallet balance is KES {} """.format(trx_code, amount, msisdn, c2b_first_name, c2b_middle_name, trx_time.strftime('%Y-%m-%d %H-%M-%s'), new_balance).strip() trx_obj.transaction_amount = amount trx_obj.transacted_by = '{} {} {}'.format( msisdn, c2b_first_name, c2b_middle_name) trx_obj.recipient = 'SELF' trx_obj.transaction_code = trx_code trx_obj.wallet = wallet trx_obj.source = 'MPESA C2B' trx_obj.save() mpesa_trx_obj.is_committed = True mpesa_trx_obj.save() serializer = WalletTransactionsSerializer(trx_obj) instance = fcm_utils.Fcm() registration_id = member.device_token fcm_data = { "request_type": "MPESA_TO_WALLET_TRANSACTION", "transaction": serializer.data } instance.data_push("single", registration_id, fcm_data) return True except Exception as e: return False else: return False
def remove_allowed_guarantee_request(request): serializer = AllowedGuaranteeSerializer(data=request.data) if serializer.is_valid(): member = request.user.member instance = sms_utils.Sms() circle = Circle.objects.get( circle_acc_number=serializer.validated_data['circle_acc_number']) phone_number = instance.format_phone_number( serializer.validated_data['guarantee']) user_circle_member = CircleMember.objects.get(circle=circle, member=member) guarantee_circle_member = CircleMember.objects.get( circle=circle, member=Member.objects.get(phone_number=phone_number)) try: AllowedGuarantorRequest.objects.filter( circle_member=user_circle_member, allows_request_from=guarantee_circle_member).delete() message = " {} {} removed from guarantee request list".format( guarantee_circle_member.member.user.first_name, guarantee_circle_member.member.user.last_name) data = {"status": 1, "message": message} except Exception as e: print(str(e)) message = " Unable to remove {} {} from guarantee request list".format( guarantee_circle_member.member.user.first_name, guarantee_circle_member.member.user.last_name) data = {"status": 0, "message": message} return Response(data, status=status.HTTP_200_OK) fcm_instance = fcm_utils.Fcm() registration_id = guarantee_circle_member.member.device_token fcm_data = { "request_type": "UPDATE_ALLOW_GUARANTOR_REQUEST", "circle_acc_number": circle.circle_acc_number, "phone_number": member.phone_number, "allow_guarantor_request": False } fcm_instance.data_push("single", registration_id, fcm_data) print(fcm_data) updating_loan_limit.delay(circle.id, member.id) return Response(data, status=status.HTTP_200_OK) data = {"status": 0, "message": serializer.errors} return Response(data, status=status.HTTP_200_OK)
def send_circle_invitation(self, circle_invitations): sms_instance = sms_utils.Sms() for invite in circle_invitations: circle, member = invite.invited_by.circle, invite.invited_by.member if invite.is_member: invited_member = Member.objects.get( phone_number=invite.phone_number) DeclinedCircles.objects.filter(circle=circle, member=invited_member).delete() registration_id = invited_member.device_token if len(registration_id): fcm_instance = fcm_utils.Fcm() invited_by = "{} {}".format(member.user.first_name, member.user.last_name) invited_serializer = InvitedCircleSerializer( circle, context={"invited_by": invited_by}) fcm_data = { "request_type": "NEW_CIRCLE_INVITATION", "circle": invited_serializer.data } print(fcm_data) fcm_instance.data_push("single", registration_id, fcm_data) else: # Logged out so send sms message = "{} {} has invited you to join {} on Opencircles.".format( member.user.first_name, member.user.last_name, circle.circle_name) sms_instance.sendsms(invite.phone_number, message) else: # Not a member so send sms message = "{} {} has invited you to join {} on Opencircles. " \ "Opencircles is a peer to peer credit and savings platform that makes you " \ "and your close friends, family and colleagues into investment and saving partners. " \ "Download the app from google play store {}".format(member.user.first_name, member.user.last_name, circle.circle_name, settings.APP_STORE_LINK) sms_instance.sendsms(invite.phone_number, message) invite.is_sent = True invite.save()
def post(self, request): serializer = SharesWithdrawalSerializer(data=request.data) if serializer.is_valid(): pin = serializer.validated_data['pin'] circle = Circle.objects.get(circle_acc_number=serializer. validated_data['circle_acc_number']) member = request.user.member created_objects = [] if circle.is_active: circle_member = CircleMember.objects.get(circle=circle, member=member) if circle_member.is_active: if request.user.check_password(pin): amount = serializer.validated_data['amount'] valid, response = shares_utils.Shares( ).validate_withdrawal_amount(amount) if valid: circle_instance = circle_utils.Circle() available_shares = circle_instance.get_available_circle_member_shares( circle, member) print("before available_shares") print(available_shares) if amount <= available_shares: shares_tariff = SharesWithdrawalTariff.objects.get( max_amount__gte=amount, min_amount__lte=amount) fcm_available_shares = circle_instance.get_guarantor_available_shares( circle, member) total_amount = amount + shares_tariff.amount if total_amount <= available_shares: if total_amount <= fcm_available_shares: shares = None try: loan_instance = loan_utils.Loan() general_instance, wallet_instance = general_utils.General( ), wallet_utils.Wallet() circle_member = CircleMember.objects.get( circle=circle, member=member) shares = circle_member.shares.get() time_processed = datetime.datetime.now( ) transaction_code = general_instance.generate_unique_identifier( 'STW') shares_desc = "{} confirmed.You have withdrawn shares worth {} {} from " \ "circle {}.Transaction cost {} {}".format(transaction_code, member.currency, amount, circle.circle_name, member.currency, shares_tariff.amount) shares_transaction = IntraCircleShareTransaction.objects.create( shares=shares, transaction_type="WITHDRAW", num_of_shares=total_amount, transaction_desc=shares_desc, transaction_code= transaction_code) created_objects.append( shares_transaction) revenue = RevenueStreams.objects.create( stream_amount=shares_tariff. amount, stream_type="SHARES WITHDRAW", stream_code=transaction_code, time_of_transaction= time_processed) created_objects.append(revenue) transaction_code = general_instance.generate_unique_identifier( 'WTC') wallet_balance = wallet_instance.calculate_wallet_balance( member.wallet) + amount wallet_desc = "{} confirmed.You have received {} {} from circle {} shares " \ "withdrawal.New wallet balance is {} {}".format(transaction_code, member.currency, amount, circle.circle_name, member.currency, wallet_balance) wallet_transaction = Transactions.objects.create( wallet=member.wallet, transaction_type='CREDIT', transaction_time=time_processed, transaction_desc=wallet_desc, transaction_amount=amount, transaction_code= transaction_code, source="shares") created_objects.append( wallet_transaction) shares_transaction_serializer = SharesTransactionSerializer( shares_transaction) wallet_transaction_serializer = WalletTransactionsSerializer( wallet_transaction) fcm_available_shares = circle_instance.get_guarantor_available_shares( circle, member) print( "others view of available_shares" ) print(fcm_available_shares) available_shares = circle_instance.get_available_circle_member_shares( circle, member) print("new available_shares") print(available_shares) loan_limit = loan_instance.calculate_loan_limit( circle, member) print("loan limit") print(loan_limit) data = { "status": 1, "shares_transaction": shares_transaction_serializer. data, "wallet_transaction": wallet_transaction_serializer. data, "loan_limit": loan_limit, "message": wallet_desc } except Exception as e: print(str(e)) general_instance = general_utils.General( ) general_instance.delete_created_objects( created_objects) data = { "status": 0, "message": "Unable to process the shares withdrawal request" } return Response( data, status=status.HTTP_200_OK) # unblock task # loan_instance.update_loan_limit(circle,member) updating_loan_limit.delay( circle.id, member.id) fcm_instance = fcm_utils.Fcm() fcm_data = { "request_type": "UPDATE_AVAILABLE_SHARES", "circle_acc_number": circle.circle_acc_number, "phone_number": member.phone_number, "available_shares": fcm_available_shares } registration_id = fcm_instance.get_circle_members_token( circle, member) fcm_instance.data_push( "multiple", registration_id, fcm_data) return Response( data, status=status.HTTP_200_OK) data = { "status": 0, "message": "Unable to perform shares withdrawal request due to" " pending loan guarantee requests." "Kindly response to the requests." } return Response(data, status=status.HTTP_200_OK) data = { "status": 0, "message": "Insufficient shares to cover the shares withdrawal charges" } return Response(data, status=status.HTTP_200_OK) data = { "status": 0, "message": "Amount entered exceeds your available shares." } return Response(data, status=status.HTTP_200_OK) data = {"status": 0, "message": response} return Response(data, status=status.HTTP_200_OK) data = {"status": 0, "message": "Invalid pin"} return Response(data, status=status.HTTP_200_OK) data = { "status": 0, "message": "Unable to withdraw savings from circle. Your account is currently " "deactivated due to delayed loan repayment." } return Response(data, status=status.HTTP_200_OK) data = { "status": 0, "message": "Unable to withdraw savings from circle.Circle is inactive." } data = {"status": 0, "message": serializer.errors} return Response(data, status=status.HTTP_200_OK)
def post(self, request, *args, **kwargs): serializer = PurchaseSharesSerializer(data=request.data) if serializer.is_valid(): pin, amount = serializer.validated_data[ 'pin'], serializer.validated_data['amount'] circle_acc_number = serializer.validated_data['circle_acc_number'] circle, member = Circle.objects.get( circle_acc_number=circle_acc_number), request.user.member if circle.is_active: circle_member = CircleMember.objects.get(circle=circle, member=member) if circle_member.is_active: if amount < settings.MIN_SUBSEQUENT_SHARES: data = { "status": 0, "message": "The allowed minimum purchased shares is " "KES {}".format(settings.MIN_SUBSEQUENT_SHARES) } return Response(data, status=status.HTTP_200_OK) valid, response = shares_utils.Shares( ).validate_purchased_shares(amount, circle, member) if valid: wallet_instance = wallet_utils.Wallet() valid, response = wallet_instance.validate_account( request, pin, amount) created_objects = [] shares = None if valid: loan_instance = loan_utils.Loan() try: general_instance = general_utils.General() circle_member = CircleMember.objects.get( circle=circle, member=member) shares = circle_member.shares.get() wallet = member.wallet wallet_balance = wallet_instance.calculate_wallet_balance( wallet) - amount transaction_code = general_instance.generate_unique_identifier( 'WTD') wallet_desc = "{} confirmed.You have purchased shares worth {} {} in circle {}." \ "New wallet balance is {} {}.".format(transaction_code, member.currency, amount, circle.circle_name, member.currency, wallet_balance) wallet_transaction = Transactions.objects.create( wallet=wallet, transaction_type="DEBIT", transaction_time=datetime.datetime.now(), transaction_desc=wallet_desc, transaction_amount=amount, recipient=circle_acc_number, transaction_code=transaction_code, source="wallet") created_objects.append(wallet_transaction) print("wallet transaction") print(wallet_transaction.transaction_amount) transaction_code = general_instance.generate_unique_identifier( 'STD') shares_desc = "{} confirmed.You have purchased shares worth {} {} " \ "in circle {}.".format(transaction_code, member.currency, amount, circle.circle_name) shares_transaction = IntraCircleShareTransaction.objects.create( shares=shares, transaction_type="DEPOSIT", sender=circle_member, recipient=circle_member, num_of_shares=amount, transaction_desc=shares_desc, transaction_code=transaction_code) created_objects.append(shares_transaction) circle_instance = circle_utils.Circle() available_shares = circle_instance.get_available_circle_member_shares( circle, member) print("available shares") print(available_shares) fcm_available_shares = circle_instance.get_guarantor_available_shares( circle, member) wallet_serializer = WalletTransactionsSerializer( wallet_transaction) shares_serializer = SharesTransactionSerializer( shares_transaction) loan_limit = loan_instance.calculate_loan_limit( circle, member) print("loan limit") print(loan_limit) data = { "status": 1, "wallet_transaction": wallet_serializer.data, "shares_transaction": shares_serializer.data, "loan_limit": loan_limit } except Exception as e: print(str(e)) general_utils.General().delete_created_objects( created_objects) data = { "status": 0, "message": "Unable to complete transaction" } return Response(data, status=status.HTTP_200_OK) # unblock task # loan_instance.update_loan_limit(circle,member) updating_loan_limit.delay(circle.id, member.id) fcm_instance = fcm_utils.Fcm() fcm_data = { "request_type": "UPDATE_AVAILABLE_SHARES", "circle_acc_number": circle.circle_acc_number, "phone_number": member.phone_number, "available_shares": fcm_available_shares } registration_id = fcm_instance.get_circle_members_token( circle, member) fcm_instance.data_push("multiple", registration_id, fcm_data) print(fcm_data) return Response(data, status=status.HTTP_200_OK) data = {"status": 0, "message": response} return Response(data, status=status.HTTP_200_OK) data = { "status": 0, "message": "Unable to deposit to circle.Your account is currently deactivated due" " to delayed loan repayment." } return Response(data, status=status.HTTP_200_OK) data = { "status": 0, "message": "Unable to deposit to circle.Circle is inactive." } return Response(data, status=status.HTTP_200_OK) data = {"status": 0, "message": response} return Response(data, status=status.HTTP_200_OK) data = {"status": 0, "message": serializer.errors} return Response(data, status=status.HTTP_200_OK)
def post(self, request): serializer = JoinCircleSerializer(data=request.data) if serializer.is_valid(): acc_number, amount, pin = serializer.validated_data[ 'circle_acc_number'], serializer.validated_data[ 'amount'], serializer.validated_data['pin'] circle = Circle.objects.get(circle_acc_number=acc_number) circle_members_count = CircleMember.objects.filter( circle=circle).count() has_defaulted = CircleMember.objects.filter( member=request.user.member, is_active=False) if has_defaulted.exists(): data = { "status": 0, "message": "Unable to join circle.One of your accounts is currently deactivated due" " to delayed loan repayment. Kindly repay your loan to be able to join this circle." } return Response(data, status=status.HTTP_200_OK) if circle_members_count <= settings.MAX_CIRCLE_MEMBER: if amount < circle.minimum_share: data = {"status":0, "message":"The allowed minimum initial deposit for circle " \ "{} is KES {}".format(circle.circle_name, circle.minimum_share)} return Response(data, status=status.HTTP_200_OK) wallet_instance = wallet_utils.Wallet() valid, response = wallet_instance.validate_account( request, pin, amount) if valid: created_objects = [] try: loan_instance = loan_utils.Loan() general_instance = general_utils.General() member = request.user.member existing_circle_member = CircleMember.objects.filter( member=member).count() wallet_transaction_code = general_instance.generate_unique_identifier( 'WTD') shares_transaction_code = general_instance.generate_unique_identifier( 'STD') wallet_balance = wallet_instance.calculate_wallet_balance( member.wallet) - amount wallet_desc = "{} confirmed. You have purchased shares worth {} {} in circle {}. " \ "New wallet balance is {} {}.".format(wallet_transaction_code, member.currency, amount, circle.circle_name, member.currency, wallet_balance) shares_desc = "{} confirmed. You have purchased shares " \ "worth {} {}".format(shares_transaction_code, member.currency, amount) circle_instance = circle_utils.Circle() circle_member = CircleMember.objects.create( circle=circle, member=member) created_objects.append(circle_member) wallet_transaction = Transactions.objects.create( wallet=request.user.member.wallet, transaction_type="DEBIT", transaction_time=datetime.datetime.now(), transaction_amount=amount, transaction_desc=wallet_desc, recipient=circle.circle_acc_number, transaction_code=wallet_transaction_code, source="wallet") created_objects.append(wallet_transaction) shares = Shares.objects.create( circle_member=circle_member) shares_transaction = IntraCircleShareTransaction.objects.create( shares=shares, transaction_type="DEPOSIT", recipient=circle_member, transaction_time=datetime.datetime.now(), transaction_desc=shares_desc, num_of_shares=amount, transaction_code=shares_transaction_code) wallet_serializer = WalletTransactionsSerializer( wallet_transaction) shares_serializer = SharesTransactionSerializer( shares_transaction) circle_member_serializer = UnloggedCircleMemberSerializer( member, context={"circle": circle}) loan_limit = loan_instance.calculate_loan_limit( circle, member) fcm_instance = fcm_utils.Fcm() old_circle_status = circle.is_active is_active = old_circle_status if not old_circle_status: new_circle_status = circle_instance.check_update_circle_status( circle) if new_circle_status: fcm_data = { "request_type": "UPDATE_CIRCLE_STATUS", "circle_acc_number": circle.circle_acc_number, "is_active": True } is_active = True registration_ids = fcm_instance.get_circle_members_token( circle, None) fcm_instance.data_push("mutiple", registration_ids, fcm_data) print(fcm_data) # unblock task updating_loan_limit.delay(circle.id, member.id) fcm_data = { "request_type": "NEW_CIRCLE_MEMBERSHIP", "circle_acc_number": circle.circle_acc_number, "circle_member": circle_member_serializer.data } registration_ids = fcm_instance.get_circle_members_token( circle, member) fcm_instance.data_push("mutiple", registration_ids, fcm_data) print(fcm_data) ref = False if existing_circle_member == 0: try: is_invited = CircleInvitation.objects.get( phone_number=member.phone_number, invited_by__circle=circle) referral_fee = settings.REFERRAL_FEE today = datetime.date.today() if is_invited.time_invited.date( ) == today and today.weekday() == 4: referral_fee = settings.FRIDAY_REFERRAL_FEE ref = True referral_programme_promotion.delay( is_invited.id, referral_fee) except CircleInvitation.DoesNotExist: print("object does not exist") except CircleInvitation.MultipleObjectsReturned: ReferralFee.objects.create( member=member, circle=circle, is_disbursed=False, extra_info= "user has been invited by more than one circle member" ) if not ref: CircleInvitation.objects.filter( phone_number=member.phone_number, invited_by__circle=circle).delete() data = { "status": 1, "wallet_transaction": wallet_serializer.data, "shares_transaction": shares_serializer.data, "loan_limit": loan_limit, "is_active": is_active } except Exception as e: print(str(e)) instance = general_utils.General() instance.delete_created_objects(created_objects) data = { "status": 0, "message": "Unable to add member to circle" } return Response(data, status=status.HTTP_200_OK) fcm_available_shares = circle_instance.get_guarantor_available_shares( circle, member) fcm_instance = fcm_utils.Fcm() fcm_data = { "request_type": "UPDATE_AVAILABLE_SHARES", "circle_acc_number": circle.circle_acc_number, "phone_number": member.phone_number, "available_shares": fcm_available_shares } registration_ids = fcm_instance.get_circle_members_token( circle, member) fcm_instance.data_push("multiple", registration_ids, fcm_data) return Response(data, status=status.HTTP_200_OK) data = {"status": 0, "message": response} return Response(data, status=status.HTTP_200_OK) data = { "status": 0, "message": "Unable to join circle.The circle is already full." } return Response(data, status=status.HTTP_200_OK) data = {"status": 0, "message": serializer.errors} return Response(data, status.HTTP_200_OK)
def post(self, request): serializer = CircleInviteSerializer(data=request.data) if serializer.is_valid(): circle = Circle.objects.get(circle_acc_number=serializer. validated_data['circle_acc_number']) sms_instance = sms_utils.Sms() phone = sms_instance.format_phone_number( serializer.validated_data['phone_number']) circle_member = CircleMember.objects.get( member=request.user.member, circle=circle) try: CircleMember.objects.get( circle=circle, member=Member.objects.filter(phone_number=phone)) data = { "status": 0, "message": "The user is already a member of the circle." } except CircleMember.DoesNotExist: invites = CircleInvitation.objects.filter( invited_by__in=CircleMember.objects.filter(circle=circle), phone_number=phone) if invites.exists(): invite = invites.latest('id') if invite.status == "Pending": data = { "status": 0, "message": "Unable to send invitation." "Member has already been invited to join this circle." } else: data = { "status": 0, "message": "Unable to send invitation." "Member already declined previous circle invitation" } else: created_objects = [] try: member_instance = member_utils.OpenCircleMember() circle_invite = CircleInvitation.objects.create( phone_number=phone, invited_by=circle_member, is_member=member_instance.get_is_member(phone)) print(circle_invite) created_objects.append(circle_invite) try: invited_member = Member.objects.get( phone_number=phone) DeclinedCircles.objects.filter( circle=circle, member=invited_member).delete() registration_id = invited_member.device_token if len(registration_id): fcm_instance = fcm_utils.Fcm() invited_by = "{} {}".format( request.user.first_name, request.user.last_name) invited_serializer = InvitedCircleSerializer( circle, context={"invited_by": invited_by}) fcm_data = { "request_type": "NEW_CIRCLE_INVITATION", "circle": invited_serializer.data } fcm_instance.data_push("single", registration_id, fcm_data) else: message = "{} {} has invited you to join circle {} on " \ "Opencircles.".format(request.user.first_name, request.user.last_name, circle.circle_name) sms_instance.sendsms(phone, message) except Member.DoesNotExist: #send sms message = "{} {} has invited you to join circle {} on Opencircles." \ "Opencircles is a peer to peer credit and savings platform that makes you " \ "and your close friends, family and colleagues into investment and " \ "saving partners.Get it on {} ".format(request.user.first_name, request.user.last_name, circle.circle_name, settings.APP_STORE_LINK) sms_instance.sendsms(phone, message) ms = "Invitation to {} has been sent.".format(phone) data = {"status": 1, "message": ms} except Exception as e: print(str(e)) general_utils.General().delete_created_objects( created_objects) data = { "status": 0, "message": "Unable to send circle invitation" } return Response(data, status=status.HTTP_200_OK) return Response(data, status=status.HTTP_200_OK) data = {"status": 0, "message": serializer.erors} return Response(data, status=status.HTTP_200_OK)
def commit_mpesa_b2b_transaction(mpesa_transaction): trx_code = mpesa_transaction['transaction_code'] amount = mpesa_transaction['amount'] transaction_time = mpesa_transaction['time'] response_json = json.loads(mpesa_transaction['response']) result = response_json['Result'] originator_conversation_id = result['OriginatorConversationID'] result_code = int(result['ResultCode']) ResultParameters = result["ResultParameters"]["ResultParameter"] paybill_dict = { n['Key']: n['Value'] for n in ResultParameters for key, value in n.iteritems() if value == "ReceiverPartyPublicName" } ReferenceData = result['ReferenceData']['ReferenceItem'] acc_no_dict = { n['Key']: n['Value'] for n in ReferenceData for key, value in n.iteritems() if value == "BillReferenceNumber" } paybill = paybill_dict["ReceiverPartyPublicName"].split(" ")[0] acc_no = acc_no_dict['BillReferenceNumber'] mpesa_trx_obj = AdminMpesaTransaction_logs.objects.get( TransactioID=trx_code) try: pending_trx = PendingMpesaTransactions.objects.get( originator_conversation_id=originator_conversation_id) print("Normal") print(pending_trx.originator_conversation_id) except PendingMpesaTransactions.DoesNotExist: pending_trx_ids = PendingMpesaTransactions.objects.filter( is_valid=True, trx_time__date=transaction_time.date(), type="B2B", amount=amount).values_list('originator_conversation_id', flat=True) print(pending_trx_ids) print(paybill_dict["ReceiverPartyPublicName"]) print(acc_no) b2b_trx = B2BTransaction_log.objects.filter( OriginatorConversationID__in=pending_trx_ids, Recipient_PayBillNumber=paybill, AccountNumber=acc_no) print(b2b_trx) if b2b_trx.exists(): b2b_trx_id = b2b_trx[0].OriginatorConversationID pending_trx = PendingMpesaTransactions.objects.get( originator_conversation_id=b2b_trx_id) else: return False print("Not normal") print(pending_trx.originator_conversation_id) b2b_trx = B2BTransaction_log.objects.get( OriginatorConversationID=pending_trx.originator_conversation_id) member = pending_trx.member if paybill == "525900" and acc_no == "sammienjihia.api": is_buyairtime = False if pending_trx.purpose in ["buy airtime", "N/A"]: is_buyairtime = True trx = pending_trx wallet = member.wallet wallet_balance = WalletUtils().calculate_wallet_balance( wallet) - amount trx_committed = False if is_buyairtime: airtime_log = AirtimePurchaseLog.objects.get( originator_conversation_id=trx.originator_conversation_id) if not airtime_log.is_purchased: sms_instance = Sms() recipient = airtime_log.recipient response = sms_instance.buyairtime(recipient, amount) if response: trx_desc = "{} confirmed. You bought airtime worth {} {} for {}. " \ "New wallet balance is {} {}".format(trx_code, member.currency, amount, recipient, member.currency, wallet_balance) trx_committed = True airtime_log.is_purchased = True airtime_log.save() else: return False else: charges = trx.charges if charges == 0: charges = 1 wallet_balance = wallet_balance - charges trx_desc = "{} confirmed. {} {} has been sent to {} for account {} " \ "from your wallet at {}.Transaction cost {} {}." \ " New wallet balance is {} {}.".format(trx_code, member.currency, amount, paybill_dict["ReceiverPartyPublicName"], acc_no, datetime.datetime.now(), member.currency, charges, member.currency, wallet_balance) amount = amount + charges RevenueStreams.objects.create( stream_amount=charges, stream_type="SMS CHARGES", stream_code=trx_code, time_of_transaction=datetime.datetime.now()) trx_committed = True if trx_committed: wallet_trx = Transactions.objects.create( wallet=wallet, transaction_type="DEBIT", transaction_desc=trx_desc, recipient="{} for {}".format( b2b_trx.Recipient_PayBillNumber, b2b_trx.AccountNumber), transacted_by=wallet.acc_no, transaction_amount=amount, transaction_code=trx_code, source="MPESA B2B") fcm_instance = fcm_utils.Fcm() registration_id = member.device_token trx_serializer = WalletTransactionsSerializer(wallet_trx) fcm_data = { "request_type": "WALLET_TO_PAYBILL_TRANSACTION", "transaction": trx_serializer.data } print(fcm_data) fcm_instance.data_push('single', registration_id, fcm_data) if is_buyairtime: airtime_log.originator_conversation_id = originator_conversation_id airtime_log.is_committed = True airtime_log.save() else: charges = pending_trx.charges if charges == 0: charges = 1 amount += charges wallet = member.wallet wallet_balance = WalletUtils().calculate_wallet_balance( wallet) - amount amount_sent = amount - charges trx_desc = "{} confirmed. {} {} has been sent to {} for account {} " \ "from your wallet at {}.Transaction cost {} {}." \ " New wallet balance is {} {}.".format(trx_code, member.currency, amount_sent, paybill_dict["ReceiverPartyPublicName"], acc_no, datetime.datetime.now(), member.currency, charges, member.currency, wallet_balance) RevenueStreams.objects.create( stream_amount=1, stream_type="SMS CHARGES", stream_code=trx_code, time_of_transaction=datetime.datetime.now()) wallet_trx = Transactions.objects.create( wallet=wallet, transaction_type="DEBIT", transaction_desc=trx_desc, recipient="{} for {}".format(b2b_trx.Recipient_PayBillNumber, b2b_trx.AccountNumber), transacted_by=wallet.acc_no, transaction_amount=amount, transaction_code=trx_code, source="MPESA B2B") fcm_instance = fcm_utils.Fcm() registration_id = member.device_token trx_serializer = WalletTransactionsSerializer(wallet_trx) fcm_data = { "request_type": "WALLET_TO_PAYBILL_TRANSACTION", "transaction": trx_serializer.data } fcm_instance.data_push('single', registration_id, fcm_data) pending_trx.originator_conversation_id = originator_conversation_id pending_trx.is_valid = False pending_trx.save() b2b_trx.OriginatorConversationID = originator_conversation_id b2b_trx.save() mpesa_trx_obj.is_committed = True mpesa_trx_obj.save()
def commit_mpesa_b2c_transaction(mpesa_transaction): trx_code = mpesa_transaction['transaction_code'] amount = mpesa_transaction['amount'] trx_time = mpesa_transaction['time'] response_json = json.loads(mpesa_transaction['response']) originator_conversation_id = response_json['Result'][ 'OriginatorConversationID'] result_code = int(response_json['Result']['ResultCode']) b2c_log = B2CTransaction_log.objects.get( OriginatorConversationID=originator_conversation_id) member_phone_number = b2c_log.Recipient_PhoneNumber mpesa_trx_obj = AdminMpesaTransaction_logs.objects.get( TransactioID=trx_code.strip()) if Member.objects.filter(phone_number=member_phone_number).exists() \ and mpesa_trx_obj.is_committed is False and result_code == 0: member = Member.objects.get(phone_number=member_phone_number) wallet = Wallet.objects.get(member=member) # Get M-PESA recipient result_params = response_json['Result']['ResultParameters'][ 'ResultParameter'] recipient = '' for result_param_obj in result_params: if result_param_obj['Key'] == 'ReceiverPartyPublicName': recipient = result_param_obj['Value'] # Get transaction charges charges = 0 if amount >= 100 and amount <= 1000: charges = 16 elif amount >= 1001 and amount <= 70000: charges = 30 try: wallet_utils = WalletUtils() new_balance = wallet_utils.calculate_wallet_balance() - ( amount + charges) # Save transactions Objects trx_obj = Transactions() trx_obj.transaction_type = 'DEBIT' trx_obj.transaction_time = trx_time trx_obj.transaction_desc = """ {} confirmed. You have sent KES {} to {} via M-PESA at {}. Transaction cost is KES {}. New wallet balance is KES {} """.format(trx_code, amount, recipient, trx_time.strftime('%Y-%m-%d %H-%M-%s'), charges, new_balance).strip() trx_obj.transaction_amount = amount + charges trx_obj.transacted_by = 'SELF' trx_obj.recipient = recipient trx_obj.transaction_code = trx_code trx_obj.wallet = wallet trx_obj.source = 'MPESA B2C' trx_obj.save() # Update mpesa log mpesa_trx_obj.is_committed = True mpesa_trx_obj.save() # Send FCM message serializer = WalletTransactionsSerializer(trx_obj) instance = fcm_utils.Fcm() registration_id = member.device_token fcm_data = { "request_type": "MPESA_TO_WALLET_TRANSACTION", "transaction": serializer.data } instance.data_push("single", registration_id, fcm_data) return True except Exception as e: return False else: return False
def post(self, request): serializer = AllowedGuaranteeSerializer(data=request.data) if serializer.is_valid(): instance = sms_utils.Sms() circle, guarantee_phone, member = Circle.objects.get( circle_acc_number=serializer. validated_data['circle_acc_number'] ), instance.format_phone_number( serializer.validated_data['guarantee']), request.user.member if guarantee_phone == member.phone_number: data = { "status": 0, "message": "Unable to add yourself to guarantee request list" } return Response(data, status=status.HTTP_200_OK) user_circle_member = CircleMember.objects.get(circle=circle, member=member) guarantee_member = Member.objects.get(phone_number=guarantee_phone) allowed_guarantee = CircleMember.objects.get( circle=circle, member=guarantee_member) try: AllowedGuarantorRequest.objects.create( circle_member=user_circle_member, allows_request_from=allowed_guarantee) guarantee_serializer = CircleMemberSerializer(guarantee_member, context={ "request": request, "circle": circle }) ms = "{} {} added to guarantee request list".format( guarantee_member.user.first_name, guarantee_member.user.last_name) data = { "status": 1, 'guarantee': guarantee_serializer.data, 'message': ms } except Exception as e: print(str(e)) ms = "Unable to add {} {} to guarantee request list".format( guarantee_member.user.first_name, guarantee_member.user.last_name) data = {"status": 0, "message": ms} return Response(data, status=status.HTTP_200_OK) fcm_instance = fcm_utils.Fcm() registration_id = guarantee_member.device_token fcm_data = { "request_type": "UPDATE_ALLOW_GUARANTOR_REQUEST", "circle_acc_number": circle.circle_acc_number, "phone_number": member.phone_number, "allow_guarantor_request": True } fcm_instance.data_push("single", registration_id, fcm_data) print(fcm_data) updating_loan_limit.delay(circle.id, member.id) return Response(data, status=status.HTTP_201_CREATED) data = {"status": 0, "errors": serializer.errors} return Response(data, status=status.HTTP_200_OK)
def commit_c2b_mpesa_transaction(request): if request.method != 'POST': # context = { # 'circles': circles_utils.CircleUtils.get_all_circles(), # 'members': members_utils.MemberUtils.get_all_members() # } return render(request, 'app_admin/c2b_transaction.html') else: print(request.POST) sms_instance = sms_utils.Sms() admins = ['+254712388212', '+254795891656', '+254714642293'] admin_phone_number = sms_instance.format_phone_number( request.POST.get('admin_phone_number')) if admin_phone_number not in admins: return_data = {'status': 0, 'message': 'Unauthorized access.'} print(return_data) return HttpResponse(json.dumps(return_data)) pin = request.POST.get('pin') user = authenticate(username=admin_phone_number, password=pin) if user is not None: code = request.POST.get('transaction_code') amount = int(request.POST.get('amount')) recipient_phone_number = sms_instance.format_phone_number( request.POST.get('recipient_phone_number')) try: member = Member.objects.get( phone_number=recipient_phone_number) except Member.DoesNotExist: return_data = { 'status': 0, 'message': 'Member with phone number does not exist' } return HttpResponse(json.dumps(return_data)) transacted_by = request.POST.get('sender_phone_number') if len(transacted_by): transacted_by = sms_instance.format_phone_number(transacted_by) else: transacted_by = recipient_phone_number created_objects = [] try: response_data = "Mpesa transaction was manually committed by {} {} {}".format( user.first_name, user.last_name, admin_phone_number) admin_mpesa_transaction = AdminMpesaTransaction_logs.objects.create( TransactioID=code, TransactionType='C2B', Response=response_data, is_committed=False) created_objects.append(admin_mpesa_transaction) wallet_instance = wallet_utils.Wallet() wallet = member.wallet wallet_balance = wallet_instance.calculate_wallet_balance( wallet) + amount transaction_desc = "{} confirmed.You have received {} {} from {} via mpesa. " \ "New wallet balance is {} {}".format(code, member.currency, amount, transacted_by, member.currency, wallet_balance) mpesa_transactions = Transactions.objects.create( wallet=wallet, transaction_type="CREDIT", transaction_desc=transaction_desc, transacted_by=transacted_by, transaction_amount=amount, transaction_code=code, source="MPESA C2B") created_objects.append(mpesa_transactions) admin_mpesa_transaction.is_committed = True admin_mpesa_transaction.is_manually_committed = True admin_mpesa_transaction.save() message = "{} {} {} has successfully committed {} mpesa transaction {} of {} {}.".format( user.first_name, user.last_name, admin_phone_number, recipient_phone_number, code, member.currency, amount) try: sms_instance.sendsms("0755564433", message) except Exception as e: print(str(e)) return_data = { 'status': 0, 'message': 'Transaction unsuccessful.Unable to notify admins.' } return HttpResponse(json.dumps(return_data)) except Exception as e: print(str(e)) general_utils.General().delete_created_objects(created_objects) return_data = { 'status': 0, 'message': 'Unable to commit transaction' } return HttpResponse(json.dumps(return_data)) serializer = WalletTransactionsSerializer(mpesa_transactions) instance = fcm_utils.Fcm() registration_id = member.device_token fcm_data = { "request_type": "MPESA_TO_WALLET_TRANSACTION", "transaction": serializer.data } instance.data_push("single", registration_id, fcm_data) return_data = { 'status': 0, 'message': 'Transaction successfully committed.' } return HttpResponse(json.dumps(return_data)) else: return_data = {'status': 0, 'message': 'Invalid admin credentials'} return HttpResponse(json.dumps(return_data))
def deactivate_circle_member(self): loans = LoanApplication.objects.filter( is_approved=True, is_disbursed=True, is_fully_repaid=False).exclude(loan_tariff=None) for loan in loans: member = loan.circle_member.member circle = loan.circle_member.circle loan_tariff = loan.loan_tariff if loan_tariff is None: loan_tariff = LoanTariff.objects.get( max_amount__gte=loan.amount, min_amount__lte=loan.amount, circle=circle) num_of_months = loan_tariff.num_of_months date_of_payment = loan.time_of_application.date() + relativedelta( months=num_of_months) today = datetime.datetime.now().date() if today > date_of_payment: print("defaulted loan") print(loan.loan_code) diff = datetime.datetime.now().date() - date_of_payment delta = diff.days amortize_loan = loan.loan_amortization.filter().latest('id') if delta == 1: CircleMember.objects.filter( circle=circle, member=member).update(is_active=False) title = "Circle {} account deactivation".format( circle.circle_name) message = "Your account has been deactivated due to late repayment of loan {} of" \ " KES {} in circle {}. Kindly repay your loan to continue saving, " \ "borrowing and earning interests from other circle members' loans.".format(loan.loan_code, amortize_loan.total_repayment, circle.circle_name) fcm_instance = fcm_utils.Fcm() registration_id = member.device_token if len(registration_id): curr_time = datetime.datetime.now().strftime( "%Y-%m-%d %H:%M:%S") fcm_data = { "request_type": "SYSTEM_WARNING_MSG", "title": title, "message": message, "time": curr_time } fcm_instance.data_push("single", registration_id, fcm_data) fcm_data = { "request_type": "UPDATE_CIRCLE_MEMBER_STATUS", "phone_number": member.phone_number, "circle_acc_number": circle.circle_acc_number, 'is_active': False } registration_ids = fcm_instance.get_circle_members_token( circle, None) fcm_instance.data_push("multiple", registration_ids, fcm_data) else: sms_instance = sms_utils.Sms() message = "Your {} account has been deactivated due to late repayment of loan {}." \ "Kindly repay your loan to reactivate the account and to continue saving, " \ "borrowing and earning interests from other circle members' loans.".format( circle.circle_name, loan.loan_code) sms_instance.sendsms(member.phone_number, message) else: title = "Circle {} loan repayment".format( circle.circle_name) message = "Kindly repay your loan {} of KES {} in circle {} to continue saving, " \ "borrowing and earning interests from other " \ "circle members' loans.".format(loan.loan_code, amortize_loan.total_repayment, circle.circle_name) fcm_instance = fcm_utils.Fcm() registration_id = member.device_token if len(registration_id): curr_time = datetime.datetime.now().strftime( "%Y-%m-%d %H:%M:%S") fcm_data = { "request_type": "SYSTEM_WARNING_MSG", "title": title, "message": message, "time": curr_time } fcm_instance.data_push("single", registration_id, fcm_data) else: sms_instance = sms_utils.Sms() message = "Kindly repay your loan {} of KES {} in circle {} to continue saving, borrowing and earning " \ "interests from other circle members' loans.".format(loan.loan_code, amortize_loan.total_repayment, circle.circle_name) sms_instance.sendsms(member.phone_number, message)