Example #1
0
class Entity(db.Model, TimestampMixin):
    """
    Base class for entity submodels.

    An entity is a model that has two names, one required and one optional, and
    a series of address, phone, emails and extra fields.
    Models to be suitable to this description are for example: User, Employee,
    Supplier, Customer, Contact, Branch, etc.
    """
    __tablename__ = 'entity'

    id = db.Column(db.Integer, primary_key=True)
    _name_1 = db.Column('name_1', db.Unicode, nullable=False)
    _name_2 = db.Column('name_2', db.Unicode)
    entity_type = db.Column(db.Unicode(50))
    notes = db.Column(db.UnicodeText)
    __mapper_args__ = {'polymorphic_on': entity_type}

    @property
    def full_name(self):
        ln = " {0}".format(self._name_2) if self._name_2 else ""
        return "{0}{1}".format(self._name_1, ln)

    def __repr__(self):
        return "<{0} '{1}'>".format(self.__class__.__name__, self.full_name)
Example #2
0
class FiscalData(db.Model):
    __tablename__ = 'fiscal_data'

    FISCAL_CONSUMIDOR_FINAL = 'CONSUMIDOR FINAL'
    FISCAL_RESPONSABLE_INSCRIPTO = 'RESPONSABLE INSCRIPTO'
    FISCAL_EXCENTO = 'EXCENTO'
    FISCAL_MONOTRIBUTO = 'MONOTRIBUTO'

    _fiscal_types = {
        FISCAL_CONSUMIDOR_FINAL: 'Consumidor Final',
        FISCAL_RESPONSABLE_INSCRIPTO: 'Responsable Inscripto',
        FISCAL_EXCENTO: 'Excento',
        FISCAL_MONOTRIBUTO: 'Monotributo',
    }

    id = db.Column(db.Integer, primary_key=True)
    cuit = db.Column(db.Unicode(13))
    fiscal_type = db.Column(db.Enum(*_fiscal_types.keys(), name='fiscal_type'),
                            default=FISCAL_CONSUMIDOR_FINAL)
    iibb = db.Column(db.Unicode, nullable=True)

    @property
    def needs_cuit(self):
        return self.fiscal_type not in (self.FISCAL_CONSUMIDOR_FINAL, )

    @property
    def type(self):
        return self._fiscal_types.get(self.fiscal_type)

    def __repr__(self):
        return "<FiscalData '{} {}' of '{}'>".format(
            self.type,
            self.cuit,
            self.entity.full_name,
        )
Example #3
0
class Product(db.Model):
    __tablename__ = 'product'
    id = db.Column(db.Integer, primary_key=True)
    code = db.Column(db.Unicode(14), nullable=False, unique=True)
    description = db.Column(db.Unicode(40), nullable=False)
    brand = db.Column(db.UnicodeText)

    suppliers = association_proxy('suppliers_info', 'supplier')
Example #4
0
File: misc.py Project: coyotevz/nbx
class Email(RefEntityMixin, db.Model):
    "Model to store entity's email information"
    __tablename__ = 'email'
    id = db.Column(db.Integer, primary_key=True)
    email_type = db.Column(db.Unicode(50))
    email = db.Column(db.Unicode(50), nullable=False)

    def __str__(self):
        retval = self.email_type + ': ' if self.email_type else ''
        retval += self.email
        return retval
Example #5
0
class Payment(db.Model):
    __tablname__ = 'payment'
    id = db.Column(db.Integer, primary_key=True)
    amount = db.Column(db.Numeric(10, 2), nullable=False)
    date = db.Column(db.Date, nullable=False)
    notes = db.Column(db.UnicodeText)

    documents = association_proxy('document_payment', 'document')

    def add_documents(self, documents):
        for document in documents:
            document.add_payment(self)
Example #6
0
File: misc.py Project: coyotevz/nbx
class Phone(RefEntityMixin, db.Model):
    "Model to store entity's phone information"
    __tablename__ = 'phone'

    id = db.Column(db.Integer, primary_key=True)
    phone_type = db.Column(db.Unicode)
    number = db.Column(db.Unicode, nullable=False)

    def __str__(self):
        retval = self.phone_type + ': ' if self.phone_type else ''
        retval += self.number
        return retval
Example #7
0
File: misc.py Project: coyotevz/nbx
class TimestampMixin(object):

    created = db.Column(db.DateTime, default=datetime.now)
    modified = db.Column(db.DateTime,
                         default=datetime.now,
                         onupdate=datetime.now)

    @staticmethod
    def stamp_modified(mapper, connection, target):
        if db.object_session(target).is_modified(target):
            target.modified = datetime.now()

    @classmethod
    def __declare_last__(cls):
        db.event.listen(cls, 'before_update', cls.stamp_modified)
Example #8
0
class SupplierContact(db.Model):
    __tablename__ = 'supplier_contact'
    supplier_id = db.Column(db.Integer,
                            db.ForeignKey('supplier.supplier_id'),
                            primary_key=True)
    contact_id = db.Column(db.Integer,
                           db.ForeignKey('contact.contact_id'),
                           primary_key=True)
    role = db.Column(db.Unicode)

    contact = db.relationship('Contact',
                              backref='supplier_contacts',
                              lazy='joined')

    def __init__(self, contact, role):
        self.contact = contact
        self.role = role
Example #9
0
class DocumentPayment(db.Model):
    __tablename__ = 'document_payment'
    document_id = db.Column(db.Integer,
                            db.ForeignKey('document.id'),
                            primary_key=True)
    payment_id = db.Column(db.Integer,
                           db.ForeignKey('payment.id'),
                           primary_key=True)
    amount = db.Column(db.Numeric(10, 2), nullable=False)

    payment = db.relationship(Payment,
                              lazy='joined',
                              backref='document_payments')
    document = db.relationship('Document',
                               lazy='joined',
                               backref='document_payments')

    def __init__(self, payment, amount):
        self.payment = payment
        self.amount = amount
Example #10
0
class Comment(db.Model, TimestampMixin):
    __tablename__ = 'comment'
    id = db.Column(db.Integer, primary_key=True)
    comment = db.Column(db.UnicodeText, nullable=False)
    created_by_id = db.Column(db.Integer,
                              db.ForeignKey('user.user_id'),
                              nullable=False)
    created_by = db.relationship(
        'User',
        backref="comments_created",
        lazy='joined',
        primaryjoin='User.user_id==Comment.modified_by_id')
    modified_by_id = db.Column(db.Integer,
                               db.ForeignKey('user.user_id'),
                               nullable=False)
    modified_by = db.relationship(
        'User',
        backref='comments_modified',
        lazy='joined',
        primaryjoin='User.user_id==Comment.modified_by_id')
    supplier_id = db.Column(db.Integer,
                            db.ForeignKey('supplier.supplier_id'),
                            nullable=False)
    supplier = db.relationship('Supplier', backref='comments', lazy='joined')
Example #11
0
class Contact(Entity):
    __tablename__ = 'contact'
    __mapper_args__ = {'polymorphic_identity': 'contact'}
    contact_id = db.Column(db.Integer,
                           db.ForeignKey('entity.id'),
                           primary_key=True)

    first_name = Entity._name_1
    last_name = Entity._name_2

    suppliers = association_proxy('supplier_contacts', 'supplier')

    @property
    def full_name(self):
        return u' '.join([self.first_name, self.last_name])
Example #12
0
class ProductSupplierInfo(db.Model):
    __tablename__ = 'productsupplier_info'
    supplier_id = db.Column(db.Integer, db.ForeignKey('supplier.supplier_id'), primary_key=True)
    supplier = db.relationship('Supplier', backref='products_info', lazy='joined')

    product_id = db.Column(db.Integer, db.ForeignKey('product.id'), primary_key=True)
    product = db.relationship('Product', backref='suppliers_info', lazy='joined')

    code = db.Column(db.Unicode(80))
    description = db.Column(db.Unicode)
    base_cost = db.Column(db.Numeric(10, 2))
    minimum_purchase = db.Column(db.Integer, default=1)
Example #13
0
class PurchaseOrderItem(db.Model):
    __tablename__ = 'purchaseorder_item'

    id = db.Column(db.Integer, primary_key=True)
    sku = db.Column(db.Unicode(40))
    description = db.Column(db.UnicodeText)
    quantity = db.Column(db.Integer, default=0)
    quantity_received = db.Column(db.Integer, default=0)
    quantity_returned = db.Column(db.Integer, default=0)

    order_id = db.Column(db.Integer,
                         db.ForeignKey('purchaseorder.id'),
                         nullable=False)
    order = db.relationship('PurchaseOrder', backref='items')

    @property
    def pending_quantity(self):
        return self.quantity - self.quantity_received
Example #14
0
File: misc.py Project: coyotevz/nbx
class Address(RefEntityMixin, db.Model):
    "Stores entity's addresses information"
    __tablename__ = 'address'

    id = db.Column(db.Integer, primary_key=True)
    street = db.Column(db.Unicode(64), nullable=False)
    streetnumber = db.Column(db.Unicode(64))
    city = db.Column(db.Unicode(64))
    province = db.Column(db.Unicode(32), nullable=False)
    zip_code = db.Column(db.Unicode(32))
    address_type = db.Column(db.Unicode)

    def __str__(self):
        retval = self.street
        retval += " %s" % self.streetnumber if self.streetnumber else 'S/N'
        if self.city:
            retval += ", %s" % self.city
        retval += ", %s" % self.province
        if self.postal_code:
            retval += " (%s)" % self.postal_code
        return retval
Example #15
0
File: misc.py Project: coyotevz/nbx
 def entity_id(cls):
     return db.Column('entity_id',
                      db.Integer,
                      db.ForeignKey('entity.id'),
                      nullable=False)
Example #16
0
class Supplier(Entity):
    __tablename__ = 'supplier'
    __mapper_args__ = {'polymorphic_identity': 'supplier'}

    supplier_id = db.Column(db.Integer,
                            db.ForeignKey('entity.id'),
                            primary_key=True)
    rz = Entity._name_1
    name = Entity._name_2
    web = db.Column(db.Unicode, default=None)

    fiscal_data_id = db.Column(db.Integer, db.ForeignKey('fiscal_data.id'))
    fiscal_data = db.relationship(FiscalData,
                                  backref=db.backref('entity', uselist=False))

    payment_term = db.Column(db.Integer)  # in days
    leap_time = db.Column(db.Integer)  # in days
    delivery_included = db.Column(db.Boolean)

    supplier_contacts = db.relationship('SupplierContact',
                                        cascade='all, delete-orphan',
                                        backref='supplier')
    contacts = association_proxy('supplier_contacts', 'contact')

    debt = db.Column(db.Numeric(10, 2))
    expired = db.Column(db.Numeric(10, 2))
    expiration_date = db.Column(db.DateTime, default=None)

    #: 'bank_accounts' attribute added by BankAccount.supplier relation
    #: 'orders' attribute added by PurchaseOrder.supplier relation
    #: 'documents' attribute added by Document.supplier relation

    #: Inherited from Entity
    #: - address (collection)
    #: - email (collection)
    #: - phone (collection)
    #: - extra field (collection)

    #    products = association_proxy('products_info', 'product')

    def add_contact(self, contact, role):
        self.supplier_contacts.append(SupplierContact(contact, role))


#    def add_product(self, product, **kwargs):
#        self.products_info.append(ProductSupplierInfo(product=product, **kwargs))

    @property
    def full_name(self):
        n = " ({0})".format(self.name) if self.name else ''
        return "{0}{1}".format(self.rz, n)

    def _update_expiration_date(self):
        doc = self.documents\
                .filter(Document.doc_status.in_([Document.STATUS_PENDING,
                                                 Document.STATUS_EXPIRED]))\
                .order_by(Document.expiration_date.asc())\
                .first()
        if doc:
            self.expiration_date = doc.expiration_date
        else:
            self.expiration_date = None
Example #17
0
class PurchaseOrder(db.Model, TimestampMixin):
    __tablename__ = 'purchaseorder'

    STATUS_CANCELLED = 'STATUS_CANCELLED'
    STATUS_QUOTING = 'STATUS_QUOTING'
    STATUS_PENDING = 'STATUS_PENDING'
    STATUS_PARTIAL = 'STATUS_PARTIAL'
    STATUS_CONFIRMED = 'STATUS_CONFIRMED'
    STATUS_COMPLETED = 'STATUS_COMPLETED'
    STATUS_DRAFT = 'STATUS_DRAFT'

    _po_status = {
        STATUS_CANCELLED: 'Cancelada',
        STATUS_QUOTING: 'Valorizando',
        STATUS_PENDING: 'Pendiente',
        STATUS_PARTIAL: 'Parcial',
        STATUS_CONFIRMED: 'Confirmada',
        STATUS_COMPLETED: 'Completa',
        STATUS_DRAFT: 'Borrador',
    }

    METHOD_EMAIL = 'METHOD_EMAIL'
    METHOD_FAX = 'METHOD_FAX'
    METHOD_PHONE = 'METHOD_PHONE'
    METHOD_PERSONALLY = 'METHOD_PERSONALLY'

    _po_method = {
        METHOD_EMAIL: 'Correo Electrónico',
        METHOD_FAX: 'Fax',
        METHOD_PHONE: 'Telefónico',
        METHOD_PERSONALLY: 'Personalmente',
    }

    id = db.Column(db.Integer, primary_key=True)
    point_sale = db.Column(db.Integer, nullable=False)
    number = db.Column(db.Integer, nullable=False)
    po_status = db.Column(db.Enum(*_po_status.keys(), name='po_status'),
                          default=STATUS_DRAFT)
    po_method = db.Column(db.Enum(*_po_method.keys(), name='po_method'),
                          default=None)
    notes = db.Column(db.UnicodeText)

    open_date = db.Column(db.Date)
    confirm_date = db.Column(db.Date)
    receival_date = db.Column(db.Date)

    supplier_id = db.Column(db.Integer,
                            db.ForeignKey('supplier.supplier_id'),
                            nullable=False)
    supplier = db.relationship('Supplier', backref="orders")

    @property
    def status(self):
        return self._po_status[self.po_status]

    @property
    def method(self):
        return self._po_method[self.po_method]

    @property
    def full_desc(self):
        if self.point_sale == 0:
            return "Pedido 0-%04d-%08d" % (self.supplier_id, self.number)
        return "Pedido %04d-%08d" % (self.point_sale, self.number)
Example #18
0
class Document(db.Model, TimestampMixin):
    __tablename__ = 'document'

    TYPE_FACTURA_A = 'TYPE_FACTURA_A'
    TYPE_NOTA_CREDITO_A = 'TYPE_NOTA_CREDITO_A'
    TYPE_PRESUPUESTO = 'TYPE_PRESUPUESTO'

    _doc_type = {
        TYPE_FACTURA_A: 'Factura A',
        TYPE_NOTA_CREDITO_A: 'Nota de Crédito',
        TYPE_PRESUPUESTO: 'Presupuesto',
    }

    STATUS_PENDING = 'STATUS_PENDING'
    STATUS_EXPIRED = 'STATUS_EXPIRED'
    STATUS_PAID = 'STATUS_PAID'

    _doc_status = {
        STATUS_PENDING: 'Pendiente',
        STATUS_EXPIRED: 'Vencida',
        STATUS_PAID: 'Pagada',
    }

    id = db.Column(db.Integer, primary_key=True)
    doc_type = db.Column(db.Enum(*_doc_type.keys(), name='doc_type'),
                         default=TYPE_FACTURA_A)
    point_sale = db.Column(db.Integer, nullable=False)
    number = db.Column(db.Integer, nullable=False)
    total = db.Column(db.Numeric(10, 2), nullable=False)
    doc_status = db.Column(db.Enum(*_doc_status.keys(), name='doc_status'),
                           default=STATUS_PENDING)
    issue_date = db.Column(db.Date)
    expiration_date = db.Column(db.Date)
    notes = db.Column(db.UnicodeText)

    supplier_id = db.Column(db.Integer, db.ForeignKey('supplier.supplier_id'),
                            nullable=False)
    supplier = db.relationship('Supplier', backref=db.backref('documents',
                               order_by='Document.issue_date.asc()',
                               lazy='dynamic'))

    #: document_payments added by DocumentPayment.document relationship

    def add_payment(self, payment, amount=None):
        if amount is None:
            amount = min([payment.amount, self.balance])
        self.document_payments.append(DocumentPayment(payment, amount))

    @property
    def type(self):
        return self._doc_type.get(self.doc_type)

    @property
    def status(self):
        return self._doc_status.get(self.doc_status)

    @property
    def full_desc(self):
        return u"%s %04d-%08d" % (self.type, self.point_sale, self.number)

    @property
    def cancelled_date(self):
        if self.state in (self.STATUS_PENDING, self.STATUS_EXPIRED):
            return None
        return Payment.query.join('document_payment')\
                            .filter(DocumentPayment.document==self)\
                            .order_by(Payment.date.desc())[0].date

    @property
    def balance(self):
        paid = db.session.query(db.func.sum(DocumentPayment.amount))\
                         .filter(DocumentPayment.document==self).scalar()\
                         or Decimal(0)
        return self.total - paid

    def __repr__(self):
        return "<Document '{}' of '{}' ({})>".format(self.full_desc,
                                                     self.supplier.rz,
                                                     self.status)