Commits

Luke Plant  committed d1f5f4e

Fixed corner case where bookings should be marked as confirmed immediately

  • Participants
  • Parent commits fb459dc
  • Branches bookings

Comments (0)

Files changed (2)

File cciw/bookings/models.py

         # Use update and F objects to avoid concurrency problems
         BookingAccount.objects.filter(id=self.id).update(total_received=models.F('total_received') + amount)
 
-        # Need new data from DB, so get a fresh object
+        # Need new data from DB:
         acc = BookingAccount.objects.get(id=self.id)
         self.total_received = acc.total_received
 
+        self.distribute_balance()
+
+    def distribute_balance(self):
         # In order to distribute funds, need to take into account the total
         # amount in the account that is not covered by confirmed places
-        existing_balance = acc.get_balance(confirmed_only=True)
+        existing_balance = self.get_balance(confirmed_only=True)
         # The 'pot' is the amount we have as excess and can use to mark places
         # as confirmed.
         pot = -existing_balance
             b.booking_expires = now + timedelta(1) # 24 hours
             b.save()
 
+        # In some cases we may have enough money to pay for places from money in
+        # account. Since a payment will not be needed or received, we need to
+        # make sure these don't expire.
+        seen_accounts = set()
+        for b in bookings:
+            if b.account_id in seen_accounts:
+                continue
+            b.account.distribute_balance()
+            seen_accounts.add(b.account_id)
+
         return True
     finally:
         lock.release()

File cciw/bookings/tests.py

         self.assertEqual(b.state, BOOKING_INFO_COMPLETE)
         self.assertContains(resp2, "Places were not booked due to modifications made")
 
+    def test_book_with_money_in_account(self):
+        self.login()
+        self.create_place()
+
+        # Put some money in my account.
+        acc = BookingAccount.objects.get(email=self.email)
+        acc.total_received = acc.bookings.all()[0].amount_due
+        acc.save()
+
+        # Book
+        resp = self.client.get(self.url)
+        state_token = re.search(r'name="state_token" value="(.*)"', resp.content).groups()[0]
+
+        resp2 = self.client.post(self.url, {'state_token': state_token,
+                                            'book_now': '1'},
+                                 follow=True)
+
+        # Place should be booked AND should not expire
+        b = acc.bookings.all()[0]
+        self.assertEqual(b.state, BOOKING_BOOKED)
+        self.assertEqual(b.booking_expires, None)
+
+        # balance should be zero
+        acc = BookingAccount.objects.get(email=self.email)
+        self.assertEqual(acc.get_balance(), Decimal('0.00'))
+        self.assertEqual(acc.get_balance(confirmed_only=True), Decimal('0.00'))
+
 
 class TestPay(CreatePlaceMixin, TestCase):