Example #1
0
class TimeEntrySchema(colander.Schema):
    title = colander.SchemaNode(
        colander.String(),
        title=_("Title"),
        missing="",
    )
    tariff_uid = colander.SchemaNode(
        colander.String(),
        title=_("Tariff"),
        missing="",
        widget=selectable_tariff_radio,
    )
    created = colander.SchemaNode(
        LocalDateTime(),
        missing=None,
        widget=deform.widget.DateTimeInputWidget(time_options={'interval': 5}),
        title=_("Start time"))
    stop_time = colander.SchemaNode(
        LocalDateTime(),
        missing=None,
        widget=deform.widget.DateTimeInputWidget(time_options={'interval': 5}),
        title=_("End time"))
    bill_hours = colander.SchemaNode(colander.Decimal(),
                                     missing=None,
                                     title=_("Bill hours"))
Example #2
0
class TariffSchema(colander.Schema):
    title = colander.SchemaNode(colander.String(), title=_("Title"))
    price = colander.SchemaNode(colander.Decimal(),
                                title=_("Price"),
                                default=0)
    currency = colander.SchemaNode(colander.String(),
                                   title=_("Currency"),
                                   missing="")
    vat = colander.SchemaNode(colander.Int(),
                              title=_("VAT in integer percentage"),
                              default=0)
Example #3
0
class ProjectSchema(BaseOrgSchema):
    trello_board = colander.SchemaNode(
        colander.String(),
        title=_('Trello board '),
        widget=trello_board_widget,
        missing="",
    )
Example #4
0
class Project(Content):
    type_name = "Project"
    type_title = _("Project")
    add_permission = "Add %s" % type_name
    css_icon = "glyphicon glyphicon-road"
    blob_key = 'image'
    trello_board = ""

    def other_used_cards(self, task=None):
        other_tasks = filter(lambda t: t != task, self.tasks_with_card())
        return [t.trello_card for t in other_tasks]

    @property
    def used_cards(self):
        return self.other_used_cards()

    def tasks_with_card(self):
        return filter(lambda t: isinstance(t, Task) and t.trello_card, self.values())

    @property
    def image_data(self):
        blobs = IBlobs(self, None)
        if blobs:
            return blobs.formdata_dict(self.blob_key)
    @image_data.setter
    def image_data(self, value):
        IBlobs(self).create_from_formdata(self.blob_key, value)

    def consumed_hours(self, only_unbilled=True):
        pass
Example #5
0
class TaskSchema(colander.Schema):
    title = colander.SchemaNode(colander.String(), title=_("Title"))
    description = colander.SchemaNode(
        colander.String(),
        title=_("Description"),
        widget=deform.widget.TextAreaWidget(rows=3),
        missing="")
    trello_card = colander.SchemaNode(
        colander.String(),
        title=_('Trello card'),
        missing='',
        widget=trello_card_widget,
    )
    tags = colander.SchemaNode(colander.List(),
                               title=_("Tags or subjects"),
                               missing="",
                               widget=tagging_widget)
Example #6
0
class BaseOrgSchema(colander.Schema):
    title = colander.SchemaNode(colander.String(), title=_("Title"))
    description = colander.SchemaNode(
        colander.String(),
        title=_("Description"),
        widget=deform.widget.TextAreaWidget(rows=3),
        missing=u"")
    tags = colander.SchemaNode(colander.List(),
                               title=_("Tags or subjects"),
                               missing="",
                               widget=tagging_widget)
    image_data = colander.SchemaNode(deform.FileData(),
                                     missing=None,
                                     title=_(u"Image"),
                                     blob_key='image',
                                     validator=supported_thumbnail_mimetype,
                                     widget=FileAttachmentWidget())
Example #7
0
class Tariff(Base):
    type_name = "Tariff"
    type_title = _("Tariff")
    add_permission = "Add %s" % type_name
    css_icon = "glyphicon glyphicon-usd"
    title = ""
    price = None
    currency = ""
    vat = None
Example #8
0
def selectable_tariff_radio(node, kw):
    values = [('', _("N/A"))]
    context = kw['context']
    while context.__parent__:
        if IFolder.providedBy(context):
            for obj in context.values():
                if ITariff.providedBy(obj):
                    values.append((obj.uid, obj.title))
        context = context.__parent__
    return deform.widget.RadioChoiceWidget(values=values)
def selectable_tariff_radio(node, kw):
    values = [('', _("N/A"))]
    context = kw['context']
    while context.__parent__:
        if IFolder.providedBy(context):
            for obj in context.values():
                if ITariff.providedBy(obj):
                    values.append((obj.uid, obj.title))
        context = context.__parent__
    return deform.widget.RadioChoiceWidget(values=values)
Example #10
0
class Customer(Content):
    type_name = "Customer"
    type_title = _("Customer")
    add_permission = "Add %s" % type_name
    css_icon = "glyphicon glyphicon-briefcase"
    blob_key = 'image'

    @property
    def image_data(self):
        blobs = IBlobs(self, None)
        if blobs:
            return blobs.formdata_dict(self.blob_key)
    @image_data.setter
    def image_data(self, value):
        IBlobs(self).create_from_formdata(self.blob_key, value)
Example #11
0
class Task(Content):
    type_name = "Task"
    type_title = _("Task")
    add_permission = "Add %s" % type_name
    css_icon = "glyphicon glyphicon-tasks"
    trello_card = ''
    card_estimated_hours = None
    card_consumed_hours = None

    def get_time_entries(self, only_unbilled=False):
        results = []
        for obj in self.values():
            if ITimeEntry.providedBy(obj) and not (only_unbilled
                                                   and obj.billed):
                results.append(obj)
        return sorted(results, key=lambda x: x.start_time, reverse=True)

    @property
    def total_time(self):
        entries = self.get_time_entries()
        if entries:
            total = timedelta()
            for t in entries:
                total += t.timedelta
            return total

    @property
    def consumed_hours(self):
        # Returns time entry hours, rounded to full half hours
        return entries_to_consumed_hours(self.get_time_entries())

    @property
    def unbilled_hours(self):
        # Returns time entry hours, rounded to full half hours
        return entries_to_consumed_hours(
            self.get_time_entries(only_unbilled=True))

    def __str__(self):
        consumed_hours = self.consumed_hours
        return ''.join((
            self.card_estimated_hours
            and '({}) '.format(self.card_estimated_hours) or '',
            self.title,
            consumed_hours and ' [{}]'.format(consumed_hours) or '',
        ))
Example #12
0
class TimeEntry(Base):
    type_name = "TimeEntry"
    type_title = _("Time entry")
    add_permission = "Add %s" % type_name
    css_icon = "glyphicon glyphicon-time"
    title = ""
    tariff_uid = ""
    stop_time = None
    bill_hours = None
    billed = False

    @property
    def creator(self):
        return getattr(self, '__creator__', ())

    @creator.setter
    def creator(self, value):
        if value:
            self.__creator__ = PersistentList(value)
        else:
            if hasattr(self, '__creator__'):
                delattr(self, '__creator__')

    @property
    def start_time(self):
        #Map to created and set via created. It makes sense to link it to that
        #attribute and use that catalog index.
        return self.created

    @property
    def timedelta(self):
        # type: () -> timedelta
        if self.bill_hours:
            return timedelta(minutes=int(self.bill_hours * 60))
        if self.stop_time is None:
            # TODO Get real timezone, yo
            return datetime.now(utc) - self.start_time
        else:
            return self.stop_time - self.start_time