<commit_before>import cbpos

import cbpos.mod.base.models.common as common

import cbpos.mod.currency.controllers as currency

from cbpos.mod.stock.models.product import Product
from cbpos.mod.sales.models.ticketline import TicketLine

from sqlalchemy import func, Table, Column, Integer, String, Float, Boolean, Enum, DateTime, MetaData, ForeignKey
from sqlalchemy.orm import relationship, backref
from sqlalchemy.ext.hybrid import hybrid_property, hybrid_method, Comparator

class Ticket(cbpos.database.Base, common.Item):
    __tablename__ = 'tickets'

    id = Column(Integer, primary_key=True)
    date_open = Column(DateTime, nullable=True, default=func.current_timestamp())
    date_close = Column(DateTime, nullable=True)
    payment_method = Column(Enum('cash', 'cheque', 'voucher', 'card', 'free', 'debt'), nullable=True)
    date_paid = Column(DateTime, nullable=True)
    comment = Column(String(255), nullable=True)
    discount = Column(Float, nullable=False, default=0)
    currency_id = Column(Integer, ForeignKey('currencies.id'))
    customer_id = Column(Integer, ForeignKey('customers.id'), nullable=True)
    user_id = Column(Integer, ForeignKey('users.id'), nullable=True)

    currency = relationship("Currency", backref="tickets")
    customer = relationship("Customer", backref="tickets")
    user = relationship("User", backref="tickets")

    @hybrid_property
    def paid(self):
        return self.date_paid is not None

    @paid.setter
    def paid(self, value):
        if value:
            self.date_paid = func.now()
        else:
            self.date_paid = None

    @paid.expression
    def paid(cls):
        return cls.date_paid != None

    def pay(self, method, paid=True):
        self.payment_method = method
        self.paid = paid
        session = cbpos.database.session()
        session.commit()
    
    @hybrid_property
    def closed(self):
        return self.date_close is not None

    @closed.setter
    def closed(self, value):
        session = cbpos.database.session()
        if value:
            self.date_close = func.now()
            result = session.query(Product, TicketLine.amount).filter((TicketLine.ticket == self) & \
                                                        (TicketLine.product_id == Product.id) & \
                                                        Product.in_stock).all()
            for p, amount in result:
                p.quantity_out(amount)
        else:
            self.date_close = None
        session.commit()

    @closed.expression
    def closed(cls):
        return cls.date_close != None

    @hybrid_property
    def total(self):
        session = cbpos.database.session()
        total = session.query(func.sum(TicketLine.total)).filter(TicketLine.ticket == self).one()[0]
        total = float(total)
        return total*(1-self.discount) if total is not None else 0
    
    @hybrid_property
    def display(self):
        # TODO see if it is a good idea to use another way to number tickets..
        """
        base_36 = str_base(self.id, 36).upper()
        display = ''
        sep = 3
        format_str = '{:0>'+str(sep)+'}'
        for i in range(len(base_36), 0, -sep):<commit_msg>Fixed bug with empty tickets<commit_after>import cbpos

import cbpos.mod.base.models.common as common

import cbpos.mod.currency.controllers as currency

from cbpos.mod.stock.models.product import Product
from cbpos.mod.sales.models.ticketline import TicketLine

from sqlalchemy import func, Table, Column, Integer, String, Float, Boolean, Enum, DateTime, MetaData, ForeignKey
from sqlalchemy.orm import relationship, backref
from sqlalchemy.ext.hybrid import hybrid_property, hybrid_method, Comparator

class Ticket(cbpos.database.Base, common.Item):
    __tablename__ = 'tickets'

    id = Column(Integer, primary_key=True)
    date_open = Column(DateTime, nullable=True, default=func.current_timestamp())
    date_close = Column(DateTime, nullable=True)
    payment_method = Column(Enum('cash', 'cheque', 'voucher', 'card', 'free', 'debt'), nullable=True)
    date_paid = Column(DateTime, nullable=True)
    comment = Column(String(255), nullable=True)
    discount = Column(Float, nullable=False, default=0)
    currency_id = Column(Integer, ForeignKey('currencies.id'))
    customer_id = Column(Integer, ForeignKey('customers.id'), nullable=True)
    user_id = Column(Integer, ForeignKey('users.id'), nullable=True)

    currency = relationship("Currency", backref="tickets")
    customer = relationship("Customer", backref="tickets")
    user = relationship("User", backref="tickets")

    @hybrid_property
    def paid(self):
        return self.date_paid is not None

    @paid.setter
    def paid(self, value):
        if value:
            self.date_paid = func.now()
        else:
            self.date_paid = None

    @paid.expression
    def paid(cls):
        return cls.date_paid != None

    def pay(self, method, paid=True):
        self.payment_method = method
        self.paid = paid
        session = cbpos.database.session()
        session.commit()
    
    @hybrid_property
    def closed(self):
        return self.date_close is not None

    @closed.setter
    def closed(self, value):
        session = cbpos.database.session()
        if value:
            self.date_close = func.now()
            result = session.query(Product, TicketLine.amount).filter((TicketLine.ticket == self) & \
                                                        (TicketLine.product_id == Product.id) & \
                                                        Product.in_stock).all()
            for p, amount in result:
                p.quantity_out(amount)
        else:
            self.date_close = None
        session.commit()

    @closed.expression
    def closed(cls):
        return cls.date_close != None

    @hybrid_property
    def total(self):
        session = cbpos.database.session()
        total = session.query(func.sum(TicketLine.total)).filter(TicketLine.ticket == self).one()[0]
        return float(total)*(1-self.discount) if total is not None else 0
    
    @hybrid_property
    def display(self):
        # TODO see if it is a good idea to use another way to number tickets..
        """
        base_36 = str_base(self.id, 36).upper()
        display = ''
        sep = 3
        format_str = '{:0>'+str(sep)+'}'
        for i in range(len(base_36), 0, -sep):
{'fraction_non_alphanumeric': 0.11187392728974879, 'fraction_numerical': 0.004992978623810267, 'mean_word_length': 2.6296715741789356, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 8, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '181960', 'n_tokens_mistral': 1886, 'n_tokens_neox': 1822, 'n_words': 449}