def send_frequent_invitations(): invite_contacts = Contacts.objects.filter(is_member=False, is_valid=True, invitation_sent=False) contacts_to_sent = invite_contacts.order_by('phone_number').values_list('phone_number', flat=True).distinct() contacts_to_send = contacts_to_sent[:500] numbers = ','.join(contacts_to_send) numbers = numbers.encode("ascii") sms = sms_utils.Sms() message = "Opencircles is a platform where friends, family and colleagues can pull resources to save and invest" \ " in consumer credit. Create a circle and get your whatsapp group to join and save in the circle and" \ " stand a chance to win Kes 5,000 every friday this festive season." \ " Get the app on play store at https://goo.gl/5KWXhx" if invite_contacts.exists(): # response,unsent = sms.sendmultiplesms(numbers, message) # if response: # invite_contacts.exclude(phone_number__in=unsent).update(invitation_sent=True) pass else: print("No contacts in this table") loans = loan_utils.Loan() #send loan reminders from this function loans.loan_repayment_reminder() #Delete loans that have expired I.E have exceeded the 1 week time span without all the guarantors accepting loans.delete_expired_loan() circle_instance = circle_utils.Circle() circle_instance.deactivate_circle_member() circle_instance.delete_inactive_circles() return "Sent messages successfully"
def validate_purchased_shares(self, amount, circle, member): available_shares = circle_utils.Circle( ).get_total_circle_member_shares(circle, member, None) remaining_shares = settings.MAXIMUM_CIRCLE_SHARES - available_shares if remaining_shares >= settings.MININIMUM_CIRCLE_SHARES: if amount <= remaining_shares: return True, "" return False, "Unable to purchase shares.The amount entered will exceed the maximum shares threshold of {} {}".format( member.currency, settings.MAXIMUM_CIRCLE_SHARES)
def get_circle_member_shares_fraction(self, shares, time_constraint, excluded_member): if shares is not None: circle_instance = circle_utils.Circle() circle, member = shares.circle_member.circle, shares.circle_member.member circle_member_shares = circle_instance.get_total_circle_member_shares( circle, member, time_constraint) total_circle_shares = circle_instance.get_total_circle_shares( circle, time_constraint, excluded_member) if total_circle_shares > 0: circle_shares_fraction = general_utils.General().get_decimal( circle_member_shares, total_circle_shares) else: circle_shares_fraction = 0 return circle_shares_fraction
def insert_circle_member_shares(self): circle_members = CircleMember.objects.all() circle_instance = circle_utils.Circle() for c in circle_members: shares = CircleMember.objects.get(circle=c.circle, member=c.member).shares.get() circle_member_shares = circle_instance.get_total_circle_member_shares( c.circle, c.member, None) total_circle_shares = circle_instance.get_total_circle_shares( c.circle, None) circle_shares_fraction = 0 if total_circle_shares > 0: circle_shares_fraction = float( format((circle_member_shares / total_circle_shares), '.3f')) shares.fraction = circle_shares_fraction shares.save()
def post(self, request): try: instance = circle_utils.Circle() circles_ids = list( CircleMember.objects.filter( member=request.user.member).values_list('circle', flat=True)) declined_ids = list( DeclinedCircles.objects.filter( member=request.user.member).values_list('circle', flat=True)) total_ids = circles_ids + declined_ids unjoined_circles = Circle.objects.filter(~Q(id__in=total_ids)) invited_circles = instance.get_invited_circles(request) invited_circles_ids = [circle.id for circle in invited_circles] total_suggested_circle_count = len(circles_ids) + len( invited_circles_ids) suggested_ids = [] if total_suggested_circle_count < settings.MAXIMUM_SUGGESTED_CIRCLE: diff = settings.MAXIMUM_SUGGESTED_CIRCLE - total_suggested_circle_count contacts = Contacts.objects.filter(member=request.user.member, is_member=True).values_list( 'phone_number', flat=True) suggested_circles = instance.get_suggested_circles( unjoined_circles, contacts, request, diff) if len(suggested_circles): suggested_ids = [ key.id for key, value in suggested_circles ] suggested_circles_ids = invited_circles_ids + suggested_ids + circles_ids circles = Circle.objects.filter(id__in=suggested_circles_ids) circle_serializer = CircleSerializer(circles, many=True, context={"request": request}) except Exception as e: print(str(e)) data = {"status": 0, "message": "Unable to fetch circle list"} return Response(data, status=status.HTTP_200_OK) data = {"status": 1, "circles": circle_serializer.data} return Response(data, status=status.HTTP_200_OK)
def get_circle_member_shares(self, shares): if shares is not None: circle_instance = circle_utils.Circle() circle, member = shares.circle_member.circle, shares.circle_member.member total_circle_shares = circle_instance.get_total_circle_shares( circle, None, None) circle_members = CircleMember.objects.filter(circle=circle) for circle_member in circle_members: shares = circle_member.shares.get() member = circle_member.member circle_member_shares = circle_instance.get_total_circle_member_shares( circle, member, None) if total_circle_shares > 0: circle_shares_fraction = float( format((circle_member_shares / total_circle_shares), '.3f')) else: circle_shares_fraction = 0 shares.fraction = circle_shares_fraction shares.circle_name = circle.circle_name shares.save()
def send_circle_invites(id_list): circle_invitations = CircleInvitation.objects.filter(id__in=id_list) instance = circle_utils.Circle() instance.send_circle_invitation(circle_invitations) message = "Saved contacts successfully" return message
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 = 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): 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): if "contact_list" in request.data: mutable = request.data._mutable request.data._mutable = True request.data["contact_list"] = json.loads( request.data["contact_list"]) request.data["loan_tariff"] = json.loads( request.data["loan_tariff"]) circle_loan_tariff = request.data["loan_tariff"] contacts = request.data[ "contact_list"] if "contact_list" in request.data else [] request.data._mutable = mutable serializer = CircleCreationSerializer(data=request.data) if serializer.is_valid(): wallet_instance = wallet_utils.Wallet() minimum_share = serializer.validated_data['minimum_share'] if minimum_share < settings.MININIMUM_CIRCLE_SHARES: data = { "status": 0, "message": "The allowed minimum circle deposit is {} {}".format( request.user.member.currency, settings.MININIMUM_CIRCLE_SHARES) } return Response(data, status=status.HTTP_200_OK) valid, response = wallet_instance.validate_account( request, serializer.validated_data['pin'], minimum_share) has_defaulted = CircleMember.objects.filter( member=request.user.member, is_active=False) if has_defaulted.exists(): data = { "status": 0, "message": "Unable to create circle.One of your accounts is currently deactivated due" " to delayed loan repayment. Kindly repay your loan to be able to create a circle." } return Response(data, status=status.HTTP_200_OK) if valid: created_objects = [] try: try: last_circle_created = Circle.objects.latest('id') last_acc_number = int( last_circle_created.circle_acc_number) acc_number = last_acc_number + 1 except ObjectDoesNotExist: acc_number = 100000 general_instance = general_utils.General() member = request.user.member circle = serializer.save(initiated_by=member, circle_acc_number=acc_number) created_objects.append(circle) circle_member = CircleMember.objects.create(member=member, circle=circle) wallet_transaction_code = general_instance.generate_unique_identifier( 'WTD') wallet_balance = wallet_instance.calculate_wallet_balance( member.wallet) - minimum_share wallet_desc = "{} confirmed.You have purchased shares worth {} {} in circle {}." \ "New wallet balance is {} {}.".format( wallet_transaction_code, member.currency, minimum_share, circle.circle_name, member.currency, wallet_balance) shares_transaction_code = general_instance.generate_unique_identifier( 'STD') shares_desc = "{} confirmed.You have purchased shares worth {} {}.".format( shares_transaction_code, member.currency, minimum_share) wallet_transaction = Transactions.objects.create( wallet=member.wallet, transaction_type="DEBIT", transaction_time=datetime.datetime.now(), transaction_amount=minimum_share, 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", num_of_shares=minimum_share, transaction_desc=shares_desc, recipient=circle_member, transaction_code=shares_transaction_code) if len(contacts): member_instance = member_utils.OpenCircleMember() circle_invites = [ CircleInvitation( invited_by=circle_member, phone_number=phone, is_member=member_instance.get_is_member(phone)) for phone in contacts ] invites = CircleInvitation.objects.bulk_create( circle_invites) id_list = [invite.id for invite in invites] send_circle_invites.delay(id_list) wallet_serializer = WalletTransactionsSerializer( wallet_transaction) shares_serializer = SharesTransactionSerializer( shares_transaction) circle_serializer = CircleSerializer( circle, context={'request': request}) circle_instance = circle_utils.Circle() circle_instance.save_loan_tariff(circle, circle_loan_tariff) circle = circle_serializer.data wallet_transaction = wallet_serializer.data shares_transaction = shares_serializer.data data = { "status": 1, "circle": circle, "wallet_transaction": wallet_transaction, "shares_transaction": shares_transaction, "message": "Circle created successfully.Circle will be activated when atleast four members join." } return Response(data, status=status.HTTP_201_CREATED) except Exception as e: instance = general_utils.General() instance.delete_created_objects(created_objects) error = "Unable to create circle" data = {"status": 0, "message": error} 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)