Exemplo n.º 1
0
class Payment(db.Model):
    __tablename__ = 'payment'

    id = db.Column(db.BigInteger, primary_key=True, nullable=False)
    invoice_id = db.Column(db.BigInteger, db.ForeignKey('invoice.id'))
    date = db.Column(db.DateTime, default=datetime.now, nullable=False)
    currency_code = db.Column(db.Unicode(3), nullable=False)
    method = db.Column(db.Unicode(50), nullable=False)
    description = db.Column(db.Unicode(255), nullable=True)
    amount = db.Column(db.Numeric(8, 2), default=0, nullable=False)
    created_at = db.Column(db.DateTime, default=datetime.now, nullable=False)

    #relation definitions
    invoice = db.relation('Invoice',
                          primaryjoin='Payment.invoice_id==Invoice.id',
                          backref=db.backref('payments', lazy='dyanmic'))
Exemplo n.º 2
0
class StripePayment(db.Model):
    __tablename__ = 'stripe_payment'

    id = db.Column(db.Integer(11), primary_key=True, nullable=False)
    user_id = db.Column(db.Integer(11),
                        db.ForeignKey('user.id'),
                        nullable=False)
    payment_id = db.Column(db.Integer(11),
                           db.ForeignKey('payment.id'),
                           nullable=True)
    invoice_id = db.Column(db.Integer(11),
                           db.ForeignKey('invoice.id'),
                           nullable=False)
    amount = db.Column(db.Numeric(8, 2), default=0)
    token = db.Column(db.Unicode(100), nullable=False)
    state = db.Column(db.Unicode(20), default=u'initialized')
    error_message = db.Column(db.Unicode(255), nullable=True)
    charge_id = db.Column(db.Unicode(100), nullable=True)
    charge = db.Column(db.UnicodeText(4294967295),
                       nullable=False,
                       default=u'{}')
    created_at = db.Column(db.DateTime(), nullable=False, default=datetime.now)

    @classmethod
    def get_or_create_for_user(cls, user_id):
        account = cls.query.filter_by(user_id=user_id).first()
        if not account:
            model = cls()
            model.user_id = user_id
            db.session.add(model)
            db.session.commit()
        return account

    def create_payment_object(self):
        """Create related payment object"""
        payment = Payment()
        payment.invoice_id = self.invoice_id
        payment.date = datetime.now()
        payment.currency_code = self.invoice.currency_code
        payment.amount = self.amount
        payment.method = 'stripe'
        payment.description = 'Credit card payment'

        db.session.add(payment)
        db.session.commit()

        return payment
Exemplo n.º 3
0
class Transaction(db.Model):
    __tablename__ = 'transaction'

    id = db.Column(db.Integer(11), primary_key=True, nullable=False)
    user_id = db.Column(db.Integer(11),
                        db.ForeignKey('user.id'),
                        nullable=False)
    subscription_id = db.Column(db.Integer(11),
                                db.ForeignKey('subscription.id'),
                                nullable=False)
    success = db.Column(db.Boolean, default=False)
    amount = db.Column(db.Numeric(8, 2), default=0)
    charge_id = db.Column(db.Unicode(100), nullable=True)
    charge = db.Column(db.UnicodeText(4294967295),
                       nullable=True,
                       default=u'{}')

    updated_at = db.Column(db.DateTime, nullable=False, default=datetime.now)
    created_at = db.Column(db.DateTime,
                           nullable=False,
                           default=datetime.now,
                           onupdate=datetime.now)
Exemplo n.º 4
0
class TaxRate(db.Model):
    __tablename__ = 'tax_rate'

    id = db.Column(u'id', db.BigInteger, primary_key=True, nullable=False)
    user_id = db.Column(u'user_id', db.BigInteger, db.ForeignKey('user.id'))

    type = db.Column(u'type', db.String(255))
    name = db.Column(u'name', db.String(255))
    rate = db.Column(u'rate', db.Numeric(8, 2), nullable=True)

    updated_at = db.Column(u'updated_at',
                           db.DateTime(),
                           nullable=False,
                           default=get_current_time())
    created_at = db.Column(u'created_at',
                           db.DateTime(),
                           nullable=False,
                           default=get_current_time())

    user = db.relation('User', lazy='select', backref='tax_rates')

    def serialize(self):
        return model_to_dict(self)
Exemplo n.º 5
0
class Plan(db.Model):
    __tablename__ = 'plan'

    id = db.Column(db.Integer(11), primary_key=True, nullable=False)
    name = db.Column(db.Unicode(20))
    gateway_uid = db.Column(db.Unicode(255))
    description = db.Column(db.Unicode(255))
    amount = db.Column(db.Numeric(8, 2), default=0)
    billing_interval = db.Column(db.Enum('daily', 'weekly', 'monthly',
                                         'yearly'),
                                 default='monthly')

    created_at = db.Column(db.DateTime, nullable=False, default=datetime.now)

    # relationships
    subscriptions = db.relation('Subscription',
                                backref=db.backref('plan',
                                                   lazy='joined',
                                                   uselist=False))

    @property
    def interval_name(self):
        if self.billing_interval == 'monthly':
            return 'month'
Exemplo n.º 6
0
class GoCardlessPayment(db.Model):
    __tablename__ = 'gocardless_payment'

    id = db.Column(db.Integer(11), primary_key=True, nullable=False)
    invoice_id = db.Column(db.Integer(11),
                           db.ForeignKey('invoice.id'),
                           nullable=False)
    user_id = db.Column(db.Integer(11),
                        db.ForeignKey('user.id'),
                        nullable=False)
    payment_id = db.Column(db.Integer(11),
                           db.ForeignKey('payment.id'),
                           nullable=True)
    amount = db.Column(db.Numeric(8, 2), default=0)
    reference = db.Column(db.Unicode(100), nullable=False)
    state = db.Column(db.Unicode(20), default=u'initialized')
    resource_id = db.Column(db.Unicode(100), nullable=True)
    resource_uri = db.Column(db.Unicode(255), nullable=True)
    error_message = db.Column(db.Unicode(255), nullable=True)

    created_at = db.Column(db.DateTime(), nullable=False, default=datetime.now)

    def create_payment_object(self):
        """Create related payment object"""
        payment = Payment()
        payment.invoice_id = self.invoice_id
        payment.date = datetime.now()
        payment.currency_code = self.invoice.currency_code
        payment.amount = self.amount
        payment.method = 'gocardless'
        payment.description = 'Direct debit payment'

        db.session.add(payment)
        db.session.commit()

        return payment
Exemplo n.º 7
0
class InvoiceItem(db.Model):
    __tablename__ = 'invoice_item'

    id = db.Column(u'id', db.BigInteger, primary_key=True, nullable=False)
    invoice_id = db.Column(u'invoice_id', db.BigInteger,
                           db.ForeignKey('invoice.id'))
    type_id = db.Column(u'type_id', db.BigInteger,
                        db.ForeignKey('invoice_item_type.id'))
    tax_rate_id = db.Column(u'tax_rate_id', db.BigInteger,
                            db.ForeignKey('tax_rate.id'))

    description = db.Column(u'description', db.String)

    quantity = db.Column(u'quantity', db.Numeric(8, 2))
    price = db.Column(u'price', db.Numeric(8, 2))
    tax = db.Column(u'tax', db.Numeric(8, 2))
    total = db.Column(u'total', db.Numeric(8, 2))

    sort_order = db.Column(u'sort_order', db.Integer, default=0)

    #relation definitions
    invoice_item_type = db.relation(
        'InvoiceItemType',
        primaryjoin='InvoiceItem.type_id==InvoiceItemType.id')
    invoice = db.relation('Invoice',
                          primaryjoin='InvoiceItem.invoice_id==Invoice.id',
                          backref=db.backref('invoice_items', lazy='dyanmic'))
    tax_rate = db.relation('TaxRate',
                           primaryjoin='InvoiceItem.tax_rate_id==TaxRate.id')

    def should_render_field(self, name):
        """Returns True if the field should be rendered in the item list on the
        invoice"""
        no_render = {
            'Comment': ['quantity', 'price', 'tax', 'total'],
            'VAT': ['quantity']
        }

        type_name = self.invoice_item_type.name
        if not type_name in no_render:
            return True

        if name in no_render[type_name]:
            return False

        return True

    def quantity_str(self):
        """Returns a more sanely formatted quantity string, taking into account
        the type of the item that we're rendering"""
        if self.invoice_item_type.name == 'Hour':
            mins = self.quantity * 60
            hours = 0
            while mins >= 60:
                mins -= 60
                hours += 1
            if mins == 0:
                return hours
            else:
                mins = int(round(mins))
                mins = str(mins).zfill(2)
                return '%s:%s' % (hours, mins)
        return int(self.quantity) if math.fmod(self.quantity,
                                               1) == 0 else self.quantity

    def update_totals(self):
        """Recalculate the tax and the totals for this invoice"""
        if self.tax_rate_id > 0:
            rate = 0
            if self.id:
                rate = self.tax_rate.rate
            else:
                from nano.models import Invoice, TaxRate
                rate = TaxRate.query.get(self.tax_rate_id).rate
            self.tax = self.quantity * float(self.price) * float(rate) / 100
        else:
            self.tax = 0

        self.total = self.quantity * float(self.price)

        return self.tax, self.total

    def serialize(self):
        """Serialize the invoice structure so that it can be used for JSON"""
        d = model_to_dict(self)
        d['InvoiceItemType'] = self.invoice_item_type.serialize()
        if self.tax_rate:
            d['TaxRate'] = self.tax_rate.serialize()
        return d
Exemplo n.º 8
0
class Invoice(db.Model):
    __tablename__ = 'invoice'
    
    DATE_FORMAT = '%a %b %d %Y'

    id                  = db.Column(u'id', db.Integer, primary_key=True, nullable=False)
    user_id             = db.Column(u'user_id', db.Integer, db.ForeignKey('user.id')) 
    contact_id          = db.Column(u'contact_id', db.Integer, db.ForeignKey('contact.id')) 
    payment_term_id     = db.Column(u'payment_term_id', db.Integer, db.ForeignKey('payment_term.id')) 
    status              = db.Column(u'status', db.String(255))
    reference           = db.Column(u'reference', db.String(255))
    po_reference        = db.Column(u'po_reference', db.String(255))
    currency_code       = db.Column(u'currency_code', db.String(5))
    date_issued         = db.Column(u'date_issued', db.DateTime)
    due_date            = db.Column(u'due_date', db.DateTime)
    written_off_date    = db.Column(u'written_off_date', db.DateTime)
    sub_total           = db.Column(u'sub_total', db.Numeric(8, 2))
    tax                 = db.Column(u'tax', db.Numeric(8, 2))
    total               = db.Column(u'total', db.Numeric(8, 2))
    payment_status      = db.Column(u'payment_status', db.Unicode(10), default=u'unpaid')

    updated_at          = db.Column(u'updated_at', db.DateTime, nullable=False, default=get_current_time())
    created_at          = db.Column(u'created_at', db.DateTime, nullable=False, default=get_current_time())

    # relations
    user                = db.relation('User', primaryjoin='Invoice.user_id==User.id', backref='invoices')
    contact             = db.relation('Contact', primaryjoin='Invoice.contact_id==Contact.id', backref='invoices')
    payment_term        = db.relation('PaymentTerm', primaryjoin='Invoice.payment_term_id==PaymentTerm.id')
    invoice_link        = db.relation('InvoiceLink', backref=db.backref('invoice', uselist=False, lazy='joined'))
    gocardless_payments = db.relation('GoCardlessPayment', backref=db.backref('invoice', uselist=False, lazy='joined'))
    stripe_payments     = db.relation('StripePayment', backref=db.backref('invoice', uselist=False, lazy='joined'))
    
    @classmethod
    def next_invoice_number(cls, user):
        """Next the next invoice number for the user"""
        cur_max = cls.query.filter_by(user_id=user.id).count()
        cur_max += 1

        return str(cur_max)

    @property
    def due_date_nice(self):
        return self.due_date.strftime(self.DATE_FORMAT)
    
    @property
    def date_issued_nice(self):
        return self.date_issued.strftime(self.DATE_FORMAT)

    def next_item_sort_order(self):
        """Generate the next number for the invoice item's sort order"""
        from nano.models import InvoiceItem
        total = InvoiceItem.query.filter_by(invoice_id=self.id).count()
        return total+1
    
    def update_totals(self, commit=False):
        """Update total and tax"""
        sub_total = 0.0
        tax = 0.0
        for item in self.invoice_items:
            sub_total += float(item.total if item.total else 0)
            tax += float(item.tax if item.tax else 0)

        self.tax = tax
        self.sub_total = sub_total
        self.total = float(self.tax) + float(self.sub_total)

        if commit:
            db.session.add(self)
            db.session.commit()
        return True
    
    def serialize(self):
        d = model_to_dict(self)
        d['InvoiceItems'] = [item.serialize() for item in self.invoice_items] 
        return d
    
    def update_payment_status(self):
        """Returns true if the amount has been paid"""
        payments = Payment.query.filter_by(invoice_id=self.id).all()
        total = 0.0
        for payment in payments:
            total += float(payment.amount)

        if total >= self.total:
            self.payment_status = u'paid'
        else:
            self.payment_status = u'unpaid'

        db.session.add(self)
        db.session.commit()

        return False

    def get_status(self):
        if self.status == 'draft':
            return 'draft'
        if self.status == 'saved':
            paid = True if self.payment_status == 'paid' else False
            if paid:
                return 'paid'
            if self.due_date <= datetime.now():
                return 'overdue'
            else:
                return 'saved'

    def __json__(self):
        return json_dumps(self.serialize())