class Currency(db.Model): __tablename__ = 'currency' #column definitions id = db.Column(u'id', db.BigInteger, primary_key=True, nullable=False) code = db.Column(u'code', db.String(length=6)) name = db.Column(u'name', db.String(length=50)) symbol = db.Column(u'symbol', db.String(length=6)) updated_at = db.Column(u'updated_at', db.DateTime(), nullable=False) created_at = db.Column(u'created_at', db.DateTime(), nullable=False)
class CompanyType(db.Model): __tablename__ = 'company_type' #column definitions id = db.Column(u'id', db.BigInteger, primary_key=True, nullable=False) name = db.Column(u'name', db.String(length=100)) updated_at = db.Column(u'updated_at', db.DateTime, nullable=False) created_at = db.Column(u'created_at', db.DateTime, nullable=False)
class PaymentTerm(db.Model): __tablename__ = 'payment_term' #column definitions id = db.Column(u'id', db.BigInteger, primary_key=True, nullable=False) days = db.Column(u'days', db.Integer) name = db.Column(u'name', db.String(length=50)) updated_at = db.Column(u'updated_at', db.DateTime, nullable=False) created_at = db.Column(u'created_at', db.DateTime, nullable=False)
class InvoiceItemType(db.Model): __tablename__ = 'invoice_item_type' #column definitions id = db.Column(u'id', db.Integer, primary_key=True, nullable=False) name = db.Column(u'name', db.String(length=20)) name_plural = db.Column(u'name_plural', db.String(length=20)) sort_order = db.Column(u'sort_order', db.Integer) updated_at = db.Column(u'updated_at', db.DateTime, nullable=False) created_at = db.Column(u'created_at', db.DateTime, nullable=False) def name_pluralized(self, quantity): if quantity > 1: return self.name_plural else: return self.name def serialize(self): return model_to_dict(self)
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)
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())
class Contact(db.Model): __tablename__ = 'contact' #column definitions 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'), nullable=False) first_name = db.Column(u'first_name', db.String(length=255)) last_name = db.Column(u'last_name', db.String(length=255)) organisation = db.Column(u'organisation', db.String(length=255)) email_address = db.Column(u'email_address', db.String(length=255)) billing_email_address = db.Column(u'billing_email_address', db.String(length=255)) address_line1 = db.Column(u'address_line1', db.String(length=255)) address_line2 = db.Column(u'address_line2', db.String(length=255)) town = db.Column(u'town', db.String(length=255)) city = db.Column(u'city', db.String(length=255)) county = db.Column(u'county', db.String(length=255)) country = db.Column(u'country', db.String(length=2)) post_code = db.Column(u'post_code', db.String(length=15)) created_at = db.Column(u'created_at', db.DateTime, nullable=False, default=get_current_time()) updated_at = db.Column(u'updated_at', db.DateTime, nullable=False, default=get_current_time()) #relation definitions user = db.relation('User', primaryjoin='Contact.user_id==User.id', backref='contacts') def full_name(self): return self.first_name + ' ' + self.last_name
class File(db.Model): __tablename__ = 'file' id = db.Column(db.Integer, primary_key=True) filename = db.Column(db.String(255)) filesize = db.Column(db.Integer(20)) extension = db.Column(db.String(25)) mimetype = db.Column(db.String(255)) location = db.Column(db.String(255)) width = db.Column(db.Integer(11)) height = db.Column(db.Integer(11)) hash = db.Column(db.String(40)) # times created_at = db.Column(db.DateTime, default=get_current_time()) updated_at = db.Column(db.DateTime, default=get_current_time()) def is_image(self): extensions = ['jpg', 'jpeg', 'png', 'bmp', 'gif'] if self.extension in extensions: return True return False def get_web_url(self, w=80, h=80, method='normal'): return self.location.replace(current_app.config['UPLOAD_DIR'] + '/', '') @classmethod def save_uploaded_file(cls, fs, filename=None): # make a new folder for the image now = datetime.now() _uuid = uuid.uuid4().hex path = '%s/%s/%s/%s/%s/%s' % (now.year, now.month, now.day, _uuid[:3], _uuid[3:6], _uuid[6:]) base_path = os.path.join(current_app.config['UPLOAD_DIR'], path) os.makedirs(base_path) name = secure_filename(fs.filename) if filename is None else filename save_path = os.path.join(base_path, name) fs.save(save_path) # get hash of file contents f1 = open(save_path, 'rb') sha1sum = hashlib.sha1(f1.read()).hexdigest() f1.close() obj = File() obj.filename = fs.filename obj.filesize = os.path.getsize(save_path) obj.mimetype = fs.mimetype obj.extension = fs.filename.rsplit('.', 1)[1] obj.location = save_path obj.hash = sha1sum return obj @classmethod def create_from_file(cls, oldpath, filename=None): now = datetime.now() _uuid = uuid.uuid4().hex path = '%s/%s/%s/%s/%s/%s' % (now.year, now.month, now.day, _uuid[:3], _uuid[3:6], _uuid[6:]) base_path = os.path.join(current_app.config['UPLOAD_DIR'], path) os.makedirs(base_path) save_path = os.path.join(base_path, filename) shutil.copy(oldpath, save_path) # get hash of file contents f1 = open(save_path, 'rb') sha1sum = hashlib.sha1(f1.read()).hexdigest() f1.close() obj = File() obj.filename = filename obj.filesize = os.path.getsize(save_path) obj.mimetype = mimetypes.guess_type(oldpath)[0] obj.extension = filename.rsplit('.', 1)[1] obj.location = save_path obj.hash = sha1sum return obj