예제 #1
0
    def return_account_balance(self,
                               date_cursor: Union[str, date,
                                                  datetime] = None) -> Decimal:
        """
        Returns the balance of the policy in a given point in time
        :param date_cursor:
        :return:
        """
        if not date_cursor:
            date_cursor = datetime.now().date()

        invoices = (DBSession.query(Invoice).filter_by(
            policy_id=self.policy.id).filter(
                Invoice.bill_date <= date_cursor).order_by(
                    Invoice.bill_date).all())
        due_now = 0
        for invoice in invoices:
            due_now += invoice.amount_due

        payments = (DBSession.query(Payment).filter_by(
            policy_id=self.policy.id).filter(
                Payment.transaction_date <= date_cursor).all())
        for payment in payments:
            due_now -= payment.amount_paid

        return Decimal(due_now)
예제 #2
0
    def setUpClass(cls):
        cls.test_agent = Contact("Test Agent", "Agent")
        cls.test_insured = Contact("Test Insured", "Named Insured")
        DBSession.add(cls.test_agent)
        DBSession.add(cls.test_insured)
        DBSession.commit()

        cls.policy = Policy("Test Policy", date(2015, 1, 1), 1200)
        cls.policy.named_insured = cls.test_insured.id
        cls.policy.agent = cls.test_agent.id
        DBSession.add(cls.policy)
        DBSession.commit()
예제 #3
0
 def cancel_policy(self,
                   reason: str,
                   date_cursor: Union[str, date, datetime] = None):
     if not date_cursor:
         date_cursor = datetime.now().date()
     self.policy.cancel_reason = reason
     self.policy.cancel_date = date_cursor
     self.policy.status = "Canceled"
     DBSession.add(self.policy)
     DBSession.commit()
     self.policy = None
     print("Policy successfully canceled!")
예제 #4
0
    def evaluate_cancellation_pending_due_to_non_pay(
            self, date_cursor: Union[str, date, datetime] = None) -> bool:
        """
        If this function returns true, an invoice
        on a policy has passed the due date without
        being paid in full. However, it has not necessarily
        made it to the cancel_date yet.
        :param date_cursor:
        :return:
        """
        if not date_cursor:
            date_cursor = datetime.now().date()

        invoices = (DBSession.query(Invoice).filter_by(
            policy_id=self.policy.id).filter(
                Invoice.due_date <= date_cursor).filter(
                    Invoice.cancel_date >= date_cursor).order_by(
                        Invoice.bill_date).all())

        for invoice in invoices:
            if not self.return_account_balance(invoice.due_date):
                continue
            else:
                return True
        return False
예제 #5
0
 def test_quarterly_on_last_installment_bill_date(self):
     self.policy.billing_schedule = "Quarterly"
     pa = PolicyAccounting(self.policy.id)
     invoices = (DBSession.query(Invoice).filter_by(
         policy_id=self.policy.id).order_by(Invoice.bill_date).all())
     self.assertEquals(
         pa.return_account_balance(date_cursor=invoices[3].bill_date), 1200)
예제 #6
0
    def __init__(self, policy_id: int) -> None:
        self.policy = DBSession.query(Policy).filter_by(id=policy_id).one()
        if self.policy.status == "Canceled":
            raise UserWarning(
                "This policy canceled \nCancel date: {0} \nReason: {1}".format(
                    self.policy.cancel_date.strftime("%Y-%m-%d"),
                    self.policy.cancel_reason,
                ))

        if not self.policy.invoices:
            self.make_invoices()
예제 #7
0
 def test_quarterly_on_second_installment_bill_date_with_full_payment(self):
     self.policy.billing_schedule = "Quarterly"
     pa = PolicyAccounting(self.policy.id)
     invoices = (DBSession.query(Invoice).filter_by(
         policy_id=self.policy.id).order_by(Invoice.bill_date).all())
     self.payments.append(
         pa.make_payment(
             contact_id=self.policy.named_insured,
             date_cursor=invoices[1].bill_date,
             amount=600,
         ))
     self.assertEquals(
         pa.return_account_balance(date_cursor=invoices[1].bill_date), 0)
예제 #8
0
    def make_payment(
            self,
            contact_id: int = 0,
            date_cursor: Union[str, date, datetime] = None,
            amount: Decimal = Decimal(0),
    ) -> Payment:
        """
        Creates a payment in a given point in time
        :param contact_id:
        :param date_cursor:
        :param amount:
        :return:
        """
        if not date_cursor:
            date_cursor = datetime.now().date()
        due_to_non_pay = self.evaluate_cancellation_pending_due_to_non_pay(
            date_cursor)
        if not contact_id:
            try:
                contact_id = self.policy.named_insured
            except:
                pass

        try:
            contact = DBSession.query(Contact).filter_by(id=contact_id).one()
        except NoResultFound:
            raise NoResultFound("We couldn't find any contact with this id")

        if due_to_non_pay and not contact.role == "Agent":
            raise UserWarning(
                "Policy has passed the due date without being "
                "paid in full, only an agent can't make a payment")

        payment = Payment(self.policy.id, contact_id, amount, date_cursor)
        DBSession.add(payment)
        DBSession.commit()

        return payment
예제 #9
0
def get_tasks():
    policy_number = request.args.get("policy_number", None)
    try:
        date_cursor = datetime.strptime(request.args.get("date_cursor", None),
                                        "%Y-%m-%d")
    except ValueError:
        raise InvalidUsage("Bad date format", status_code=400)
    try:
        policy = (DBSession.query(Policy).filter(
            Policy.policy_number == policy_number).one())
    except NoResultFound:
        raise InvalidUsage("Policy Not Found", status_code=404)
    invoices = policy.invoices
    pa = PolicyAccounting(policy.id)
    balance = pa.return_account_balance(date_cursor=date_cursor)
    data = {
        "balance": str(balance),
        "invoices": [i.serialize() for i in invoices]
    }
    return jsonify(data)
예제 #10
0
    def evaluate_cancel(self,
                        date_cursor: Union[str, date,
                                           datetime] = None) -> bool:
        """
        Check if there is any balance after any of the cancel dates
        of the invoices in this policy
        :param date_cursor:
        :return:
        """
        if not date_cursor:
            date_cursor = datetime.now().date()

        invoices = (DBSession.query(Invoice).filter_by(
            policy_id=self.policy.id).filter(
                Invoice.cancel_date <= date_cursor).order_by(
                    Invoice.bill_date).all())

        for invoice in invoices:
            if not self.return_account_balance(invoice.cancel_date):
                continue
            else:
                return True
        else:
            return False
예제 #11
0
 def switch_billing_schedule(self, new_billing_schedule: str) -> None:
     """
     Move a policy to a different billing schedule
     :param new_billing_schedule:
     :return:
     """
     try:
         BILLING_SCHEDULES[new_billing_schedule]
     except KeyError:
         raise KeyError("Invalid billing schedule")
     if self.policy.billing_schedule == new_billing_schedule:
         raise UserWarning(
             "This policy is already on {0}".format(new_billing_schedule))
     for invoice in self.policy.invoices:
         invoice.deleted = 1
         DBSession.add(invoice)
     self.policy.billing_schedule = new_billing_schedule
     DBSession.add(self.policy)
     DBSession.flush()
     self.make_invoices()
예제 #12
0
def insert_data():
    # Contacts
    contacts = []
    john_doe_agent = Contact("John Doe", "Agent")
    contacts.append(john_doe_agent)
    john_doe_insured = Contact("John Doe", "Named Insured")
    contacts.append(john_doe_insured)
    bob_smith = Contact("Bob Smith", "Agent")
    contacts.append(bob_smith)
    anna_white = Contact("Anna White", "Named Insured")
    contacts.append(anna_white)
    joe_lee = Contact("Joe Lee", "Agent")
    contacts.append(joe_lee)
    ryan_bucket = Contact("Ryan Bucket", "Named Insured")
    contacts.append(ryan_bucket)

    for contact in contacts:
        DBSession.add(contact)
    DBSession.commit()

    policies = []
    p1 = Policy("Policy One", date(2015, 1, 1), 365)
    p1.billing_schedule = "Annual"
    p1.named_insured = john_doe_insured.id
    p1.agent = bob_smith.id
    policies.append(p1)

    p2 = Policy("Policy Two", date(2015, 2, 1), 1600)
    p2.billing_schedule = "Quarterly"
    p2.named_insured = anna_white.id
    p2.agent = joe_lee.id
    policies.append(p2)

    p3 = Policy("Policy Three", date(2015, 1, 1), 1200)
    p3.billing_schedule = "Monthly"
    p3.named_insured = ryan_bucket.id
    p3.agent = john_doe_agent.id
    policies.append(p3)

    p4 = Policy("Policy Four", date(2015, 2, 1), 500)
    p4.billing_schedule = "Two-Pay"
    p4.named_insured = ryan_bucket.id
    p4.agent = john_doe_agent.id
    policies.append(p4)

    for policy in policies:
        DBSession.add(policy)
    DBSession.commit()

    for policy in policies:
        PolicyAccounting(policy.id)

    payment_for_p2 = Payment(p2.id, anna_white.id, 400, date(2015, 2, 1))
    DBSession.add(payment_for_p2)
    DBSession.commit()
예제 #13
0
    def make_invoices(self) -> None:
        """
        Create invoices for the policy according with its billing schedule
        """
        for invoice in self.policy.invoices:
            DBSession.delete(invoice)

        invoices = []
        first_invoice = Invoice(
            self.policy.id,
            self.policy.effective_date,  # bill_date
            self.policy.effective_date + relativedelta(months=1),  # due
            self.policy.effective_date +
            relativedelta(months=1, days=14),  # cancel
            self.policy.annual_premium,
        )
        invoices.append(first_invoice)

        if self.policy.billing_schedule == "Annual":
            pass
        elif self.policy.billing_schedule == "Two-Pay":
            first_invoice.amount_due = first_invoice.amount_due / BILLING_SCHEDULES.get(
                self.policy.billing_schedule)
            for i in range(1,
                           BILLING_SCHEDULES.get(
                               self.policy.billing_schedule)):
                months_after_eff_date = i * 6
                bill_date = self.policy.effective_date + relativedelta(
                    months=months_after_eff_date)
                invoice = Invoice(
                    self.policy.id,
                    bill_date,
                    bill_date + relativedelta(months=1),
                    bill_date + relativedelta(months=1, days=14),
                    self.policy.annual_premium /
                    BILLING_SCHEDULES.get(self.policy.billing_schedule),
                )
                invoices.append(invoice)
        elif self.policy.billing_schedule == "Quarterly":
            first_invoice.amount_due = first_invoice.amount_due / BILLING_SCHEDULES.get(
                self.policy.billing_schedule)
            for i in range(1,
                           BILLING_SCHEDULES.get(
                               self.policy.billing_schedule)):
                months_after_eff_date = i * 3
                bill_date = self.policy.effective_date + relativedelta(
                    months=months_after_eff_date)
                invoice = Invoice(
                    self.policy.id,
                    bill_date,
                    bill_date + relativedelta(months=1),
                    bill_date + relativedelta(months=1, days=14),
                    self.policy.annual_premium /
                    BILLING_SCHEDULES.get(self.policy.billing_schedule),
                )
                invoices.append(invoice)
        elif self.policy.billing_schedule == "Monthly":
            first_invoice.amount_due = first_invoice.amount_due / BILLING_SCHEDULES.get(
                self.policy.billing_schedule)
            for i in range(1,
                           BILLING_SCHEDULES.get(
                               self.policy.billing_schedule)):
                bill_date = self.policy.effective_date + relativedelta(
                    months=i)
                invoice = Invoice(
                    self.policy.id,
                    bill_date,
                    bill_date + relativedelta(months=1),
                    bill_date + relativedelta(months=1, days=14),
                    self.policy.annual_premium /
                    BILLING_SCHEDULES.get(self.policy.billing_schedule),
                )
                invoices.append(invoice)
        else:
            print("You have chosen a bad billing schedule.")

        for invoice in invoices:
            DBSession.add(invoice)
        DBSession.commit()
예제 #14
0
 def tearDown(self):
     for invoice in self.policy.invoices:
         DBSession.delete(invoice)
     for payment in self.payments:
         DBSession.delete(payment)
     DBSession.commit()
예제 #15
0
 def tearDownClass(cls):
     DBSession.delete(cls.test_insured)
     DBSession.delete(cls.test_agent)
     DBSession.delete(cls.policy)
     DBSession.commit()
예제 #16
0
 def tearDown(self):
     for invoice in self.policy.invoices:
         DBSession.delete(invoice)
     DBSession.commit()