Example #1
0
 def test_updateExpense_exception(self, mockMakeRequest):
     mockMakeRequest.side_effect = Exception(
         "Invalid response %s. Please check your consumer key and secret." %
         404)
     expense = Expense()
     expense.id = 1010934284
     expense.setCost('10')
     expense.setDescription("Testing")
     user1 = ExpenseUser()
     user1.setId(79774)
     user1.setPaidShare('10.00')
     user1.setOwedShare('2.0')
     user2 = ExpenseUser()
     user2.setId(281236)
     user2.setPaidShare('0.00')
     user2.setOwedShare('8.00')
     users = []
     users.append(user1)
     users.append(user2)
     expense.setUsers(users)
     with self.assertRaises(Exception):
         expenseRes, errors = self.sObj.updateExpense(expense)
     mockMakeRequest.assert_called_with(
         "https://secure.splitwise.com/api/v3.0/update_expense/1010934284",
         "POST", {
             'cost': '10',
             'description': 'Testing',
             'users__0__user_id': 79774,
             'users__0__paid_share': '10.00',
             'users__0__owed_share': '2.0',
             'users__1__user_id': 281236,
             'users__1__paid_share': '0.00',
             'users__1__owed_share': '8.00'
         },
         files=None)
Example #2
0
def add_bill(cost=100.0):
    users = []
    group = sObj.getGroup(10204809)
    people = group.getMembers()

    expense = Expense()
    expense.setCost(str(cost))
    expense.setDescription("Capital One Transfer")
    # per_person = str(round(cost / len(people), 2))
    per_person = cost

    paying_user =sObj.getCurrentUser()
    paying_id = paying_user.getId()
    paying_expense_user = ExpenseUser()
    paying_expense_user.setId(paying_id)
    paying_expense_user.setPaidShare(str(cost))
    paying_expense_user.setOwedShare(per_person)
    users.append(paying_expense_user)


    for friend in people:
        id = friend.getId()
        if id == paying_id:
            continue
        user = ExpenseUser()
        user.setId(id)
        user.setPaidShare('0.0')
        user.setOwedShare(per_person)
        users.append(user)
        expense.setUsers(users)
        expense = sObj.createExpense(expense)
        print(expense.getId())
Example #3
0
def share_expense_with_group_members(sw: Splitwise, desc, cost, group_id,
                                     date):
    grp = sw.getGroup(group_id)
    current_user = sw.getCurrentUser()
    other_members = [m for m in grp.getMembers() if m.id != current_user.id]
    _debug(current_user)
    _debug(other_members)
    cost_per_user = round(cost / len(grp.members), 2)

    expense = Expense()
    expense.cost = f"{cost}"
    expense.description = f"{desc}"
    expense.group_id = f"{group_id}"
    expense.setDate(date.strftime("%Y/%m/%d"))

    users = []
    for om in other_members:
        user = ExpenseUser()
        user.setId(om.id)
        user.setPaidShare(f"0")
        user.setOwedShare(f"{cost_per_user}")
        users.append(user)
    user = ExpenseUser()
    user.setId(current_user.id)
    user.setPaidShare(f"{cost}")
    user.setOwedShare(f"{cost - len(users) * cost_per_user}")
    users.append(user)
    expense.users = users
    sw.createExpense(expense)
Example #4
0
    def getExpenses(self,offset=None,limit=None,group_id=None,friendship_id=None,dated_after=None,dated_before=None,updated_after=None,updated_before=None):

        options = {}

        #Copy of the locals is created as if I directly work on
        #locals and create variables in the loop a dictionary changed
        #error is thrown. Refer to bug #2 on Github
        localCopy = dict(locals())
        params = localCopy.keys()
        for param in params:
            if param != 'self' and param != 'options' and localCopy.get(param) is not None:
                options[param] = localCopy.get(param)

        url = Splitwise.GET_EXPENSES_URL

        url += self.__prepareOptionsUrl(options)
        content = self.__makeRequest(url)
        content = json.loads(content.decode("utf-8"))
        ##SEYON
        return content
        expenses = []
        if "expenses" in content:
            for e in content["expenses"]:
                expenses.append(Expense(e))

        return expenses
Example #5
0
    def createExpense(self, expense):
        #Get the expense Dict
        expense_data = expense.__dict__

        #Get users and store in a separate var
        expense_users = expense.getUsers()
        #Delete users from original dict as we
        #need to put like users_1_
        del expense_data['users']

        #Add user values to expense_data
        count = -1
        for user in expense_users:
            count += 1
            user_dict = user.__dict__

            for key in user_dict:
                if key == "id":
                    gen_key = "user_id"
                else:
                    gen_key = key
                expense_data["users__" + str(count) + "__" +
                             gen_key] = user_dict[key]

        content = self.__makeRequest(Splitwise.CREATE_EXPENSE_URL, "POST",
                                     expense_data)
        content = json.loads(content.decode("utf-8"))
        expense = None

        if "expenses" in content:
            expense = Expense(content["expenses"][0])

        return expense
Example #6
0
    def updateExpense(self, expense):
        """ Updates an existing expense.

        Args:
            expense(:obj:`splitwise.expense.Expense`): Splitwise Expense Object.
            expense id must be set. Include only the fields that should be updated. null fields are ignored

        Returns:
            tuple: tuple containing:
              expense(:obj:`splitwise.expense.Expense`): Object with Expense detail

              errors(:obj:`splitwise.error.SplitwiseError`): Object representing errors
        """
        expense_id = expense.id
        if expense_id is None:
            raise SplitwiseBadRequestException("Incorrect query parameters sent. Expense Id cannot be null")

        # Get the expense Dict
        expense_data = expense.__dict__

        del expense_data['id']

        # Get users and store in a separate var
        expense_users = expense.getUsers()

        if expense_users:
            # Delete users from original dict as we
            # need to put like users_1_
            del expense_data['users']
            # Add user values to expense_data
            Splitwise.setUserArray(expense_users, expense_data)

        category = expense.getCategory()
        if category:
            expense_data["category_id"] = category.getId()

        receipt = expense.getReceiptPath()
        files = None
        if receipt:
            files = {"receipt":  io.open(receipt, "rb")}

        content = self.__makeRequest(
            Splitwise.UPDATE_EXPENSE_URL+"/"+str(expense_id), "POST", expense_data, files=files)
        content = json.loads(content)
        expense = None
        errors = None

        if files:
            files["receipt"].close()

        if 'expenses' in content:
            if len(content['expenses']) > 0:
                expense = Expense(content["expenses"][0])

        if 'errors' in content:
            if len(content['errors']) != 0:
                errors = SplitwiseError(content['errors'])

        return expense, errors
Example #7
0
    def getExpense(self,id):
        content = self.__makeRequest(Splitwise.GET_EXPENSE_URL+"/"+str(id))
        content = json.loads(content.decode("utf-8"))
        expense = None
        if "expense" in content:
            expense = Expense(content["expense"])

        return expense
Example #8
0
 def test_expense_invalidkeys_fail(self):
     sObj = Splitwise('consumerkey', 'consumersecret', {
         "oauth_token": "sdsd",
         "oauth_token_secret": "sdsdd"
     })
     expense = Expense()
     with self.assertRaises(SplitwiseUnauthorizedException):
         sObj.createExpense(expense)
Example #9
0
          def addSplitwise(tf):
              amount = tf['number_oNYSbrj3CNlF']
              name = False
              if 'textfield_Maf3TeF00J84' in tf:
                 name = tf['textfield_Maf3TeF00J84']
              catagory = tf['list_uDy8LvuB3wTa_choice']
              split = [tf[i].lower() for i in tf.keys() if 'list_SFFmFqOvH1Xv_choice' in i]
               
              users = []
              namesfg = []
              if split:
                  for i in self.sw.getGroups():
                      if i.getName().lower() in split:
                         namefg.extend(i.getMembers())
                  split.extend(namesfg)
                  for i in self.sw.getFriends():
                      print(i.__dict__)
                      first = i.getFirstName()
                      if not first:
                         first = ""
                      last = i.getLastName()
                      if not last:
                         last = ""
                      if first.lower() + ' ' + last.lower() in split:
                         user = ExpenseUser()
                         user.setId(i.getId())
                         user.setPaidShare('0')
                         user.setOwedShare('1')
                         users.append(user)
                     
                  each = '%.2f'%(float(amount)/(len(users)+1))
                  for user in users:
                      user.setOwedShare(each)

                  me = ExpenseUser()
                  me.setId(self.sw.getCurrentUser().getId())
                  me.setOwedShare('%.2f'%(float(100*int(amount)-int(100*float(each)*len(users)))/100))
                  me.setPaidShare(amount)
                  users.append(me)
             
                  expense = Expense()
                  expense.setCost(str(amount))
                  expense.setDescription(name)
                  expense.setUsers(users)
                  print(users)
                  self.sw.createExpense(expense)

              row = self.gs.getRow(catagory)
              monYr = datetime.datetime.now().strftime("%b %Y")
              col = self.gs.getCol(monYr)

              self.gs.addCell(col, row, amount)
Example #10
0
    def createExpense(self, expense):
        """ Creates a new expense.

        Args:
            expense(:obj:`splitwise.expense.Expense`): Splitwise Expense Object.

        Returns:
            tuple: tuple containing:
              expense(:obj:`splitwise.expense.Expense`): Object with Expense detail

              errors(:obj:`splitwise.error.SplitwiseError`): Object representing errors
        """
        # Get the expense Dict
        expense_data = expense.__dict__

        # Get users and store in a separate var
        expense_users = expense.getUsers()

        if expense_users:
            # Delete users from original dict as we
            # need to put like users_1_
            del expense_data['users']
            # Add user values to expense_data
            Splitwise.setUserArray(expense_users, expense_data)

        category = expense.getCategory()
        if category:
            expense_data["category_id"] = category.getId()

        receipt = expense.getReceiptPath()
        files = None
        if receipt:
            files = {"receipt": io.open(receipt, "rb")}

        content = self.__makeRequest(Splitwise.CREATE_EXPENSE_URL,
                                     "POST",
                                     expense_data,
                                     files=files)
        content = json.loads(content)
        expense = None
        errors = None

        if files:
            files["receipt"].close()

        if 'expenses' in content:
            if len(content['expenses']) > 0:
                expense = Expense(content["expenses"][0])

        if 'errors' in content:
            if len(content['errors']) != 0:
                errors = SplitwiseError(content['errors'])

        return expense, errors
Example #11
0
def _create_expense(initiator_id: str, recipient_id: str, amount: float, description: str):
    """
    This will create an expense where the {initiator} owes the {recipient} {amount}.
    """
    if amount <= 0:
        raise CommandException('Negative amounts not allowed')

    tso: User = User.objects.get(friendly_name='tso')
    initiator: User = User.objects.get(slack_id=initiator_id)
    recipient: User = User.objects.get(slack_id=recipient_id)
    users = []

    expense = Expense()
    expense.setGroupId(settings.SPLITWISE_GROUP_ID)
    expense.setDescription(description)
    expense.setCost(amount)

    initiator_user = ExpenseUser()
    initiator_user.setId(initiator.splitwise_id)
    initiator_user.setPaidShare(0)
    initiator_user.setOwedShare(amount)
    users.append(initiator_user)

    recipient_user = ExpenseUser()
    recipient_user.setId(recipient.splitwise_id)
    recipient_user.setPaidShare(amount)
    recipient_user.setOwedShare(0)
    users.append(recipient_user)

    # We do this because we're using my access token.
    if tso.id not in [initiator.id, recipient.id]:
        tso_user = ExpenseUser()
        tso_user.setId(tso.splitwise_id)
        tso_user.setPaidShare(0)
        tso_user.setOwedShare(0)
        users.append(tso_user)

    expense.setUsers(users)
    if not sObj.createExpense(expense):
        raise CommandException('Failed to create SW expense')
Example #12
0
    def pay_bill(self, paying_user_id: int, bill: CoffeeBill) -> str:
        """
        Pay a bill by creating an expense for `paying_user` with respect to logged in splitwise user.
        :param paying_user_id:  Splitwise id of paying user
        :param bill:            CoffeeBill to be payed
        :return:                Splitwise transaction id
        """
        # Convert amount to string
        amount_str = f"{bill.sum:.2f}"

        # User which will pay money
        paying_user = ExpenseUser()
        paying_user.setId(paying_user_id)
        paying_user.setOwedShare(amount_str)

        # User which will receive money
        my_user = ExpenseUser()
        my_user.setId(self.user.getId())
        my_user.setPaidShare(amount_str)

        # Create Expense/Transaction
        expense = Expense()
        expense.setCost(amount_str)
        expense.setDescription(f"CoffeeTracker, Rechnung {bill.id}")
        expense.addUser(paying_user)
        expense.addUser(my_user)

        # Execute transaction
        expense_response, errors = self.s.createExpense(expense)

        if errors is not None:
            raise RuntimeError(
                "An error occured while processing the transaction with Splitwise: "
                f"{errors.errors}")

        return f"{expense_response.getId()}"
Example #13
0
    def getExpenses(self,
                    offset=None,
                    limit=None,
                    group_id=None,
                    friendship_id=None,
                    dated_after=None,
                    dated_before=None,
                    updated_after=None,
                    updated_before=None
                    ):
        """ Gets the list of expenses given parameters.

        Args:
            offset(int, optional): Number of expenses to be skipped
            limit(int, optional): Number of expenses to be returned
            group_id(long, optional): GroupID of the expenses
            friendship_id(long, optional): FriendshipID of the expenses
            dated_after(str, optional): ISO 8601 Date time. Return expenses later that this date
            dated_before(str, optional): ISO 8601 Date time. Return expenses earlier than this date
            updated_after(str, optional): ISO 8601 Date time. Return expenses updated after this date
            updated_before(str, optional): ISO 8601 Date time. Return expenses updated before this date

        Returns:
            :obj:`list` of :obj:`splitwise.expense.Expense`: List of Expense
        """

        options = {}

        # Copy of the locals is created as if I directly work on
        # locals and create variables in the loop a dictionary changed
        # error is thrown. Refer to bug #2 on Github
        localCopy = dict(locals())
        params = localCopy.keys()
        for param in params:
            if param != 'self' and param != 'options' and localCopy.get(param) is not None:
                options[param] = localCopy.get(param)

        url = Splitwise.GET_EXPENSES_URL

        url += self.__prepareOptionsUrl(options)
        content = self.__makeRequest(url)
        content = json.loads(content)
        expenses = []
        if "expenses" in content:
            for e in content["expenses"]:
                expenses.append(Expense(e))

        return expenses
Example #14
0
    def getExpense(self, id):
        """ Gets the detail of the expense given the expense id.

        Args:
            id(long, optional): ID of the expense.

        Returns:
            :obj:`splitwise.expense.Expense`: Object representing an expense
        """
        content = self.__makeRequest(Splitwise.GET_EXPENSE_URL+"/"+str(id))
        content = json.loads(content)
        expense = None
        if "expense" in content:
            expense = Expense(content["expense"])

        return expense
Example #15
0
    def test_updateExpense_error(self, mockMakeRequest):
        mockMakeRequest.return_value = '{"expenses":[],"errors":{"base":["An unknown error occurred. Please try again or contact [email protected] if you experience repeated issues. Sorry for the trouble!"]}}'  # noqa: E501
        expense = Expense()
        expense.id = 1010934284
        expense.setCost('10')
        expense.setDescription("Testing")
        user1 = ExpenseUser()
        user1.setId(79774)
        user1.setPaidShare('10.00')
        user1.setOwedShare('2.0')
        user2 = ExpenseUser()
        user2.setId(281236)
        user2.setPaidShare('0.00')
        user2.setOwedShare('8.00')
        users = []
        users.append(user1)
        users.append(user2)
        expense.setUsers(users)
        expenseRes, errors = self.sObj.updateExpense(expense)
        mockMakeRequest.assert_called_with(
            "https://secure.splitwise.com/api/v3.0/update_expense/1010934284",
            "POST", {
                'cost': '10',
                'description': 'Testing',
                'users__0__user_id': 79774,
                'users__0__paid_share': '10.00',
                'users__0__owed_share': '2.0',
                'users__1__user_id': 281236,
                'users__1__paid_share': '0.00',
                'users__1__owed_share': '8.00'
            },
            files=None)
        self.assertEqual(
            errors.getErrors(), {
                'base': [
                    'An unknown error occurred. Please try again or contact [email protected] if you experience repeated issues. \
Sorry for the trouble!'
                ]
            })
Example #16
0
 def test_updateExpense_missingExpenseId_Exception(self, mockMakeRequest):
     mockMakeRequest.side_effect = SplitwiseBadRequestException(
         "Incorrect query parameters sent. Expense Id cannot be null")
     expense = Expense()
     expense.setCost('10')
     expense.setDescription("Testing")
     user1 = ExpenseUser()
     user1.setId(79774)
     user1.setPaidShare('10.00')
     user1.setOwedShare('2.0')
     user2 = ExpenseUser()
     user2.setId(281236)
     user2.setPaidShare('0.00')
     user2.setOwedShare('8.00')
     users = []
     users.append(user1)
     users.append(user2)
     expense.setUsers(users)
     with self.assertRaises(SplitwiseBadRequestException):
         expenseRes, errors = self.sObj.updateExpense(expense)
    def create_expense_object(self, payer_id, payee_id, amount, description):
        expense = Expense()
        expense.setCost(amount)
        expense.setDescription(description)

        payer = ExpenseUser()
        payer.setId(payer_id)
        payer.setPaidShare(amount)
        payer.setOwedShare(0.00)

        payee = ExpenseUser()
        payee.setId(payee_id)
        payee.setPaidShare(0.00)
        payee.setOwedShare(amount)

        users = [payer, payee]
        expense.setUsers(users)
        expense = self.createExpense(expense)

        return expense
Example #18
0
def addMoney(friendName, currency, expenseReason):
    speech = "hello"
    print "name =", friendName
    print currency
    print "inside add money"
    if not friendName or not currency:
        print "error in name or currency"
        return tell("sorry couldn't proceed with transaction")

    consumer_key = ''
    consumer_secret = ''
    sObj = Splitwise(consumer_key, consumer_secret)

    with open('accesstoken.json', 'r') as f:
        access_token = json.load(f)
        print access_token
    sObj.setAccessToken(access_token)

    amountOwed = currency['amount']
    expense = Expense()
    expense.setCost(amountOwed)
    expense.setDescription(expenseReason)

    user1 = ExpenseUser()
    user1.setId(utils.getSplitwiseId('nirmit'))
    user1.setPaidShare(str(amountOwed))
    user1.setOwedShare('0.0')

    user2 = ExpenseUser()
    user2.setId(utils.getSplitwiseId(friendName))
    user2.setPaidShare('0.00')
    user2.setOwedShare(str(amountOwed))

    users = []
    users.append(user1)
    users.append(user2)
    expense.setUsers(users)

    expense = sObj.createExpense(expense)
    print expense
Example #19
0
    def createExpense(self,expense):
        #Get the expense Dict
        expense_data = expense.__dict__

        #Get users and store in a separate var
        expense_users = expense.getUsers()
        #Delete users from original dict as we
        #need to put like users_1_
        del expense_data['users']

        #Add user values to expense_data
        Splitwise.setUserArray(expense_users, expense_data)
        content = self.__makeRequest(Splitwise.CREATE_EXPENSE_URL,"POST",expense_data)
        content = json.loads(content.decode("utf-8"))
        expense = None

        if "expenses" in content:
            expense = Expense(content["expenses"][0])

        return expense
Example #20
0
    def addExpense(self, cost: float, description: str, group_id: int,
                   payer: str) -> None:
        """
        Adds expense to Splitwise group. If expenses don't evenly get 
        distributed, it will randomly assign pennies to even things off
        """
        expense = Expense()
        expense.setCost(str(cost))
        expense.setDescription(description)
        expense.setGroupId(group_id)

        group = self.sObj.getGroup(group_id)
        member_dict = self.getGroupMemberIDs(group)
        member_count = len(member_dict)
        per_person_cost = round(cost / member_count, 2)
        expense_members = []
        print(per_person_cost * member_count, cost)
        for member in member_dict:
            expense_user = ExpenseUser()
            expense_user.setId(member_dict[member])
            expense_user.setFirstName(member)
            expense_user.setOwedShare(str(per_person_cost))

            if member == payer:
                expense_user.setPaidShare(cost)
            else:
                expense_user.setPaidShare('0.00')

            expense_members.append(expense_user)

        if cost < per_person_cost * member_count:
            remainder = (per_person_cost * float(member_count)) - cost
            shuffle(expense_members)
            i = 0
            while remainder > 0.00:
                owed = float(expense_members[i].getOwedShare())
                owed -= 0.01
                expense_members[i].setOwedShare(str(owed))
                remainder -= 0.01
                if i == member_count - 1:
                    i = 0
                else:
                    i += 1

        elif cost > per_person_cost * member_count:
            remainder = round(cost - (per_person_cost * float(member_count)),
                              2)
            print(remainder)
            shuffle(expense_members)
            i = 0
            while remainder > 0.00:
                owed = float(expense_members[i].getOwedShare())
                owed += 0.01
                expense_members[i].setOwedShare(str(owed))
                remainder -= 0.01
                if i == member_count - 1:
                    i = 0
                else:
                    i += 1

        expense.setUsers(expense_members)
        expenses = self.sObj.createExpense(expense)
        print('Successfully added to Splitwise. Expense ID:', expenses.getId())
Example #21
0
 def test_expense_flow(self):
     receipt = os.path.join(os.path.dirname(os.path.realpath(__file__)),
                            "receipt.jpg")
     expense = Expense()
     expense.setDescription("End2EndTest")
     expense.setCost('10')
     expense.setGroupId(19571167)
     expense.setSplitEqually()
     expense.setReceipt(receipt)
     # create expense
     expense, error = self.sObj.createExpense(expense)
     self.assertIsNone(error)
     self.assertIsNotNone(expense.getId())
     # delete expense
     success, error = self.sObj.deleteExpense(expense.getId())
     self.assertIsNone(error)
     self.assertTrue(success)
Example #22
0
def submission():
    global df
    # TODO: add checks beforehand whether the user has clicked on all checkboxes
    # print(request.form)

    sObj = Splitwise(Config.consumer_key,Config.consumer_secret)
    sObj.setAccessToken(session['access_token'])

    saleh = ExpenseUser()
    saleh.setId(2242086)
    paypal = ExpenseUser()
    paypal.setId(18572820)
    nuraini = ExpenseUser()
    nuraini.setId(2705458)

    for key in request.form:
        if not is_number(key):
            continue
        value = request.form[key]
        if value == 'Payment':
            continue # we dont handle payments yet
        print(key, value)
        amount = df.iloc[int(float(key))]['Amount']
        users = []
        users.append(saleh)
        users.append(paypal)
        users.append(nuraini)
        saleh.setPaidShare('0.00')
        nuraini.setPaidShare('0.00')
        paypal.setPaidShare('0.00')
            
        saleh.setOwedShare('0.00')
        nuraini.setOwedShare('0.00')
        paypal.setOwedShare('0.00')

        expense = Expense()
        expense.setUsers(users)
        expense.setGroupId(6456733)
        expense.setCost(str(abs(float(amount))))
        expense.setDescription(df.iloc[int(float(key))]['Description'])

        try:
            expense.setDate(datetime.datetime.strptime(df.iloc[int(float(key))]['Trans Date'], '%m/%d/%Y').strftime('%d/%m/%Y'))
        except:
            expense.setDate(datetime.datetime.strptime(df.iloc[int(float(key))]['Trans Date'], '%m/%d/%y').strftime('%d/%m/%Y'))

        # case where a transaction is refunded
        if float(amount) > 0:
            if value == 'Saleh':
                paypal.setOwedShare(str(abs(float(amount))))
                saleh.setPaidShare(str(abs(float(amount))))
            elif value == 'Nuraini':
                paypal.setOwedShare(str(abs(float(amount))))
                nuraini.setPaidShare(str(abs(float(amount))))   
            expense = sObj.createExpense(expense)
            continue

        # case for expenses
        if value == 'Saleh':
            saleh.setOwedShare(str(abs(float(amount))))
            paypal.setPaidShare(str(abs(float(amount))))
            expense = sObj.createExpense(expense)
        elif value == 'Nuraini':
            nuraini.setOwedShare(str(abs(float(amount))))
            paypal.setPaidShare(str(abs(float(amount))))
            expense = sObj.createExpense(expense)
        elif value == 'Half-Split':
            half = round(abs(float(amount))/2,2)
            other_half = abs(float(amount))-half
            nuraini.setOwedShare(half)
            saleh.setOwedShare(other_half)
            paypal.setPaidShare(str(abs(float(amount))))
            expense = sObj.createExpense(expense)
        elif value == 'Share':
            
            continue
    
    return redirect(url_for("success"))
Example #23
0
def transaction(Description, Group, Payer, Price, Contributors):
    # price, date, description, group ID or this particular groups name, members
    sObj = Splitwise(consumer_key, secret_key)
    sObj.setAccessToken(session['access_token'])
    user = sObj.getCurrentUser()
    groups = sObj.getGroups()
    group_dict = {group.getName(): group for group in groups}
    importedData = {'Date': datetime.datetime.now(), 'Description': Description, 'Group': Group, 'Payer': Payer, 'Debit': Price}
    expense = Expense()
    price = float(importedData['Debit'] or 0)
    expense.setCost(price)
    expense.setDate(importedData['Date'])
    expense.setDescription(importedData['Description'])
    expense.setGroupId(group_dict[importedData['Group']].getId())
    members = group_dict[importedData['Group']].getMembers()
    users = []
    contributors = Contributors
    for member in members:
        if member.getFirstName() in contributors:
            user = ExpenseUser()
            user.setId(member.getId())
            if member.getFirstName() == importedData['Payer']:
                user.setPaidShare(price)
            else:
                user.setPaidShare(0)
            users.append(user)
    paid = 0
    share = round(price/len(users), 2)
    for user in users:
        user.setOwedShare(share)
        paid = paid + share
    diff = price - paid
    if diff != 0:
        user = random.choice(users)
        user.setOwedShare(share + diff)
    expense.setUsers(users)
    expense = sObj.createExpense(expense)
Example #24
0
 def test_updateExpense_split_equally_success(self, mockMakeRequest):
     mockMakeRequest.return_value = '{"expenses":[{"id":1010906976,"group_id":19433671,"friendship_id":null,"expense_bundle_id":null,"description":"Testing","repeats":false,"repeat_interval":"never","email_reminder":false,"email_reminder_in_advance":-1,"next_repeat":null,"details":"Full details of the expense","comments_count":0,"payment":false,"creation_method":null,"transaction_method":"offline","transaction_confirmed":false,"transaction_id":null,"cost":"13.0","currency_code":"SGD","repayments":[{"from":643871,"to":79774,"amount":"5.0"}],"date":"2020-06-24T06:57:29Z","created_at":"2020-06-24T06:57:29Z","created_by":{"id":79774,"first_name":"Naman","last_name":"Aggarwal","picture":{"medium":"https://splitwise.s3.amazonaws.com/uploads/user/avatar/79774/medium_mypic.jpg"},"custom_picture":true},"updated_at":"2020-06-24T06:57:29Z","updated_by":null,"deleted_at":null,"deleted_by":null,"category":{"id":18,"name":"General"},"receipt":{"large":null,"original":null},"users":[{"user":{"id":79774,"first_name":"Naman","last_name":"Aggarwal","picture":{"medium":"https://splitwise.s3.amazonaws.com/uploads/user/avatar/79774/medium_mypic.jpg"}},"user_id":79774,"paid_share":"10.0","owed_share":"5.0","net_balance":"5.0"},{"user":{"id":643871,"first_name":"Shantanu","last_name":"Alshi","picture":{"medium":"https://s3.amazonaws.com/splitwise/uploads/user/default_avatars/avatar-blue19-100px.png"}},"user_id":643871,"paid_share":"0.0","owed_share":"5.0","net_balance":"-5.0"}]}],"errors":{}}'  # noqa: E501
     expense = Expense()
     expense.id = 1010906976
     expense.setCost('13')
     expense.setDescription("Testing")
     expense.setGroupId(19433671)
     expense.setDetails("Full details of the expense")
     expense.setSplitEqually()
     expenseRes, errors = self.sObj.updateExpense(expense)
     mockMakeRequest.assert_called_with(
         "https://secure.splitwise.com/api/v3.0/update_expense/1010906976",
         "POST", {
             'cost': '13',
             'description': 'Testing',
             'details': 'Full details of the expense',
             'group_id': 19433671,
             'split_equally': True
         },
         files=None)
     self.assertIsNone(errors)
     self.assertEqual(expenseRes.getId(), 1010906976)
     self.assertEqual(expenseRes.getGroupId(), 19433671)
     self.assertEqual(expenseRes.getFriendshipId(), None)
     self.assertEqual(expenseRes.getExpenseBundleId(), None)
     self.assertEqual(expenseRes.getDescription(), "Testing")
     self.assertEqual(expenseRes.getRepeatInterval(), "never")
     self.assertEqual(expenseRes.getEmailReminderInAdvance(), -1)
     self.assertEqual(expenseRes.getNextRepeat(), None)
     self.assertEqual(expenseRes.getDetails(),
                      "Full details of the expense")
     self.assertEqual(expenseRes.getCommentsCount(), 0)
     self.assertEqual(expenseRes.getCreationMethod(), None)
     self.assertEqual(expenseRes.getTransactionMethod(), "offline")
     self.assertEqual(expenseRes.getTransactionId(), None)
     self.assertEqual(expenseRes.getCost(), "13.0")
     self.assertEqual(expenseRes.getCurrencyCode(), "SGD")
     self.assertEqual(len(expenseRes.getRepayments()), 1)
     self.assertEqual(expenseRes.getRepayments()[0].getFromUser(), 643871)
     self.assertEqual(expenseRes.getRepayments()[0].getToUser(), 79774)
     self.assertEqual(expenseRes.getRepayments()[0].getAmount(), "5.0")
     self.assertEqual(expenseRes.getDate(), "2020-06-24T06:57:29Z")
     self.assertEqual(expenseRes.getCreatedAt(), "2020-06-24T06:57:29Z")
     self.assertEqual(expenseRes.getCreatedBy().getId(), 79774)
     self.assertEqual(expenseRes.getCreatedBy().getFirstName(), "Naman")
     self.assertEqual(expenseRes.getCreatedBy().getLastName(), "Aggarwal")
     self.assertEqual(
         expenseRes.getCreatedBy().getPicture().getMedium(),
         "https://splitwise.s3.amazonaws.com/uploads/user/avatar/79774/medium_mypic.jpg"
     )
     self.assertEqual(expenseRes.getUpdatedAt(), "2020-06-24T06:57:29Z")
     self.assertEqual(expenseRes.getUpdatedBy(), None)
     self.assertEqual(expenseRes.getDeletedAt(), None)
     self.assertEqual(expenseRes.getDeletedBy(), None)
     self.assertEqual(expenseRes.getCategory().getId(), 18)
     self.assertEqual(expenseRes.getCategory().getName(), "General")
     self.assertEqual(expenseRes.getReceipt().getLarge(), None)
     self.assertEqual(expenseRes.getReceipt().getOriginal(), None)
     self.assertEqual(len(expenseRes.getUsers()), 2)
     self.assertEqual(expenseRes.getUsers()[0].getId(), 79774)
     self.assertEqual(expenseRes.getUsers()[0].getFirstName(), "Naman")
     self.assertEqual(expenseRes.getUsers()[0].getLastName(), "Aggarwal")
     self.assertEqual(
         expenseRes.getUsers()[0].getPicture().getMedium(),
         "https://splitwise.s3.amazonaws.com/uploads/user/avatar/79774/medium_mypic.jpg"
     )
     self.assertEqual(expenseRes.getUsers()[0].getPaidShare(), "10.0")
     self.assertEqual(expenseRes.getUsers()[0].getOwedShare(), "5.0")
     self.assertEqual(expenseRes.getUsers()[0].getNetBalance(), "5.0")
     self.assertEqual(expenseRes.getUsers()[1].getId(), 643871)
     self.assertEqual(expenseRes.getUsers()[1].getFirstName(), "Shantanu")
     self.assertEqual(expenseRes.getUsers()[1].getLastName(), "Alshi")
     self.assertEqual(
         expenseRes.getUsers()[1].getPicture().getMedium(),
         "https://s3.amazonaws.com/splitwise/uploads/user/default_avatars/avatar-blue19-100px.png"
     )
     self.assertEqual(expenseRes.getUsers()[1].getPaidShare(), "0.0")
     self.assertEqual(expenseRes.getUsers()[1].getOwedShare(), "5.0")
     self.assertEqual(expenseRes.getUsers()[1].getNetBalance(), "-5.0")
def main():
    if 'access_token' in session:
        sObj.setAccessToken(session['access_token'])
        user = sObj.getCurrentUser()
        friends = sObj.getFriends()
        friends_dict = {friend.getFirstName():friend.getId() for friend in friends}
        groups = sObj.getGroups()
        group_list = [group.getName() for group in groups]
        group_id = [group.getId() for group in groups]
        group_dict = {group.getName():group for group in groups}

        with open(CSV_FILE_LOCATION, encoding='utf-8-sig') as data:
            importedData = list(csv.DictReader(data))
            # print(importedData)

            ##### Vet csv before proceeding #####
        for i, row in enumerate(importedData):
            if not (row.get('Debit') and row.get('Payer') and row.get('Group')):
                return f"Remove blanks on row {i+1} in your CSV and try again."

        with open(DB) as db_json:
            db = json.load(db_json)

        msg = []

        # Begin loop reading the CSV
        for row in importedData:
            rowstring = f"{row.get('Date')}, {row.get('Debit')}, {row.get('Description')}, {row.get('Group')}, {row.get('Payer')}"
            rsbytes = bytes(rowstring, 'utf-8')
            hash_obj = hashlib.sha256(rsbytes)
            hex_dig = hash_obj.hexdigest()
            # print(hex_dig)
            if hex_dig in db:
                msg.append(f"{rowstring} looks like a duplicate, skipping")
                continue
            else:
                db[hex_dig] = "True"


            expense = Expense()
            price = float(row['Debit'] or 0)
            expense.setCost(price)
            expense.setDate(row['Date'])
            expense.setDescription(row['Description'])
            expense.setGroupId(group_dict[row['Group']].getId())
            members = group_dict[row['Group']].getMembers()
            users = []

            for member in members:
                user = ExpenseUser()
                user.setId(member.getId())
                if member.getFirstName() == row['Payer']:
                    user.setPaidShare(price)
                else:
                    user.setPaidShare(0)
                users.append(user)

            paid = 0
            share = round(price/len(users),2)
            for user in users:
                user.setOwedShare(share)
                paid = paid + share
            diff = price - paid
            if diff != 0:
                user = random.choice(users)
                user.setOwedShare(share + diff)


            expense.setUsers(users)

            expense = sObj.createExpense(expense)

        msg.append('Import successful!')

        with open(DB, 'w') as outfile:
            json.dump(db, outfile)
            msg.append('New entries recorded in db.')

        message = "<br>".join(msg)
        return message


    return 'User is not logged in'
Example #26
0
 def test_updateExpense_split_manually_success(self, mockMakeRequest):
     mockMakeRequest.return_value = '{"expenses":[{"id":1010934284,"group_id":null,"friendship_id":null,"expense_bundle_id":null,"description":"Testing","repeats":false,"repeat_interval":"never","email_reminder":false,"email_reminder_in_advance":-1,"next_repeat":null,"details":null,"comments_count":0,"payment":false,"creation_method":null,"transaction_method":"offline","transaction_confirmed":false,"transaction_id":null,"cost":"10.0","currency_code":"SGD","repayments":[{"from":281236,"to":79774,"amount":"8.0"}],"date":"2020-06-24T08:14:07Z","created_at":"2020-06-24T08:14:07Z","created_by":{"id":79774,"first_name":"Naman","last_name":"Aggarwal","picture":{"medium":"https://splitwise.s3.amazonaws.com/uploads/user/avatar/79774/medium_mypic.jpg"},"custom_picture":true},"updated_at":"2020-06-24T08:14:07Z","updated_by":null,"deleted_at":null,"deleted_by":null,"category":{"id":18,"name":"General"},"receipt":{"large":null,"original":null},"users":[{"user":{"id":79774,"first_name":"Naman","last_name":"Aggarwal","picture":{"medium":"https://splitwise.s3.amazonaws.com/uploads/user/avatar/79774/medium_mypic.jpg"}},"user_id":79774,"paid_share":"10.0","owed_share":"2.0","net_balance":"8.0"},{"user":{"id":281236,"first_name":"Siddharth","last_name":"Goel","picture":{"medium":"https://splitwise.s3.amazonaws.com/uploads/user/avatar/281236/medium_f5fccc37-0a88-4519-9398-59c8c19b92aa.jpeg"}},"user_id":281236,"paid_share":"0.0","owed_share":"8.0","net_balance":"-8.0"}]}],"errors":{}}'  # noqa: E501
     expense = Expense()
     expense.id = 1010934284
     expense.setCost('10')
     expense.setDescription("Testing")
     user1 = ExpenseUser()
     user1.setId(79774)
     user1.setPaidShare('10.00')
     user1.setOwedShare('2.0')
     user2 = ExpenseUser()
     user2.setId(281236)
     user2.setPaidShare('0.00')
     user2.setOwedShare('8.00')
     users = []
     users.append(user1)
     users.append(user2)
     expense.setUsers(users)
     expenseRes, errors = self.sObj.updateExpense(expense)
     mockMakeRequest.assert_called_with(
         "https://secure.splitwise.com/api/v3.0/update_expense/1010934284",
         "POST", {
             'cost': '10',
             'description': 'Testing',
             'users__0__user_id': 79774,
             'users__0__paid_share': '10.00',
             'users__0__owed_share': '2.0',
             'users__1__user_id': 281236,
             'users__1__paid_share': '0.00',
             'users__1__owed_share': '8.00'
         },
         files=None)
     self.assertIsNone(errors)
     self.assertEqual(expenseRes.getId(), 1010934284)
     self.assertEqual(expenseRes.getGroupId(), None)
     self.assertEqual(expenseRes.getFriendshipId(), None)
     self.assertEqual(expenseRes.getExpenseBundleId(), None)
     self.assertEqual(expenseRes.getDescription(), "Testing")
     self.assertEqual(expenseRes.getRepeatInterval(), "never")
     self.assertEqual(expenseRes.getEmailReminderInAdvance(), -1)
     self.assertEqual(expenseRes.getNextRepeat(), None)
     self.assertEqual(expenseRes.getDetails(), None)
     self.assertEqual(expenseRes.getCommentsCount(), 0)
     self.assertEqual(expenseRes.getCreationMethod(), None)
     self.assertEqual(expenseRes.getTransactionMethod(), "offline")
     self.assertEqual(expenseRes.getTransactionId(), None)
     self.assertEqual(expenseRes.getCost(), "10.0")
     self.assertEqual(expenseRes.getCurrencyCode(), "SGD")
     self.assertEqual(len(expenseRes.getRepayments()), 1)
     self.assertEqual(expenseRes.getRepayments()[0].getFromUser(), 281236)
     self.assertEqual(expenseRes.getRepayments()[0].getToUser(), 79774)
     self.assertEqual(expenseRes.getRepayments()[0].getAmount(), "8.0")
     self.assertEqual(expenseRes.getDate(), "2020-06-24T08:14:07Z")
     self.assertEqual(expenseRes.getCreatedAt(), "2020-06-24T08:14:07Z")
     self.assertEqual(expenseRes.getCreatedBy().getId(), 79774)
     self.assertEqual(expenseRes.getCreatedBy().getFirstName(), "Naman")
     self.assertEqual(expenseRes.getCreatedBy().getLastName(), "Aggarwal")
     self.assertEqual(
         expenseRes.getCreatedBy().getPicture().getMedium(),
         "https://splitwise.s3.amazonaws.com/uploads/user/avatar/79774/medium_mypic.jpg"
     )
     self.assertEqual(expenseRes.getUpdatedAt(), "2020-06-24T08:14:07Z")
     self.assertEqual(expenseRes.getUpdatedBy(), None)
     self.assertEqual(expenseRes.getDeletedAt(), None)
     self.assertEqual(expenseRes.getDeletedBy(), None)
     self.assertEqual(expenseRes.getCategory().getId(), 18)
     self.assertEqual(expenseRes.getCategory().getName(), "General")
     self.assertEqual(expenseRes.getReceipt().getLarge(), None)
     self.assertEqual(expenseRes.getReceipt().getOriginal(), None)
     self.assertEqual(len(expenseRes.getUsers()), 2)
     self.assertEqual(expenseRes.getUsers()[0].getId(), 79774)
     self.assertEqual(expenseRes.getUsers()[0].getFirstName(), "Naman")
     self.assertEqual(expenseRes.getUsers()[0].getLastName(), "Aggarwal")
     self.assertEqual(
         expenseRes.getUsers()[0].getPicture().getMedium(),
         "https://splitwise.s3.amazonaws.com/uploads/user/avatar/79774/medium_mypic.jpg"
     )
     self.assertEqual(expenseRes.getUsers()[0].getPaidShare(), "10.0")
     self.assertEqual(expenseRes.getUsers()[0].getOwedShare(), "2.0")
     self.assertEqual(expenseRes.getUsers()[0].getNetBalance(), "8.0")
     self.assertEqual(expenseRes.getUsers()[1].getId(), 281236)
     self.assertEqual(expenseRes.getUsers()[1].getFirstName(), "Siddharth")
     self.assertEqual(expenseRes.getUsers()[1].getLastName(), "Goel")
     self.assertEqual(
         expenseRes.getUsers()[1].getPicture().getMedium(),
         "https://splitwise.s3.amazonaws.com/uploads/user/avatar/281236/medium_f5fccc37-0a88-4519-9398-59c8c19b92aa.jpeg"
     )
     self.assertEqual(expenseRes.getUsers()[1].getPaidShare(), "0.0")
     self.assertEqual(expenseRes.getUsers()[1].getOwedShare(), "8.0")
     self.assertEqual(expenseRes.getUsers()[1].getNetBalance(), "-8.0")
Example #27
0
File: app.py Project: omijn/tmo
def add_group_expense(exp_data: dict):
    """
    Utility function to add multiple expenses at once.
    Pass in a dict of user_ids -> amount owed
    """
    try:
        total = float(exp_data['total'])
        group_id = exp_data['group_id']
        desc = exp_data['desc']
    except KeyError:
        print("total, group_id and desc are required fields in the expense")
        return

    expense = Expense()
    expense.setCost(total)
    expense.setDescription(desc)
    expense.setGroupId(group_id)

    sum = 0

    for user_id, details in exp_data['users'].items():
        try:
            amt = float(details["amt"])
        except KeyError:
            print("'amt' is a required field")
            return
        except ValueError:
            print(f"invalid amount {details['amt']}")
            return

        user = ExpenseUser()
        user.setId(user_id)
        user.setPaidShare(0)
        user.setOwedShare(amt)
        sum += amt

        expense.addUser(user)

    me = ExpenseUser()
    me.setId(s.getCurrentUser().getId())
    me.setPaidShare(total)
    me.setOwedShare(total - sum)
    expense.addUser(me)

    if DRY_RUN:
        print("--- dry run ---")
        print_expense_details(expense)
        return

    resp, err = s.createExpense(expense)

    # handle err
    if err is not None:
        print(err.getErrors())
        return

    print("Expense created!")
    timestamp_comment = f"added at {datetime.datetime.now()} :)"
    add_comment_to_expense(resp.getId(), timestamp_comment)

    # extra comments
    if "comment" in exp_data and exp_data["comment"] != "":
        add_comment_to_expense(resp.getId(), comment)
Example #28
0
    def import_expenses(self):
        try:
            row = int(self.le_initial_row.text()) - 1
            description_col = int(self.le_description_col.text()) - 1
            date_col = int(self.le_date_col.text()) - 1
            default_date = self.default_date.date()
            date_format = self.le_date_format.text()
            percent = 1.0 / len(list(self.current_group.getMembers()))
            while self.model.item(row) is not None:
                print("Row ", row)

                expense = Expense()
                expense.setDescription(
                    self.model.item(row, description_col).text())
                print("Expense: ", expense.getDescription())
                date = QDate.fromString(
                    self.model.item(row, date_col).text(), date_format)
                if not date.isValid():
                    date = default_date
                expense.setDate(date.toString(Qt.ISODate))
                print("Date: ", expense.getDate())

                cost = 0
                users = []
                for member in self.current_group.getMembers():
                    print("Processing member ", member.getFirstName())
                    member_column = int(
                        self.member_widget_map[member.getId()].text()) - 1
                    paid = 0
                    try:
                        paid = float(
                            self.model.item(row, member_column).text())
                        print("Expense: ",
                              self.model.item(row, member_column).text())
                    except:
                        pass
                    cost = cost + paid
                    expense_user = ExpenseUser()
                    expense_user.setId(member.getId())
                    expense_user.setPaidShare(str(paid))
                    users.append(expense_user)
                for expense_user in users:
                    expense_user.setOwedShare(str(cost * percent))
                if cost == 0:
                    raise Exception(
                        self.tr('No se ha introducido monto para el gasto'))
                expense.setCost(str(cost))
                expense.setUsers(users)
                expense.setGroupId(self.current_group.id)
                self.sObj.createExpense(expense)
                row = row + 1
                self.le_initial_row.setText(str(row + 1))
        except Exception as inst:
            QMessageBox.critical(
                self, self.tr("Error"),
                self.tr("Se ha producido un error en la fila") + str(row + 1) +
                "\n" + str(inst))
            traceback.print_exc()
 def get_expense_obj(self):
     return Expense()
Example #30
0
File: app.py Project: omijn/tmo
def print_expense_details(expense: Expense):
    for user in expense.getUsers():
        print(f"{user.getId()} owes {user.getOwedShare()}")