Пример #1
0
class MaintenanceFormWidget(ModelFormWidget):

    TITLE = 'Intervention'

    FIELDSETS = [(
        segment(
            ('maintenance_type', 'date'),
            'company',
            'quote_file',
            style=STYLE_SEGMENT_BASIC,
        ),
        segment(('contract', 'cost'), 'notes', style=STYLE_SEGMENT_BASIC),
    )]

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.contract.changed_event = self.__on_contract_change

    def __on_contract_change(self):
        """Update Company and Cost fields to reflect the selected Contract."""
        if self.contract.value:
            contract_pk = self.contract.value
            contract = MaintenanceContract.objects.get(pk=contract_pk)
            self.company.value = contract.company.pk
            self.cost.value = 0
        else:
            self.company.value = None
            self.cost.value = None
class PrivateInfoFormWidget(ModelFormWidget):
    """
    To be used as inline: `person` field missing
    """

    MODEL = PrivateInfo
    TITLE = 'Private Info'

    FIELDSETS = [
        # 'info:The information provided in the fields below is only shared with the HR department.',
        ('birthcountry', 'birthcity', 'citizenship'),
        segment(
            'h3:Documentation',
            ('iddoc', 'iddoc_number', 'iddoc_expiration'),
            ('nif', 'socialsecurity_number')
        ),
        segment(
            'h3:Health Insurance',
            ('has_health_insurance', 'health_insurance_start'),
        ),
        segment(
            'h3:Bank Information',
            'bank_info',
            'iban',
            css='secondary'
        ),
        'address',
        'curriculum_vitae',
    ]

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

        # some tweaks before migrating the model
        self.has_health_insurance.label = "Has insurance plan?"
        self.bank_info.label = ""
        self.iddoc.label = "ID Document"
        self.nif.label = "NIF"

    def __has_permissions(self):
        """Custom method to check authorizations since PyForms ModelForm
        only inherits the permissions system for inlines.
        Once this is fixed, the following methods should be cleaned up.
        """
        user = PyFormsMiddleware.user()
        return any([
            user.is_superuser,
            settings.PROFILE_HUMAN_RESOURCES in user.groups.all(),
        ])

    def has_view_permissions(self):
        return self.__has_permissions() or super().has_view_permissions()

    def has_update_permissions(self):
        return self.__has_permissions() or super().has_update_permissions()
Пример #3
0
class EquipmentEditForm(ResourceFormWidget):
    FIELDSETS = [
        ('name', 'location', 'category', '_new_category_btn'),
        {
            '1:Details': [(segment(
                'company',
                ('brand', 'product_number'),
                ('sn', 'an'),
                'sop',
                style=STYLE_SEGMENT_BASIC,
            ), 'req_access', 'access_req',
                           segment('url',
                                   'description',
                                   style=STYLE_SEGMENT_BASIC), 'managers')],
            '2:Status': [(
                segment(
                    ('acquisition_date', 'warranty'),
                    ('disposal_date', ' '),
                    'uses_external_booking',
                    'is_missing',
                    style=STYLE_SEGMENT_BASIC,
                ),
                segment('responsible', 'groups', style=STYLE_SEGMENT_BASIC),
            )],
            '3:Images': ['ImagesListWidget'],
            '4:Racks': ['EquipmentRackListWidget'],
            'Maintenance': [
                'h3:Interventions', 'MaintenanceListWidget',
                'MaintenanceContractInlineListWidget'
            ],
            'Notes': ['notes'],
        },
    ]

    INLINES = ResourceFormWidget.INLINES + [EquipmentRackListWidget]

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

        # FIXME how to add extra inline ???

        self._new_category_btn = ControlButton(
            label='<i class="plus icon"></i>',
            helptext='Add new category',
            default=self.__new_category_btn_evt,
            css='blue circular ui icon button',
        )

        self.notes.label = ''

    def __new_category_btn_evt(self):
        # FIXME the new value does not show up in the ComboBox
        EquipmentCategoryAddForm(title='Create a new equipment category')
Пример #4
0
class AuthorsAliasListWidget(ModelAdminWidget):
    """
    """
    UID = 'authors-alias'
    TITLE = 'Authors alias'

    MODEL = AuthorAlias

    ###########################################################################
    # ORQUESTRA CONFIGURATION

    LAYOUT_POSITION = conf.ORQUESTRA_HOME
    ORQUESTRA_MENU = 'left>PublicationsListWidget'
    ORQUESTRA_MENU_ORDER = 2
    ORQUESTRA_MENU_ICON = 'newspaper outline'
    #AUTHORIZED_GROUPS = ['superuser']

    ###########################################################################

    FIELDSETS = [segment(('name', 'person'))]

    LIST_FILTER = ['person']

    SEARCH_FIELDS = ['name__icontains', 'person__full_name__icontains']

    LIST_DISPLAY = ['name', 'person']

    @classmethod
    def has_permissions(cls, user):
        if user.is_superuser:
            return True

        return user.groups.filter(
            permissions__codename__in=['app_access_imp_pub']).exists()
class ContractCreateFormWidget(ModelFormWidget):

    FIELDSETS = [
        'h3:Identification',
        segment(('ref', 'supervisor'), ('person', 'warn_when_ending')),
        'h3:Contract conditions',
        segment(('start', 'months_duration', 'days_duration', 'end'),
                ('salary', ), ('socialsecurity_pay', 'socialsecurity_from'),
                ('socialsecurity_start', 'socialsecurity_end')),
        'h3:Function',
        segment('position', 'fellowship_ref', 'fellowship_type'),
        segment('description', 'notes', css='secondary'),
    ]

    READ_ONLY = ['end']

    # AUTHORIZED_GROUPS = ['superuser', settings.APP_PROFILE_HR_PEOPLE]

    @classmethod
    def has_permissions(cls, user):
        from .contracts_list import ContractsListWidget
        return ContractsListWidget.has_permissions(user)

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

        self.start.changed_event = self.__update_end_date
        self.months_duration.changed_event = self.__update_end_date
        self.days_duration.changed_event = self.__update_end_date

    def __update_end_date(self):
        try:
            days = 0 if not self.days_duration.value else self.days_duration.value
            self.end.value = (
                self.start.value +
                relativedelta(months=self.months_duration.value, days=days) -
                timedelta(days=1))
        except:
            self.end.value = ''

    def update_object_fields(self, obj):
        self.__update_end_date()
        obj.end = self.end.value
        res = super().update_object_fields(obj)
        return res
Пример #6
0
class SupplierFormAdmin(ModelFormWidget):

    MODEL = Supplier  #model to manage
    TITLE = 'Suppliers'  #title of the application

    #formset of the edit form
    FIELDSETS = [(segment(
        ('name', 'nif'),
        ('email', 'contact'),
        ('country', 'phone'),
    ),
                  segment('keywords', 'discounts', 'category',
                          ('_category', '_addcategory_btn')))]

    AUTHORIZED_GROUPS = ['superuser', settings.APP_PROFILE_ORDERS]

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

        self._addcategory_btn = ControlButton(
            '<i class="icon plus" ></i>Category',
            css='basic mini',
            field_css='five wide',
            label_visible=False,
            default=self.__create_new_category,
        )
        self._category = ControlText('New category',
                                     field_css='eleven wide',
                                     label_visible=False,
                                     visible=False)

    def __create_new_category(self):

        if self._category.visible is False:
            self._category.show()
            self._addcategory_btn.label = '<i class="icon file outline" ></i>Create'
            self._addcategory_btn.css = 'blue'
        else:
            self._category.hide()
            self._addcategory_btn.label = '<i class="icon plus" ></i>Category'
            self._addcategory_btn.css = 'basic mini'
            if self._category.value:
                obj, created = Category.objects.get_or_create(
                    name=self._category.value)
Пример #7
0
class MaintenanceContractFormWidget(ModelFormWidget):

    MODEL = MaintenanceContract

    LAYOUT_POSITION = conf.ORQUESTRA_NEW_TAB

    FIELDSETS = [(
        segment(('start_date', 'end_date'), 'contract_file'),
        segment('company', 'notes'),
    ), 'resources']

    @property
    def title(self):
        obj = self.model_object
        if obj is None:
            return ModelFormWidget.title.fget(self)
        else:
            return str(obj)

    @title.setter
    def title(self, value):
        ModelFormWidget.title.fset(self, value)
Пример #8
0
class ExpenseCodeListApp(ModelAdminWidget):

    TITLE = 'Expense codes'

    MODEL = ExpenseCode

    LIST_DISPLAY = ['number', 'type']

    FIELDSETS = [
        segment(
            # 'financeproject',  # not required if app used as Inline
            ('number', 'type')
        )
    ]

    # ORQUESTRA CONFIGURATION
    # =========================================================================
    LAYOUT_POSITION = conf.ORQUESTRA_HOME
    # =========================================================================

    AUTHORIZED_GROUPS = ['superuser', settings.PROFILE_LAB_ADMIN]

    def has_add_permissions(self):
        finance_project = self.parent_model.objects.get(pk=self.parent_pk)
        if finance_project.code == 'NO TRACK':
            return False
        else:
            return True

    def has_update_permissions(self, obj):
        if obj and obj.project.code == 'NO TRACK':
            return False
        else:
            return True

    def has_remove_permissions(self, obj):
        """Only superusers may delete these objects."""
        user = PyFormsMiddleware.user()
        return user.is_superuser
Пример #9
0
class FormEditApp(ModelFormWidget):
    MODEL = Form
    INLINES = [FormTypeFieldsApp]

    FIELDSETS = [
        no_columns('form_code', 'content_type', 'active'), 'form_title',
        'form_set',
        segment('FormTypeFieldsApp')
    ]

    AUTHORIZED_GROUPS = ['superuser']

    def get_readonly(self, default):
        if self.object_pk:
            return default + ['content_type']
        else:
            return default

    def autocomplete_search(self, queryset, keyword, control):

        if control == self.content_type:
            return queryset.filter(model__icontains=keyword)

        return super().autocomplete_search(queryset, keyword, control)
class HumanResourcesForm(ModelFormWidget):
    """
    The advanced version of the form should only be available to
    administrators.
    """
    LAYOUT_POSITION = conf.ORQUESTRA_NEW_TAB

    HAS_CANCEL_BTN_ON_EDIT = False
    CLOSE_ON_REMOVE        = True

    FIELDSETS = [
        no_columns('_privateinfo_btn', '_proposals_btn', '_contracts_btn', 'active'),
        ' ',
        'h3:PERSONAL INFORMATION',
        (
            segment(
                'full_name',
                ('first_name', 'last_name'),
                ('gender', 'birthday'),
                ('position', 'curriculum_vitae'),
                'biography',
                field_css='fourteen wide',
            ),
            segment(
                '_img',
                '_rotimg_btn',
                'img',
                field_style='max-width:330px;'
            )
        ),
        'h3:EDUCATION',
        segment('AcademicCareerInline'),
        'h3:CONTACT INFORMATION',
        segment(
            ('email', 'personal_email'),
            ('phone_number', 'phone_extension'),
            'emergency_contact',
            css='secondary'
        ),
        'h3:INSTITUTIONAL INFORMATION',
        segment(
            'InstitutionAffiliationInline',
            ('card_number', 'room'),
            'auth_user',
            css='secondary'
        ),
        'h3:GROUPS',
        segment('GroupsInline', css='blue'),
        'h3:AUTH GROUPS',
        segment('AuthGroupsInline', css='red')
    ]

    READ_ONLY = ['auth_user']

    INLINES = [
        AcademicCareerInline,
        InstitutionAffiliationInline,
        GroupsInline,
        AuthGroupsInline,
    ]

    AUTHORIZED_GROUPS = ['superuser']


    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

        if hasattr(self, 'active'):
            self.active.label_visible = False
            self.active.field_style = 'text-align: right;margin-top:5px;'
            self.active.field_css = 'two wide'

        self._rotimg_btn = ControlButton(
            '<i class="icon undo" ></i>Rotate',
            default=self.__rotimg_evt,
            label_visible=False,
            style='margin-top:5px;',
            field_style='text-align: right;',
            css='mini')

        self._img = ControlImg('Image', label_visible=False)

        self.img.changed_event = self.__update_image_evt

        ###############################################
        ## Human Resources related buttons
        ###############################################
        self._privateinfo_btn = ControlButton(
            '<i class="icon lock" ></i>Private info',
            default=self.__privateinfo_btn_evt,
            label_visible=False,
            css='basic red'
        )
        self._contracts_btn = ControlButton(
            '<i class="icon file alternate" ></i>Contracts',
            default=self.__contracts_btn_evt,
            label_visible=False,
            css='basic'
        )
        self._proposals_btn = ControlButton(
            '<i class="icon file alternate outline" ></i>Proposals',
            default=self.__proposals_btn_evt,
            label_visible=False,
            css='basic'
        )

        # Only show this buttons if the humanresources modules is installed.
        if not hr_module_installed:
            self._privateinfo_btn.hide()
            self._contracts_btn.hide()
            self._proposals_btn.hide()
        else:
            if self.model_object is None:
                self._contracts_btn.hide()
                self._proposals_btn.hide()
                self._privateinfo_btn.hide()

        if self.model_object is not None:
            self.__update_image_evt()

    @classmethod
    def has_permissions(cls, user):
        from .humanresources_list import HumanResourcesList
        return HumanResourcesList.has_permissions(user)

    def __update_image_evt(self):
        url = self.model_object.thumbnail_url(geometry_string='300x300')
        self._img.value = url + '?t=' + str(timezone.now().timestamp())

    def __rotimg_evt(self):
        delete(self.img.filepath, delete_file=False)
        im = Image.open(self.img.filepath)
        rot = im.rotate(90)
        rot.save(self.img.filepath)
        self.__update_image_evt()

    def __privateinfo_btn_evt(self):
        obj = self.model_object
        if obj:
            privateinfo = obj.get_privateinfo()
            app = PrivateInfoFormWidget(
                pk=privateinfo.pk,
                title=str(privateinfo),
                has_cancel_btn=False,
            )
            app.LAYOUT_POSITION = conf.ORQUESTRA_NEW_TAB

    def __proposals_btn_evt(self):
        obj = self.model_object
        if not obj:
            return

        app = ContractProposalsListWidget(
            parent_pk=obj.pk,
            parent_model=Person,
            has_cancel_btn=False,
        )
        app.LAYOUT_POSITION = conf.ORQUESTRA_NEW_TAB

    def __contracts_btn_evt(self):
        obj = self.model_object
        if not obj:
            return

        app = ContractsListWidget(
            parent_pk=obj.pk,
            parent_model=Person,
            has_cancel_btn=False,
        )
        app.LAYOUT_POSITION = conf.ORQUESTRA_NEW_TAB

    @property
    def title(self):
        obj = self.model_object
        if obj is None:
            return ModelFormWidget.title.fget(self)
        else:
            return "Person: {0}".format(obj.name)

    @title.setter
    def title(self, value):
        ModelFormWidget.title.fset(self, value)
class EditFundingOpportunitiesApp(ModelFormWidget):

    AUTHORIZED_GROUPS = [settings.PERMISSION_EDIT_FUNDING, 'superuser']

    TITLE = "Edit opportunities"
    MODEL = FundingOpportunity

    FIELDSETS = [
        'h2:Opportunity details',
        segment([
            ('subject', 'fundingopportunity_published',
             'fundingopportunity_rolling'),
            ('fundingopportunity_name', 'fundingopportunity_end'),
            ('_loi', 'fundingopportunity_loideadline',
             'fundingopportunity_fullproposal'),
            ('fundingopportunity_link', 'topics'),
        ]), 'h2:Financing info',
        segment([
            ('financingAgency', 'currency', 'paymentfrequency'),
            ('fundingtype', 'fundingopportunity_value',
             'fundingopportunity_duration'),
        ]), 'h2:Description',
        segment([
            'fundingopportunity_eligibility',
            'fundingopportunity_scope',
            'fundingopportunity_brifdesc',
        ])
    ]

    def __init__(self, *args, **kwargs):
        self._loi = ControlCheckBox('LOI',
                                    changed_event=self.__loi_changed_event)
        self._copybtn = ControlButton('Copy',
                                      default=self.__copybtn_event,
                                      label_visible=False,
                                      css='red')

        super().__init__(*args, **kwargs)

        self.fundingopportunity_loideadline.hide()
        self.fundingopportunity_fullproposal.hide()
        self.__fundingtype_changed_evt()
        self.__loi_changed_event()
        self.fundingtype.changed_event = self.__fundingtype_changed_evt

    def __fundingtype_changed_evt(self):
        if self.fundingtype.value == None:
            self.fundingopportunity_value.show()

        else:
            self.fundingopportunity_value.hide()
            self.fundingopportunity_value.value = None

    def __loi_changed_event(self):
        if self._loi.value:
            self.fundingopportunity_loideadline.show()
            self.fundingopportunity_fullproposal.show()
        else:
            self.fundingopportunity_loideadline.value = None
            self.fundingopportunity_fullproposal.value = None
            self.fundingopportunity_loideadline.hide()
            self.fundingopportunity_fullproposal.hide()

    def delete_event(self):
        res = super(EditFundingOpportunitiesApp, self).delete_event()
        self._copybtn.hide()
        return res

    def save_event(self, obj, new_object):
        res = super(EditFundingOpportunitiesApp,
                    self).save_event(obj, new_object)
        self._copybtn.show()
        return res

    def show_create_form(self):
        super(EditFundingOpportunitiesApp, self).show_create_form()
        self._copybtn.hide()

    def show_edit_form(self, pk=None):
        super(EditFundingOpportunitiesApp, self).show_edit_form(pk)
        self._copybtn.show()

        if self.fundingopportunity_loideadline.value is None and self.fundingopportunity_fullproposal.value is None:
            self.fundingopportunity_loideadline.hide()
            self.fundingopportunity_fullproposal.hide()
            self._loi.value = False
        else:
            self._loi.value = True

    def get_buttons_row(self):
        return [
            no_columns('_save_btn', '_create_btn', '_cancel_btn', ' ',
                       '_copybtn', ' ', '_remove_btn')
        ]

    def __copybtn_event(self):
        obj = self.model_object
        obj.pk = None
        obj.fundingopportunity_name += ' (copy)'
        obj.save()

        for topic in self.model_object.topics.all():
            obj.topics.add(topic)

        app = PyFormsMiddleware.get_instance('opportunities-app')
        app.populate_list()
        app.show_edit_form(obj.pk)
        self.info('Copied')
class ContractEditFormWidget(ModelFormWidget):

    TITLE = 'Edit contract'

    MODEL = Contract

    INLINES = [PayoutInline, FilesInline]

    LAYOUT_POSITION = conf.ORQUESTRA_NEW_TAB
    HAS_CANCEL_BTN_ON_EDIT = False
    CLOSE_ON_REMOVE = True

    FIELDSETS = [
        'h3:Identification',
        segment(
            ('ref', '_openproposal_btn', 'warn_when_ending'),
            ('person', 'supervisor')
        ),
        'h3:Contract conditions',
        segment(
            ('start', 'months_duration',
             'days_duration', 'end'),
            ('salary', ),
            ('socialsecurity_pay', 'socialsecurity_from'),
            ('socialsecurity_start', 'socialsecurity_end')
        ),
        'h3:Function',
        segment(
            'position',
            'fellowship_ref',
            'fellowship_type'
        ),
        ' ',
        segment('PayoutInline', css='blue'),
        ' ',
        segment('FilesInline', css='blue'),
        ' ',
        segment(
            'description',
            'notes',
            css='secondary'
        ),
    ]

    READ_ONLY = (
        'person',
        'supervisor',
        'start',
        'end',
        'description',
        'salary',
        'position',
        'fellowship_type',
        'fellowship_ref',
    )

    @classmethod
    def has_permissions(cls, user):
        from .contracts_list import ContractsListWidget
        return ContractsListWidget.has_permissions(user)

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

        self._renew_btn = ControlButton(
            '<i class="icon refresh" ></i>Renew',
            default=self.__renew_btn_evt,
            # label_visible=False,
            css='secondary'
        )

        self._openproposal_btn = ControlButton(
            'Proposal', default=self.__open_proposal_evt)

        if self.model_object is None or not self.model_object.can_be_renewed():
            self._renew_btn.hide()

    def __renew_btn_evt(self):
        pass

    # noinspection PyUnresolvedReferences,PyUnresolvedReferences,PyUnresolvedReferences,PyUnresolvedReferences,PyUnresolvedReferences
    def __open_proposal_evt(self):
        obj = self.model_object

        # The import has to be done here to avoid recursive imports
        # between the contracts and the proposals
        from ..proposals.proposals_form import EditContractProposalFormWidget

        for proposal in obj.contractproposal_set.all():
            app = EditContractProposalFormWidget(
                pk=proposal.pk,
                title=str(proposal),
                has_cancel_btn=False
            )
            app.LAYOUT_POSITION = conf.ORQUESTRA_NEW_TAB

    def get_contract_start(self):
        return self.model_object.start

    @property
    def title(self):
        obj = self.model_object
        if obj is None:
            return ModelFormWidget.title.fget(self)
        else:
            return "Contract: {0}".format(obj)

    @title.setter
    def title(self, value):
        ModelFormWidget.title.fset(self, value)
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

        authors = kwargs.get('authors')
        title = kwargs.get('title')
        journal_name = kwargs.get('journal_name')
        doi = kwargs.get('doi')
        pubdate = kwargs.get('pubdate')
        pubyear = kwargs.get('pubyear')

        self.pub_hash = str(
            (authors, title, journal_name, doi, pubdate, pubyear))

        text = f"""
            <table>
                <tr>
                    <th style='text-align: right' >Title</th>
                    <td style='padding:5px;padding-left:10px;' colspan='3' >{title}</th>
                <tr/>
                <tr>
                    <th style='text-align: right' >Authors</th>
                    <td style='padding:5px;padding-left:10px;' colspan='3' >{authors}</th>
                <tr/>
                <tr>
                    <th style='text-align: right' >Journal</th>
                    <td style='padding:5px;padding-left:10px;' >{journal_name}</th>
                    <th style='text-align: right' >Pub date</th>
                    <td style='padding:5px;padding-left:10px;' >{pubdate}</th>
                <tr/>
                <tr>
                    <th style='text-align: right' >Year</th>
                    <td style='padding:5px;padding-left:10px;' >{pubyear}</th>
                    <th style='text-align: right' >Doi</th>
                    <td style='padding:5px;padding-left:10px;' >{doi}</th>
                <tr/>
            </table>
        """

        self._person = ControlAutoComplete(
            'Author',
            queryset=Person.objects.all().order_by('full_name'),
            visible=False)
        self._authoralias = ControlText('Author alias', visible=False)
        self._addalias = ControlButton('Add alias',
                                       default=self.__add_author_alias_evt,
                                       visible=False)

        alias = AuthorAlias.objects.all()

        self._authors = ControlList(
            'Unknown authors',
            default=[[a] for a in authors.split(';')
                     if not alias.filter(name=a).exists()],
            horizontal_headers=['Authors alias'],
            item_selection_changed_event=self.__authors_selection_changed_evt)

        self._ignorebtn = ControlButton('Ignore this publication',
                                        css='red',
                                        default=self.__ignore_this_pub_evt,
                                        label_visible=False)
        self._info = ControlLabel(text)
        self._details = ControlEmptyWidget(parent=self,
                                           name='_details',
                                           default=PubsList(**kwargs))

        self.formset = [
            '_ignorebtn', '_info', ('_person', '_authoralias', '_addalias'),
            '_authors',
            segment('_details', css='secondary')
        ]

        if len(self._authors.value) == 0:
            self._authors.hide()
Пример #14
0
class AllOrderEditFormWidget(OrderEditFormWidget):

    #UID   = 'edit-all-orders'
    TITLE = 'Edit order (full access)'

    AUTHORIZED_GROUPS = ['superuser', settings.APP_PROFILE_ALL_ORDERS]

    #sub models to show in the interface
    INLINES = [
        AllOrderExpenseCodeInline,
    ]

    #formset of the edit form
    FIELDSETS = [
        no_columns('order_req', 'group'),
        (
            segment(
                'finance',
                'order_desc',
                ('order_amount', 'currency', 'order_paymethod'),
                field_css='fourteen wide',
            ),
            segment(
                ('order_reqnum', 'order_reqdate'),
                ('order_podate', 'expected_date'),
                ('order_deldate', ' '),
                'order_notes',
                css='secondary',
            ),
        ),
        segment('AllOrderExpenseCodeInline', css='green'),
        no_columns('responsible', )
    ]

    @classmethod
    def has_permissions(cls, user):
        from .all_orders_list import OrderAdminWidget
        return OrderAdminWidget.has_permissions(user)

    @property
    def title(self):
        obj = self.model_object
        if obj is None:
            return ModelFormWidget.title.fget(self)
        else:
            return "Order(full access): {0}".format(obj.order_id)

    @title.setter
    def title(self, value):
        ModelFormWidget.title.fset(self, value)

    def has_add_permissions(self):
        return True

    def has_view_permissions(self):
        return True

    def has_remove_permissions(self):
        return True

    def has_update_permissions(self):
        return True
Пример #15
0
class UserProfileFormWidget(ModelFormWidget):

    UID = 'profile'
    TITLE = 'My Profile'

    MODEL = Person

    LAYOUT_POSITION = conf.ORQUESTRA_HOME

    ORQUESTRA_MENU = 'top'
    ORQUESTRA_MENU_ICON = 'user'
    ORQUESTRA_MENU_ORDER = 1

    HAS_CANCEL_BTN_ON_EDIT = False

    READ_ONLY = (
        'full_name',
        'gender',
        'img',
        'card_number',
        'phone_extension',
        'position',
    )

    FIELDSETS = [
        segment((
            '_summary',
            '_img',
        ), ),
        'h3:PERSONAL INFORMATION',
        {
            '1:General': [
                ('gender', 'birthday'),
                ('personal_email', 'phone_number'),
                'curriculum_vitae',
                'emergency_contact',
            ],
            '2:Public': [
                # 'info:The information provided in the fields below will be shared publicly.',
                ('first_name', 'last_name'),
                'biography',
            ],
            '3:Private': ['_privateinfo'] if hr_module_installed else None,
            '4:Institutional': [
                ('card_number', 'phone_extension'),
                'ProfileGroupsInline',
            ],
            '5:Affiliation': [
                'InstitutionAffiliationInline',
            ],
            '6:Education': [
                'AcademicCareerInline',
            ],
        },
    ]

    INLINES = [
        InstitutionAffiliationInline,
        ProfileGroupsInline,
        AcademicCareerInline,
    ]

    def __init__(self, *args, **kwargs):
        user = PyFormsMiddleware.user()
        try:
            person = Person.objects.get(auth_user=user)
        except Person.DoesNotExist:
            person = Person.objects.get(email=user.email)
            person.auth_user = user
            person.save()

        super().__init__(pk=person.pk, *args, **kwargs)

        membership = GroupMembership.objects.filter(person=person).first()
        membership_html = (
            f'<h3><a>{membership.group}</a> - {membership.position}</h3>'
            if membership is not None else '')
        s = (f'<h1>{person.full_name}</h1>'
             '<address>'
             f'{membership_html}'
             '\n'
             f'<a href="mailto:{person.email}" target="_blank">'
             f'<i class="envelope icon"></i>{person.email}</a>'
             '</address>')
        self._summary = ControlSimpleLabel(
            default=s,
            label_visible=False,
            field_css='fourteen wide',
        )

        if hr_module_installed:
            self._privateinfo = ControlEmptyWidget(
                parent=self,
                name='_privateinfo',
                default=ProfilePrivateInfoFormWidget(
                    pk=person.get_privateinfo().pk,
                    has_cancel_btn=False,
                ),
            )

        try:
            img_url = self.model_object.thumbnail_url(
                geometry_string='300x300')
        except AttributeError:
            img_url = static('square-image.png')
        self._img = ControlImg('Image',
                               default=img_url,
                               label_visible=False,
                               field_css='three wide')

    def save_form_event(self, obj):
        self._privateinfo.value.save_form_event(
            self._privateinfo.value.model_object)
        super().save_form_event(obj)

    def has_remove_permissions(self):
        return False
Пример #16
0
class OrderEditFormWidget(ModelFormWidget):

    MODEL = Order
    LAYOUT_POSITION = conf.ORQUESTRA_NEW_TAB
    HAS_CANCEL_BTN_ON_EDIT = False

    CLOSE_ON_REMOVE = True

    TITLE = 'Edit order'

    READ_ONLY = [
        'responsible',
    ]

    INLINES = [OrderExpenseCodeInline, OrderFileInline]

    FIELDSETS = [('order_req', 'group'),
                 (
                     segment(
                         'finance',
                         'order_desc',
                         ('order_amount', 'currency', 'order_paymethod'),
                         field_css='fourteen wide',
                     ),
                     segment(
                         ('order_reqnum', 'order_reqdate'),
                         ('order_podate', 'expected_date'),
                         ('order_deldate', ' '),
                         'order_notes',
                         css='secondary',
                     ),
                 ),
                 segment('OrderExpenseCodeInline', css='green'),
                 segment('OrderFileInline', css='blue'),
                 no_columns('responsible', )]

    AUTHORIZED_GROUPS = ['superuser', settings.APP_PROFILE_ORDERS]

    @classmethod
    def has_permissions(cls, user):
        from .orders_list import OrderAdminWidget
        return OrderAdminWidget.has_permissions(user)

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

        user = PyFormsMiddleware.user()

        # Filter Auth Groups to the groups the user is a member of.
        self.group.queryset = self.group.queryset.order_by('name')
        if not user.is_superuser:
            self.group.queryset = self.group.queryset & user.groups.all()

        if self.group.queryset.count() == 1:
            self.group.value = self.group.queryset.first().pk

        if self.object_pk is not None:
            self._duplicate_btn = ControlButton(
                'Duplicate',
                default=self.__duplicate_btn_evt,
                label_visible=False,
                css='basic brown')

    def autocomplete_search(self, queryset, keyword, control):
        qs = super().autocomplete_search(queryset, keyword, control)

        if control.name == 'group' and keyword is not None:
            return qs.filter(name__icontains=keyword)
        else:
            return qs

    def __duplicate_btn_evt(self):
        user = PyFormsMiddleware.user()
        order = self.model_object.duplicate(user)
        OrderEditFormWidget(pk=order.pk, parent_win=self.parent)

    def get_buttons_row(self):
        buttons = []
        if self.has_update_permissions(): buttons.append('_save_btn')
        if self.has_add_permissions(): buttons.append('_create_btn')
        if self.has_cancel_btn: buttons.append('_cancel_btn')
        if self.has_remove_permissions(): buttons.append('_remove_btn')
        if self.object_pk is not None: buttons.append('_duplicate_btn')
        return [no_columns(*buttons)]

    def create_newobject(self):
        obj = super().create_newobject()
        obj.responsible = PyFormsMiddleware.user()
        return obj

    def delete_event(self):
        res = super().delete_event()
        self._duplicate_btn.hide()
        return res

    @property
    def title(self):
        obj = self.model_object
        if obj is None:
            return ModelFormWidget.title.fget(self)
        else:
            return "Order: {0}".format(obj.order_id)

    @title.setter
    def title(self, value):
        ModelFormWidget.title.fset(self, value)
Пример #17
0
class ViewFundApp(ModelViewFormWidget):

    UID = 'viewfund-app'

    TITLE = 'Funding opportunities'
    ORQUESTRA_MENU = 'left'
    ORQUESTRA_MENU_ORDER = 0
    ORQUESTRA_MENU_ICON = 'money'
    LAYOUT_POSITION = conf.ORQUESTRA_NEW_WINDOW

    MODEL = FundingOpportunity
    FIELDSETS = [
        no_columns('_favoritebtn', '_urlbtn', '_editbtn'),
        'h2:Opportunity details',
        segment([
            ('subject', 'fundingopportunity_link'),
            ('fundingopportunity_name', 'fundingopportunity_end'),
            ('fundingopportunity_loideadline',
             'fundingopportunity_fullproposal'),
            'topics',
        ]), 'h2:Financing info',
        segment([
            'financingAgency',
            ('fundingopportunity_value', 'currency', 'paymentfrequency',
             'fundingopportunity_duration'),
        ]), 'h2:Description',
        segment([
            'fundingopportunity_eligibility',
            'fundingopportunity_scope',
            'fundingopportunity_brifdesc',
        ])
    ]

    ADD_FAVORITE_LABEL = '<i class="icon star" ></i> Add to favorites'
    REMOVE_FAVORITE_LABEL = '<i class="icon empty star" ></i> Remove from favorites'

    def __init__(self, obj_pk):
        self.obj = FundingOpportunity.objects.get(pk=obj_pk)
        ModelViewFormWidget.__init__(self,
                                     title=self.obj.fundingopportunity_name,
                                     pk=obj_pk)

        if self.fundingopportunity_loideadline.value is None:
            self.fundingopportunity_loideadline.hide()

        if self.fundingopportunity_fullproposal.value is None:
            self.fundingopportunity_fullproposal.hide()

        user = PyFormsMiddleware.user()

        self._editbtn = ControlButton('<i class="icon edit" ></i> Edit',
                                      label_visible=False)

        self._editbtn.value = 'window.location = "/app/opportunities-app/#/funding.apps.fundingopportunities.EditFundingApp/?fund_pk={0}";'.format(
            obj_pk)
        if not user.groups.filter(
                name__in=[settings.PERMISSION_EDIT_FUNDING]).exists():
            self._editbtn.hide()

        self._favoritebtn = ControlButton('Favorite')
        self._favoritebtn.label_visible = False
        self._favoritebtn.value = self.__mark_as_favorite

        if Favorite.objects.filter(user=user, funding=self.obj,
                                   active=True).exists():
            self._favoritebtn.label = self.REMOVE_FAVORITE_LABEL
            self._favoritebtn.css = 'primary basic'
        else:
            self._favoritebtn.label = self.ADD_FAVORITE_LABEL
            self._favoritebtn.css = 'blue'

        self._urlbtn = ControlButton("<i class='ui icon external'></i> URL")
        self._urlbtn.label_visible = False
        self._urlbtn.css = 'basic blue'
        if self.obj and self.obj.fundingopportunity_link:
            self._urlbtn.value = "window.open('{0}', '_blank');".format(
                self.obj.fundingopportunity_link)
        else:
            self._urlbtn.hide()

    def __mark_as_favorite(self):
        user = PyFormsMiddleware.user()

        favorite = None

        try:
            favorite = Favorite.objects.get(user=user, funding=self.obj)

            if favorite.active:
                self._favoritebtn.label = self.ADD_FAVORITE_LABEL
                self._favoritebtn.css = 'blue'
                favorite.active = False
                favorite.save()
            else:
                self._favoritebtn.label = self.REMOVE_FAVORITE_LABEL
                self._favoritebtn.css = 'primary basic'
                favorite.active = True
                favorite.save()

        except Favorite.DoesNotExist:
            Favorite(user=user, funding=self.obj, active=True).save()
            self._favoritebtn.label = self.REMOVE_FAVORITE_LABEL
            self._favoritebtn.css = 'primary basic'

        sidemenu_app = PyFormsMiddleware.get_instance('sidemenu-app')
        sidemenu_app.reload()
Пример #18
0
class CreateContractProposalFormWidget(ModelFormWidget):

    FIELDSETS = [(segment(
        'h3:IDENTIFICATION OF THE PARTIES',
        ('person', 'supervisor'),
        'info:If the Person is missing from the list, use the '
        'fields below to indicate the name and email contact',
        (
            'person_name',
            'person_email',
        ),
        field_css='fourteen wide',
    ), segment('_img', field_style='max-width:330px;')),
                 segment(
                     'h3:CONTRACT DETAILS',
                     (
                         'start',
                         'months_duration',
                         'days_duration',
                         'end_date',
                     ),
                     ('position', 'fellowship_type', 'salary', ' '),
                     'description',
                 )]

    @classmethod
    def has_permissions(cls, user):
        from .proposals_list import ContractProposalsListWidget
        return ContractProposalsListWidget.has_permissions(user)

    def __init__(self, *args, **kwargs):

        self._img = ControlImg('Image', label_visible=False)

        super().__init__(*args, **kwargs)

        self.start.changed_event = self.__update_end_date
        self.months_duration.changed_event = self.__update_end_date
        self.days_duration.changed_event = self.__update_end_date

        # Handle situation where Add Form is opened as inline
        if not hasattr(self, 'person'):
            person = Person.objects.get(pk=self.parent_pk)
            self.person = ControlAutoComplete(
                label='Person',
                queryset=Person.objects.all(),
                default=person.pk,
                readonly=True,
            )
            self.__update_image_evt()

        self.person.changed_event = self.__update_image_evt

    def __update_end_date(self):

        try:
            days = 0 if not self.days_duration.value else self.days_duration.value
            self.end_date.value = (
                self.start.value.date() +
                relativedelta(months=self.months_duration.value, days=days) -
                timedelta(days=1))
        except:
            self.end_date.value = ''

    def __update_image_evt(self):
        try:
            person = Person.objects.get(pk=self.person.value)
        except Person.DoesNotExist:
            url = Person.DEFAULT_PICTURE_URL
        else:
            url = person.thumbnail_url('300x300')
        self._img.value = url

    def save_event(self, obj, new_object):
        if new_object:
            user = PyFormsMiddleware.user()
            obj.responsible = user.person
        return super().save_event(obj, new_object)
Пример #19
0
class CostCenterListApp(ModelAdminWidget):

    TITLE = 'Cost Centers'
    UID = 'cost-centers'

    MODEL = CostCenter

    LIST_DISPLAY = ['code', 'name', 'start_date', 'end_date']

    LIST_FILTER = ['group', 'project__code']

    SEARCH_FIELDS = ['name__icontains', 'code__icontains']

    INLINES = [FinanceProjectListApp]

    FIELDSETS = [
        segment(
            'name',
            ('code', 'start_date', 'end_date'),
            'group',
        ),
        ' ',
        'FinanceProjectListApp',
        ' ',
    ]

    # ORQUESTRA CONFIGURATION
    # =========================================================================
    ORQUESTRA_MENU = 'left>FinancesDashboardWidget'
    ORQUESTRA_MENU_ORDER = 10
    ORQUESTRA_MENU_ICON = 'boxes'
    LAYOUT_POSITION = conf.ORQUESTRA_HOME
    # =========================================================================

    AUTHORIZED_GROUPS = ['superuser', settings.PROFILE_LAB_ADMIN]

    def __init__(self, *args, **kwargs):

        self._active = ControlCheckBox(
            'Active',
            default=True,
            label_visible=False,
            changed_event=self.populate_list,
            # field_style='text-align:right;',  # FIXME breaks form
        )

        super().__init__(*args, **kwargs)

        # Edit filter label
        self._list.custom_filter_labels = {
            'project__code': 'Project Code',
        }

    def get_toolbar_buttons(self, has_add_permission=False):
        return tuple((['_add_btn'] if has_add_permission else []) + [
            '_active',
        ])

    def get_queryset(self, request, qs):

        if self._active.value:
            qs = qs.active()

        return qs

    def has_remove_permissions(self, obj):
        """Only superusers may delete these objects."""
        user = PyFormsMiddleware.user()
        return user.is_superuser
Пример #20
0
class GroupFormApp(ModelFormWidget):

    LAYOUT_POSITION = conf.ORQUESTRA_NEW_TAB
    HAS_CANCEL_BTN_ON_EDIT = False
    CLOSE_ON_REMOVE = True
    TITLE = 'Group'

    INLINES = [MembershipsListWidget
               ] + ([ProjectsListWidget] if research_module_installed else [])

    LAYOUT_POSITION = conf.ORQUESTRA_NEW_TAB

    FIELDSETS = [
        ('type', 'responsible'), ' ',
        (segment(
            'h3: IDENTIFICATION',
            'name',
            'subject',
            field_css='fourteen wide',
        ), segment('_img', field_style='max-width:330px;')), {
            '1:Group Information': [
                'description',
                'web',
                'logo_img',
                '_grpimg',
            ],
            '2:Members': ['MembershipsListWidget'],
            '3:Projects':
            ['ProjectsListWidget'] if research_module_installed else None,
        }
    ]

    def __init__(self, *args, **kwargs):

        self._img = ControlImg('Image', label_visible=False)
        self._grpimg = ControlImg('Image', label_visible=False)

        super().__init__(*args, **kwargs)

        self.responsible.changed_event = self.__update_image_evt

        self.logo_img.changed_event = self.__update_group_img_evt

        self.__update_image_evt()
        self.__update_group_img_evt()

    def __update_group_img_evt(self):
        self._grpimg.value = self.logo_img.value

    def __update_image_evt(self):
        try:
            person = Person.objects.get(pk=self.responsible.value.pk)
            url = person.thumbnail_url('300x300')
        except:
            url = Person.DEFAULT_PICTURE_URL

        self._img.value = url

    @property
    def title(self):
        obj = self.model_object
        if obj is None:
            return ModelFormWidget.title.fget(self)
        else:
            return "Group: {0}".format(obj.name)

    @title.setter
    def title(self, value):
        ModelFormWidget.title.fset(self, value)
Пример #21
0
class RequestReimbursementForm(ModelFormWidget):
    """
    """

    TITLE = "Request Reimbursement"

    MODEL = Reimbursement

    HAS_CANCEL_BTN_ON_ADD  = False
    HAS_CANCEL_BTN_ON_EDIT = False
    CLOSE_ON_REMOVE = True

    READ_ONLY = ["created", "modified", "status_changed", 'status']

    INLINES = [ExpenseInline]

    FIELDSETS = [
        no_columns('_previous', '_submit', "_print", '_printed', '_submit2approve','_reject', '_accept', 'bank_transfer_date', '_close', style="float:right"),
        "h3:Requester Information",
        segment(
            ("person", "iban")
        ),
        "h3:Expenses",
        segment("ExpenseInline"),
        ("created", "modified", "status", "status_changed")
    ]

    # Orquestra ===============================================================
    LAYOUT_POSITION = conf.ORQUESTRA_NEW_TAB
    # =========================================================================

    def __init__(self, *args, **kwargs):

        self._previous = ControlButton(
            '<i class="ui icon paper plane outline"></i>Previous status',
            css="basic gray",
            visible = False,
            label_visible=False,
            default = self.__previous_status_evt
        )

        self._submit = ControlButton(
            '<i class="ui icon paper plane outline"></i>Submit',
            css="blue",
            visible=False,
            label_visible=False,
            default = self.__submit_2_pending_evt
        )

        self._print = ControlButton(
            '<i class="ui icon print"></i>Print',
            visible=False,
            css="basic blue",
            label_visible=False
        )

        self._printed = ControlButton(
            '<i class="ui icon paper plane outline"></i>Set printed',
            visible=False,
            css="blue",
            label_visible=False,
            default=self.__set_printed_evt
        )

        self._submit2approve = ControlButton(
            '<i class="ui icon paper plane outline"></i>Submit to approval',
            visible=False,
            css="blue",
            label_visible=False,
            default=self.__submit_2_approve_evt
        )

        self._accept = ControlButton(
            '<i class="ui icon thumbs up"></i>Accept',
            visible=False,
            css="green",
            label_visible=False,
            default = self.__accept_evt
        )

        self._reject = ControlButton(
            '<i class="ui icon thumbs down"></i>Reject',
            visible=False,
            css="red",
            label_visible=False,
            default=self.__reject_evt
        )

        self._close = ControlButton(
            '<i class="ui icon thumbs up"></i>It was paid',
            visible=False,
            css="green basic",
            default=self.__set_closed_evt
        )

        super().__init__(*args, **kwargs)

        self.person.enabled = False

        if self.model_object is None:

            user   = PyFormsMiddleware.user()
            person = user.person_user.first()

            if person is not None:
                self.person.value = person.pk
                self.iban.value = person.privateinfo.iban
            else:
                self.warning(
                    'You need a Person profile associated to your account to be able to create reimbursements.'
                )

        self.update_fields_visibility()


    def update_fields_visibility(self):
        obj = self.model_object

        if obj:
            self._print.value = 'window.open("{0}", "_blank");'.format(
                reverse("print-reimbursement-form", args=[obj.pk])
            )
            self._print.show()
        else:
            self._print.hide()

        # show submit button only when is draft
        if obj is None or obj.status != 'draft':
            self._submit.hide()

        # show print button only when the reimbursement is pending
        if obj is None:
            self._print.hide()

        if obj and self.has_update_permissions():

            if obj.status == 'draft':

                self.bank_transfer_date.hide()
                self._submit.show()
                self._previous.hide()
                self._print.hide()
                self._printed.hide()
                self._submit2approve.hide()
                self._accept.hide()
                self._reject.hide()
                self._close.hide()
                self.iban.enabled = True

            elif obj.status == 'pending':

                self.bank_transfer_date.hide()
                self._previous.show()
                self._submit.hide()
                self._print.show()
                self._printed.show()
                self._submit2approve.hide()
                self._accept.hide()
                self._reject.hide()
                self._close.hide()
                self.iban.enabled = False

            elif obj.status == 'printed':

                self.bank_transfer_date.hide()
                self._previous.show()
                self._submit.hide()
                self._print.hide()
                self._printed.hide()
                self._submit2approve.show()
                self._accept.hide()
                self._reject.hide()
                self._close.hide()
                self.iban.enabled = False

            elif obj.status == 'submitted':

                self.bank_transfer_date.hide()
                self._previous.show()
                self._submit.hide()
                self._print.hide()
                self._printed.hide()
                self._submit2approve.hide()
                self._accept.show()
                self._reject.show()
                self._close.hide()
                self.iban.enabled = False

            elif obj.status in ['rejected', 'approved']:

                self._previous.hide()
                self._submit.hide()
                self._print.hide()
                self._printed.hide()
                self._submit2approve.hide()
                self._accept.hide()
                self._reject.hide()
                self.iban.enabled = False

                if obj.status == 'approved':
                    self.bank_transfer_date.show()
                    self._close.show()
                else:
                    self.bank_transfer_date.hide()
                    self._close.hide()

            elif obj.status == 'closed':

                self.bank_transfer_date.show()
                self.bank_transfer_date.readonly = True
                self._previous.hide()
                self._submit.hide()
                self._print.hide()
                self._printed.hide()
                self._submit2approve.hide()
                self._accept.hide()
                self._reject.hide()
                self._close.hide()
                self.iban.enabled = False

        else:

            self.bank_transfer_date.hide()
            self._submit.hide()
            self._previous.hide()
            self._print.hide()
            self._printed.hide()
            self._submit2approve.hide()
            self._accept.hide()
            self._reject.hide()
            self._close.hide()
            self.iban.enabled = True

        if obj.status == 'closed':
            self.bank_transfer_date.show()
            self.bank_transfer_date.readonly = True



    def save_btn_event(self):
        super().save_btn_event()
        self.update_fields_visibility()

    def __previous_status_evt(self):
        if not self.has_update_permissions():
            raise Exception('No permission')

        obj = self.model_object
        obj.previous_status()

        self.show_edit_form(self.object_pk)
        self.update_fields_visibility()

    def __set_printed_evt(self):
        if not self.has_update_permissions():
            raise Exception('No permission')

        obj = self.model_object
        obj.set_printed()

        self.show_edit_form(self.object_pk)
        self.update_fields_visibility()

    def __submit_2_pending_evt(self):
        """
        Notify the users with approval responsibility about the new reimbursement
        """
        if not self.has_update_permissions():
            raise Exception('No permission')

        obj = self.model_object
        obj.submit_to_pending()

        self.show_edit_form(self.object_pk)
        self.update_fields_visibility()

    def __submit_2_approve_evt(self):
        if not self.has_update_permissions():
            raise Exception('No permission')

        obj = self.model_object
        obj.submit_for_approval()

        self.show_edit_form(self.object_pk)
        self.update_fields_visibility()

    def __accept_evt(self):
        if not self.has_update_permissions():
            raise Exception('No permission')

        obj = self.model_object
        obj.accept()

        self.show_edit_form(self.object_pk)
        self.update_fields_visibility()

    def __reject_evt(self):
        if not self.has_update_permissions():
            raise Exception('No permission')

        obj = self.model_object
        obj.reject()

        self.show_edit_form(self.object_pk)
        self.update_fields_visibility()

    def __set_closed_evt(self):
        if not self.has_update_permissions():
            raise Exception('No permission')

        obj = self.model_object
        obj.bank_transfer_date = self.bank_transfer_date.value
        obj.set_closed() # this function will save the object

        self.show_edit_form(self.object_pk)
        self.update_fields_visibility()


    def get_readonly(self, default):
        res  = super().get_readonly(default)
        obj  = self.model_object

        if obj and obj.status in ['rejected', 'approved']:
            return res + ['status']

        if obj and obj.has_approve_permissions(PyFormsMiddleware.user()):
            return res
        else:
            return res + ['status']


    def update_object_fields(self, obj):
        """
        Update the created by field.
        :param Reimbursement obj:
        :return: Return the updated reimbursement object.
        """
        obj = super().update_object_fields(obj)

        if obj.pk is None:
            obj.created_by = PyFormsMiddleware.user()

        return obj

    @property
    def title(self):
        obj = self.model_object
        if obj:
            name = obj.requester_name
            total = obj.total
            return f"({obj.pk}) {obj.person} ({obj.total})"
        else:
            return super().title