Exemple #1
0
class HandlingView(ModelView):
    list_template = 'admin/realtime.html'
    column_default_sort = ('id', True)
    column_display_pk = True
    column_list = ('source', 'accepted_by', 'delegated_by', 'message')
    form_columns = ('source', 'message')
    column_labels = dict(source='Источник',
                         accepted_by='Принял',
                         delegated_by='Получил',
                         message='Сообщение')
    form_overrides = {
        'message':
        TextAreaField,
        'сообщения':
        QueryAjaxModelLoader('Источник',
                             db.session,
                             Source,
                             fields=['id'],
                             page_size=10)
    }

    form_widget_args = {
        'message': {
            'rows': 5,
            'style': 'font-family: monospace;'
        }
    }
    can_delete = False
    can_edit = False
    create_modal = True
Exemple #2
0
class CategoryView(ModelView):
    column_exclude_list = [
        'delete_time', 'update_time', 'create_time', 'status'
    ]
    #column_list = ('email', 'nickname', 'auth')
    column_labels = {
        'name': u"分类名称",
        # 'topic_img_id':u"图标id",
        'image': u"图标"
    }

    form_ajax_refs = {
        'topic_img_id':
        QueryAjaxModelLoader('topic_img_id',
                             db.session,
                             Image,
                             fields=['id'],
                             page_size=10)
        # 'Image': {
        #     'fields': ['topic_img_id'],
        #     'page_size': 10
        # }
    }

    #                form_ajax_refs = {
    #                    'user': QueryAjaxModelLoader('user', db.session, User, fields=['email'], page_size=10)
    #                }

    def __init__(self, session, **kwargs):
        # You can pass name add other parameters if you want to
        super(CategoryView, self).__init__(Category, session, **kwargs)
Exemple #3
0
class RoleView(ModelView):
    """Admin view for roles."""

    can_view_details = True

    list_all = ('id', 'name', 'description')

    column_list = \
        column_searchable_list = \
        column_filters = \
        column_details_list = \
        columns_sortable_list = \
        list_all

    form_columns = ('name', 'description', 'users')

    user_loader = QueryAjaxModelLoader(
        'user',
        LocalProxy(lambda: _datastore.db.session),
        User,
        fields=['email'],
        page_size=10
    )

    form_extra_fields = {
        'users': AjaxSelectMultipleField(user_loader)
    }

    form_ajax_refs = {
        'user': user_loader
    }
Exemple #4
0
class OrganisationView(SocoModelView):
    can_export = True
    form_args = {
        'nom': {
            'label': gettext('Nom de l\'organisation')
        },
        'interne': {
            'label':
            gettext(
                'Est-ce une organisation interne, susceptible d\'organiser des événements ?'
            )
        },
        'email': {
            'label': gettext('Adresse mail de contact')
        },
        'lieu': {
            'label': gettext('Lieux utilisés')
        },
        'evenement': {
            'label': gettext('Événements programmés')
        }
    }
    form_overrides = dict(logo=LogoField)
    #inline_models = [(Evenement, dict(form_columns=['id', 'titre', 'date']))]
    form_ajax_refs = {
        'personne':
        QueryAjaxModelLoader('personne',
                             db_session,
                             Personne,
                             fields=['nom', 'prenom'],
                             page_size=10),
        'lieu':
        QueryAjaxModelLoader('lieu',
                             db_session,
                             Lieu,
                             fields=['nom'],
                             page_size=10),
        'evenement':
        QueryAjaxModelLoader('evenement',
                             db_session,
                             Evenement,
                             fields=['titre'],
                             page_size=10)
    }
Exemple #5
0
class SubCategoryView(ModelView):
    can_delete = False
    column_list = ("name", "category.name")
    column_labels = {
        "name": "Name",
        "category.name": "Category"

    }
    form_excluded_columns = ["product"]
    column_searchable_list = [
        "name"
    ]

    def scaffold_form(self):
        form_class = super(SubCategoryView, self).scaffold_form()
        form_class.category = fields.SelectField(
            label="Category",
            coerce=int,
            choices=Session.query(
                db.Category.category_id, 
                db.Category.name
                ).all()
        )
        return form_class

    def create_model(self, form):
        cat = db.Category.read_category(db.Category, form.category.data)
        db.SubCategory(form.name.data, cat)
        flash("Record was successfully created", "success")
     
    def update_model(self, form, model):
        update = Session.query(
            db.SubCategory
        ).filter(
            db.SubCategory.sub_category_id == model.sub_category_id
        ).update(
            {
                "name":form.name.data,
                "category_id":form.category.data
            })
        if update:
            Session.commit()
            return True
        else:
            return False

    form_ajax_refs = {
        "category": QueryAjaxModelLoader(
            "category", 
            Session, 
            db.Category,
            fields=["name"] 
        )
    }
Exemple #6
0
class InscriptionView(SocoModelView):
    can_export = True
    column_exclude_list = [
        'upd', 'token', 'type_inscription', 'telephone', 'commentaire',
        'badge1', 'badge2'
    ]
    form_args = {'telephone': {'label': gettext('Téléphone')}}
    form_ajax_refs = {
        'evenement':
        QueryAjaxModelLoader('evenement',
                             db_session,
                             Evenement,
                             fields=['titre'],
                             page_size=10),
        'personne':
        QueryAjaxModelLoader('personne',
                             db_session,
                             Personne,
                             fields=['nom', 'prenom'],
                             page_size=10)
    }
Exemple #7
0
class ReviewView(RegularView):
    can_export = True
    column_list = ('id', 'date_modified',
                   'comment', 'location', 'generic',
                   'tag_id', 'score', 'submission_id',
                   'author_id', 'assignment_version',
                   'submission_version', 'version',
                   'forked_id', 'forked_version')
    column_formatters = {'author_id': _editable(User, 'id'), 'submission_id': _editable(Submission, 'id')}

    form_ajax_refs = {
        'submission': QueryAjaxModelLoader('submission', db.session, Submission, fields=['id'], page_size=10)
    }
Exemple #8
0
 def postprocess_form(self, form):
     from psi.app.views.components import DisabledStringField
     form.total_amount = DisabledStringField(label=lazy_gettext('Total Amount'))
     form.saleable_quantity = DisabledStringField(label=lazy_gettext('Saleable Quantity')),
     ajaxLoader = QueryAjaxModelLoader(name='product',
                                       session=service.Info.get_db().session,
                                       model=Product,
                                       fields=['name'])
     form.product = AjaxSelectField(ajaxLoader, label=lazy_gettext('Product(Can be searched by first letter)'))
     form.itl_receiving_line = None
     form.remark = None
     form.itl_shipping_line = None
     form.in_transit_quantity = None
     return form
Exemple #9
0
 def postprocess_form(self, form):
     form.total_amount = DisabledStringField(
         label=lazy_gettext('Total Amount'))
     form.remark = None
     form.pol_receiving_lines = None
     ajaxLoader = QueryAjaxModelLoader(
         name='product',
         session=service.Info.get_db().session,
         model=Product,
         fields=['name'])
     form.product = AjaxSelectField(
         ajaxLoader,
         label=lazy_gettext('Product(Can be searched by first letter)'))
     return form
Exemple #10
0
 def postprocess_form(self, form):
     from flask_admin.model.fields import AjaxSelectField
     ajaxLoader = QueryAjaxModelLoader(name='product',
                                       session=service.Info.get_db().session,
                                       model=Product,
                                       fields=['name'])
     form.product = AjaxSelectField(ajaxLoader, label=lazy_gettext('Product(Can be searched by first letter)'))
     form.retail_price = DisabledStringField(label=lazy_gettext('Retail Price'))
     form.price_discount = DisabledStringField(label=lazy_gettext('Price Discount'))
     form.original_amount = DisabledStringField(label=lazy_gettext('Original Amount'))
     form.actual_amount = DisabledStringField(label=lazy_gettext('Actual Amount'))
     form.discount_amount = DisabledStringField(label=lazy_gettext('Discount Amount'))
     form.remark = None
     form.sol_shipping_line = None
     form.external_id = None
     return form
Exemple #11
0
class PersonneView(SocoModelView):
    can_export = True
    column_exclude_list = ['token']
    form_args = {'prenom': {'label': gettext('Prénom')}}
    inline_models = [
        (Inscription,
         dict(form_columns=['id', 'evenement', 'attestation_demandee']))
    ]
    form_ajax_refs = {
        'organisation':
        QueryAjaxModelLoader('organisation',
                             db_session,
                             Organisation,
                             fields=['nom'],
                             page_size=10)
    }
Exemple #12
0
class FormulaireView(SocoModelView):
    column_exclude_list = [
        'upd', 'texte_restauration_1', 'texte_restauration_2', 'texte_libre_1',
        'texte_libre_2'
    ]
    column_labels = dict(
        date_ouverture_inscriptions=gettext("Ouverture inscript."),
        date_cloture_inscriptions=gettext("Clôture inscript."))
    column_descriptions = dict(
        organisateurs_en_copie=gettext(
            "Souhaitez-vous que les organisateurs reçoivent un mail à chaque inscription ?"
        ),
        champ_attestation=gettext(
            "Les personnes qui s'inscrivent peuvent demander une attestation de présence"
        ),
        champ_restauration_1=gettext("Pour pouvoir s'inscrire à un repas"),
        texte_restauration_1=gettext("Le texte de la question correspondante"),
        champ_restauration_2=gettext(
            "2ème possibilité pour pouvoir s'inscrire à un repas"),
        texte_restauration_2=gettext("Le texte de la question correspondante"),
        champ_libre_1=gettext("Présence d'une question libre"),
        texte_libre_1=gettext("Le texte de la cette question"),
        champ_libre_2=gettext("Présence d'une 2ème question libre"),
        texte_libre_2=gettext("Le texte de cette 2ème question"))
    form_ajax_refs = {
        'evenement':
        QueryAjaxModelLoader('evenement',
                             db_session,
                             Evenement,
                             fields=['titre'],
                             page_size=10)
    }
    form_args = {
        'date_ouverture_inscriptions': {
            'label': gettext('Date d\'ouverture des inscriptions'),
            'validators': [DataRequired()]
        },
        'date_cloture_inscriptions': {
            'label': gettext('Date de clôture des inscriptions'),
            'validators': [DataRequired()]
        },
        'organisateurs_en_copie': {
            'label': gettext('Organisateurs en copie ?')
        }
    }
Exemple #13
0
class RoleView(ModelView):
    """Admin view for roles."""

    can_view_details = True

    list_all = ("id", "name", "description")

    column_list = (
        column_searchable_list
    ) = column_filters = column_details_list = columns_sortable_list = list_all

    form_columns = ("name", "description", "users")

    user_loader = QueryAjaxModelLoader(
        "user",
        LocalProxy(lambda: _datastore.db.session),
        User,
        fields=["email"],
        page_size=10,
    )

    form_extra_fields = {"users": AjaxSelectMultipleField(user_loader)}

    form_ajax_refs = {"user": user_loader}
class QuestionAdmin(BaseAdminView):
    # def is_visible(self):
    #     return False

    column_list = ['id', 'type', 'lod', 'topic', 'tags']

    column_searchable_list = ['type', 'lod', 'topic']
    column_filters = ['type', 'lod', 'topic', 'tags']
    column_editable_list = ['type']

    form_edit_rules = [
        'type', 'lod', 'topic', 'tags', 'points_correct', 'points_wrong',
        'sections', 'tita_answer', 'html', 'rc_passage', 'choices',
        'coding_cases', 'allowed_languages', 'logic'
    ]

    form_ajax_refs = {
        'sections':
        QueryAjaxModelLoader('sections',
                             db.session,
                             Section,
                             fields=['name'],
                             page_size=10),
        'tags':
        QueryAjaxModelLoader('tags',
                             db.session,
                             Tag,
                             fields=['name'],
                             page_size=10)
    }

    form_create_rules = form_edit_rules

    form_overrides = dict(html=CKTextAreaField,
                          rc_passage=CKTextAreaField,
                          logic=CKTextAreaField)
    inline_models = (ChoicesInlineForm(Choice),
                     CodingCasesInlineForm(CodingCase))

    form_choices = {
        'type': [('RC', 'RC'), ('MCQ', 'MCQ'), ('TITA', 'TITA'),
                 ('CODING', 'CODING'), ('SUBJECTIVE', 'SUBJECTIVE')],
        'lod': [('Easy', 'Easy'), ('Medium', 'Medium'),
                ('Difficult', 'Difficult')],
        'topic': [("Simplifications", "Simplifications"),
                  ("Compound & Simple Interest", "Compound & Simple Interest"),
                  ("Ratio and Proportion", "Ratio and Proportion"),
                  ("Probability", "Probability"),
                  ("Time,Speed,Distance & Work", "Time,Speed,Distance & Work"),
                  ("Number System", "Number System"), ("Algebra", "Algebra"),
                  ("Geometry", "Geometry"), ("Mensuration", "Mensuration"),
                  ("Percentage", "Percentage"),
                  ("Quadratic Equation", "Quadratic Equation"),
                  ("Profit/Loss/Discount", "Profit/Loss/Discount"),
                  ("Mixtures and Alligation", "Mixtures and Alligation"),
                  ("Inequalities", "Inequalities"),
                  ("Permutation & Combination", "Permutation & Combination"),
                  ("Logarithms", "Logarithms"), ("Ages", "Ages"),
                  ("Investments andShares", "Investments andShares"),
                  ("Bar Graph", "Bar Graph"), ("Line Graph", "Line Graph"),
                  ("Tables", "Tables"), ("PieChart", "PieChart"),
                  ("Number Series", "Number Series"),
                  ("Seating Arrangement", "Seating Arrangement"),
                  ("Puzzles", "Puzzles"), ("Input Output", "Input Output"),
                  (" Coding Decoding", " Coding Decoding"),
                  ("Visual Puzzle", "Visual Puzzle"),
                  ("Reading Comprehension", "Reading Comprehension"),
                  ("Parajumbles", "Parajumbles"),
                  ("Para  Completion", "Para  Completion"),
                  ("Summary Based Question", "Summary Based Question"),
                  ("Sentence error correction", "Sentence error correction"),
                  ("Verbal Ability", "Verbal Ability"),
                  ("Cloze Test", "Cloze Test"), ("Syllogisms", "Syllogisms"),
                  ("Fill in the blanks", "Fill in the blanks"),
                  ("Odd one out", "Odd one out"),
                  ("Verbal Reasoning", "Verbal Reasoning"),
                  ("Synoyms", "Synoyms"), ("Antonyms", "Antonyms"),
                  ("Operating Systems", "Operating Systems"),
                  ("C Programming", "C Programming"), ("Array", "Array"),
                  ("Linkedlist", "Linkedlist"),
                  ("Data Structures", "Data Structures"), ("DBMS", "DBMS"),
                  ("Output", "Output")]
    }
    form_args = {
        'type': {
            'validators': [
                InputRequired(),
                AnyOf(['RC', 'MCQ', 'TITA', "CODING", "SUBJECTIVE"])
            ]
        },
        'points_correct': {
            'validators': [InputRequired(), DecimalField]
        },
        'points_wrong': {
            'validators': [InputRequired(), DecimalField]
        },
        'lod': {
            'validators':
            [InputRequired(),
             AnyOf(["Easy", "Medium", "Difficult"])]
        }
    }
Exemple #15
0
class SalesOrderAdmin(ModelViewWithAccess, ModelWithLineFormatter):
    from psi.app.models import SalesOrderLine, SalesOrder
    from formatter import expenses_formatter, incoming_formatter, \
        shipping_formatter, default_date_formatter, line_formatter

    line_fields = [product_field, quantity_field, retail_price_field,
                   actual_amount_field, original_amount_field,
                   discount_amount_field, remark_field]

    column_extra_row_actions = [
        MarkShipRowAction('fa fa-camera-retro'),
        MarkInvalidRowAction('fa fa-minus-circle')
    ]

    column_list = ('id', 'type', 'status', 'customer', 'logistic_amount', 'actual_amount', 'original_amount',
                   'discount_amount', 'order_date', 'incoming', 'expense', 'so_shipping', 'remark')
    column_filters = ('order_date', 'logistic_amount',
                      FloatSmallerFilter(SalesOrder.actual_amount, lazy_gettext('Actual Amount')),
                      FloatGreaterFilter(SalesOrder.actual_amount, lazy_gettext('Actual Amount')),
                      FloatEqualFilter(SalesOrder.actual_amount, lazy_gettext('Actual Amount')),
                      FloatSmallerFilter(SalesOrder.discount_amount, lazy_gettext('Discount Amount')),
                      FloatGreaterFilter(SalesOrder.discount_amount, lazy_gettext('Discount Amount')),
                      FloatEqualFilter(SalesOrder.discount_amount, lazy_gettext('Discount Amount')),
                      FloatSmallerFilter(SalesOrder.original_amount, lazy_gettext('Total Amount')),
                      FloatGreaterFilter(SalesOrder.original_amount, lazy_gettext('Total Amount')),
                      FloatEqualFilter(SalesOrder.original_amount, lazy_gettext('Total Amount')),)

    column_searchable_list = ('customer.first_name', 'customer.last_name', 'remark', 'type.display', 'type.code',
                              'status.display', 'status.code', 'customer.mobile_phone', 'customer.email',
                              'customer.address', 'customer.level.display', 'customer.join_channel.display')

    form_columns = ('id', 'customer', 'logistic_amount', 'status', 'order_date', 'remark', 'actual_amount',
                    'original_amount', 'discount_amount', 'lines')
    form_edit_rules = ('customer', 'logistic_amount', 'order_date', 'status', 'remark', 'actual_amount',
                       'original_amount', 'discount_amount', 'lines')
    form_create_rules = ('customer', 'logistic_amount',  'order_date', 'status', 'remark', 'lines',)

    column_details_list = ('id', 'type', 'status', 'customer', 'external_id', 'logistic_amount', 'order_date', 'remark',
                           'actual_amount', 'original_amount', 'discount_amount', 'incoming', 'expense',
                           'so_shipping', 'lines',)

    column_editable_list = ('remark',)

    form_extra_fields = {
        'transient_external_id': DisabledStringField(label=lazy_gettext('External Id')),
        'actual_amount': DisabledStringField(label=lazy_gettext('Actual Amount')),
        'original_amount': DisabledStringField(label=lazy_gettext('Original Amount')),
        'discount_amount': DisabledStringField(label=lazy_gettext('Discount Amount'))
    }

    form_overrides = dict(external_id=ReadonlyStringField)

    form_args = dict(
        logistic_amount=dict(default=0),
        order_date=dict(default=datetime.now()),
        status=dict(query_factory=SalesOrder.status_option_filter),
        customer=dict(description=lazy_gettext('Customer can be searched by name, mobile phone, email or first letter of his/her name'))
    )

    form_excluded_columns = ('incoming', 'expense', 'so_shipping')
    column_sortable_list = ('id', 'logistic_amount', 'actual_amount', 'original_amount', 'discount_amount',
                            'order_date',('status', 'status.display'), ('type', 'type.display'))

    form_ajax_refs = {
        'customer': QueryAjaxModelLoader('customer',
                                         service.Info.get_db().session, Customer,
                                         filters=[],
                                         fields=['first_name', 'last_name', 'mobile_phone', 'email', 'mnemonic']),
        'product': QueryAjaxModelLoader(name='product',
                                        session=service.Info.get_db().session,
                                        model=Product,
                                        # --> Still need to filter the products by organization.
                                        # --> Line 209 is commented out, need to bring it back.
                                        fields=['name', 'mnemonic'])
    }

    inline_models = (SalesOrderLineInlineAdmin(SalesOrderLine),)

    column_formatters = {
        'expense': expenses_formatter,
        'incoming': incoming_formatter,
        'so_shipping': shipping_formatter,
        'order_date': default_date_formatter,
        'lines': line_formatter,
    }

    column_labels = {
        'id': lazy_gettext('id'),
        'logistic_amount': lazy_gettext('Logistic Amount'),
        'order_date': lazy_gettext('Order Date'),
        'remark': lazy_gettext('Remark'),
        'actual_amount': lazy_gettext('Actual Amount'),
        'original_amount': lazy_gettext('Original Amount'),
        'discount_amount': lazy_gettext('Discount Amount'),
        'incoming': lazy_gettext('Related Incoming'),
        'expense': lazy_gettext('Related Expense'),
        'so_shipping': lazy_gettext('Related Shipping'),
        'lines': lazy_gettext('Lines'),
        'external_id': lazy_gettext('External Id'),
        'customer': lazy_gettext('Customer'),
        'customer.name': lazy_gettext('Customer'),
        'status': lazy_gettext('Status'),
        'type': lazy_gettext('Type'),
    }

    def create_form(self, obj=None):
        form = super(SalesOrderAdmin, self).create_form(obj)
        self.hide_line_derive_fields_on_create_form(form)
        form_util.filter_by_organization(form.customer, Customer)
        self.filter_product_by_organization(form)
        return form

    def hide_line_derive_fields_on_create_form(self, form):
        form.lines.form.actual_amount = None
        form.lines.form.discount_amount = None
        form.lines.form.original_amount = None
        form.lines.form.price_discount = None
        form.lines.form.retail_price = None

    def edit_form(self, obj=None):
        form = super(SalesOrderAdmin, self).edit_form(obj)
        form_util.filter_by_organization(form.customer, Customer)
        self.filter_product_by_organization(form)
        return form

    @staticmethod
    def filter_product_by_organization(form):
        # Set query factory for new created line
        # TODO.xqliu Fix this for AJAX lookup
        # If we uncomment follow line to limit the query to current organization
        # The AJAX look up fails.
        # form.lines.form.product.kwargs['query_factory'] = partial(Product.organization_filter, current_user.organization_id)
        # Set query object filter for existing lines
        line_entries = form.lines.entries
        for sub_line in line_entries:
            form_util.filter_by_organization(sub_line.form.product, Product)

    def on_model_change(self, form, model, is_created):
        super(SalesOrderAdmin, self).on_model_change(form, model, is_created)
        if is_created:
            model.type = EnumValues.get(const.DIRECT_SO_TYPE_KEY)
            if model.status is None:
                model.status = EnumValues.get(const.SO_DELIVERED_STATUS_KEY)
            model.organization = current_user.organization
        if model.status.code == const.SO_DELIVERED_STATUS_KEY:
            incoming = SalesOrderService.create_or_update_incoming(model)
            expense = SalesOrderService.create_or_update_expense(model)
            shipping = None
            if model.type.code == const.DIRECT_SO_TYPE_KEY:
                shipping = SalesOrderService.create_or_update_shipping(model)
            db = service.Info.get_db()
            if expense is not None:
                db.session.add(expense)
            if incoming is not None:
                db.session.add(incoming)
            if shipping is not None:
                db.session.add(shipping)

    @property
    def role_identify(self):
        return "direct_sales_order"
Exemple #16
0
class PostModelView(AdminRequiredMixin, ModelView):
    can_create = False

    form_ajax_refs = {
        'user':
        QueryAjaxModelLoader('user',
                             db.session,
                             User,
                             fields=['username'],
                             page_size=10)
    }
    form_excluded_columns = (
        'content_time',
        'post_tags',
    )

    column_list = ('user.username', 'title', 'url', 'created', 'edited')
    column_labels = {'user.username': '******', 'url': 'URL'}
    column_sortable_list = (
        'user.username',
        'title',
        'url',
        'created',
        'edited',
    )
    column_searchable_list = (
        'user.username',
        'title',
        'url',
    )
    column_filters = (
        FilterLike(User.username, 'Username'),
        FilterLike(Post.title, 'Title'),
        FilterLike(Post.url, 'URL'),
        DateTimeBetweenFilter(Post.created, 'Created'),
        DateTimeSmallerFilter(Post.created, 'Created'),
        DateTimeGreaterFilter(Post.created, 'Created'),
        DateTimeBetweenFilter(Post.edited, 'Edited'),
        DateTimeSmallerFilter(Post.edited, 'Edited'),
        DateTimeGreaterFilter(Post.edited, 'Edited'),
    )
    form_overrides = {
        'content': MarkdownField,
    }
    extra_css = ('//cdn.jsdelivr.net/simplemde/latest/simplemde.min.css', )

    def on_model_change(self, form, model, is_created):
        with suppress(AttributeError):
            if form.content.data:
                tags = {
                    _.group(1)
                    for _ in TAG_EXTRACTOR.finditer(form.content.data)
                }
                model.content_time = readtime.of_markdown(
                    form.content.data).minutes
                model.post_tags.clear()
                model.post_tags.extend((PostTag(_) for _ in tags))

    def _username_formatter(view, context, model, name):
        # `view` is current administrative view
        # `context` is instance of jinja2.runtime.Context
        # `model` is model instance
        # `name` is property name
        user = getattr(model, 'user')
        return Markup(
            '<img src="{}" width="20px" height="20px" class="img-circle"> {}'.
            format(escape(getattr(user, 'logotype')),
                   escape(getattr(user, 'username'))))

    def _url_formatter(self, context, model, name):
        user = getattr(model, 'user')
        url = getattr(model, name)
        full_url = url_for('post.post',
                           username=getattr(user, 'username'),
                           postname=url)
        return Markup('<a href="{}">{}</a>'.format(escape(full_url),
                                                   escape(url)))

    column_formatters = {
        'user.username': _username_formatter,
        'url': _url_formatter,
        'created': datetime_formatter,
        'edited': datetime_formatter,
    }
Exemple #17
0
class TransactionsModelView(OFXModelView):
    list_template = 'transactions.html'

    # column_default_sort = dict(field='date', sort_desc=True, absolute_value=False)
    column_default_sort = ('date', True)

    column_list = ('id', 'date', 'type', 'account', 'description', 'amount',
                   'debit_subaccount', 'credit_subaccount', 'journal_entry_id')

    column_filters = column_list

    column_searchable_list = ('description', )

    column_labels = dict(
        id='ID',
        account='From Account',
        date='Date Posted',
        journal_entry_id='JE',
    )

    column_formatters = dict(
        id=id_formatter,
        journal_entry_id=link_journal_entry_formatter,
        date=date_formatter,
        amount=currency_formatter,
        description=string_formatter,
        type=string_formatter,
    )

    column_display_actions = False

    ajax_subaccount_loader = QueryAjaxModelLoader(name='subaccounts',
                                                  session=db.session,
                                                  model=Subaccounts,
                                                  fields=('name', ),
                                                  page_size=10,
                                                  placeholder='Subaccount')

    form_ajax_refs = dict(subaccounts=ajax_subaccount_loader, )

    @expose('/', methods=('GET', 'POST'))
    def index_view(self):

        if request.method == 'POST':
            form = request.form.copy().to_dict()
            new_mapping = Mappings(
                source='ofx',
                keyword=form['keyword'],
                positive_credit_subaccount_id=form['subaccount'],
                negative_debit_subaccount_id=form['subaccount'],
            )
            try:
                db.session.add(new_mapping)
                db.session.commit()
            except IntegrityError:
                db.session.rollback()
            mapping_id, = (db.session.query(
                Mappings.id).filter(Mappings.source == 'ofx').filter(
                    Mappings.keyword == form['keyword']).one())
            apply_single_ofx_mapping(mapping_id)
            return redirect(url_for('banking/transactions.index_view'))

        class NewOFXTransactionMapping(Form):
            keyword = HiddenField()
            subaccount = AjaxSelectField(loader=self.ajax_subaccount_loader,
                                         allow_blank=False)

        new_mapping_form = NewOFXTransactionMapping()

        self._template_args['new_mapping_form'] = new_mapping_form
        return super(TransactionsModelView, self).index_view()

    @expose('/<expense_account>/<keyword>')
    def favorite(self, expense_account, keyword):
        new_mapping = Mappings()
        new_mapping.source = 'ofx'
        new_mapping.keyword = keyword
        new_mapping.positive_credit_subaccount_id = expense_account
        new_mapping.negative_debit_subaccount_id = expense_account
        try:
            db.session.add(new_mapping)
            db.session.commit()
        except IntegrityError:
            db.session.rollback()
        mapping_id, = (db.session.query(
            Mappings.id).filter(Mappings.source == 'ofx').filter(
                Mappings.keyword == keyword).one())
        apply_single_ofx_mapping(mapping_id)
        return redirect(url_for('banking/transactions.index_view'))

    @expose('/apply-all-mappings/')
    def apply_all_mappings_view(self):
        apply_all_mappings()
        return redirect(url_for('banking/transactions.index_view'))
Exemple #18
0
class FranchisePurchaseOrderAdmin(BasePurchaseOrderAdmin, DeleteValidator):

    type_code = const.FRANCHISE_PO_TYPE_KEY

    inline_models = (
        FranchisePurchaseOrderLineInlineAdmin(PurchaseOrderLine), )

    @property
    def role_identify(self):
        return "franchise_purchase_order"

    column_list = ('id', 'order_date', 'logistic_amount', 'goods_amount',
                   'total_amount', 'status', 'all_expenses', 'all_receivings',
                   'remark')

    form_columns = ('status', 'logistic_amount', 'order_date', 'goods_amount',
                    'total_amount', 'remark', 'lines')

    form_edit_rules = ('status', 'logistic_amount', 'order_date',
                       'goods_amount', 'total_amount', 'remark', 'lines')

    form_create_rules = ('status', 'order_date', 'logistic_amount', 'remark',
                         'lines')

    form_extra_fields = {
        "goods_amount":
        DisabledStringField(label=lazy_gettext('Goods Amount')),
        "total_amount":
        DisabledStringField(label=lazy_gettext('Total Amount')),
    }

    form_ajax_refs = {
        'product':
        QueryAjaxModelLoader(
            name='product',
            session=service.Info.get_db().session,
            model=Product,
            # --> Still need to filter the products by organization.
            # --> Line 209 is commented out, need to bring it back.
            fields=['name', 'mnemonic'])
    }

    column_sortable_list = (
        'id',
        'logistic_amount',
        'total_amount',
        ('status', 'status.display'),
        'goods_amount',
        'order_date',
    )

    column_details_list = ('id', 'status', 'logistic_amount', 'order_date',
                           'goods_amount', 'total_amount', 'remark', 'lines',
                           'all_expenses', 'all_receivings')

    column_searchable_list = ('status.display', 'remark')

    def edit_form(self, obj=None):
        form = super(FranchisePurchaseOrderAdmin, self).edit_form(obj)
        # Set query_factory for newly added line
        parent_org_id = obj.to_organization.id
        # If we uncomment follow line to limit the query to current organization
        # The AJAX look up fails.
        # form.lines.form.product.kwargs['query_factory'] = partial(
        #    Product.organization_filter, parent_org_id)
        if not security_util.user_has_role('purchase_price_view'):
            form_util.del_form_field(self, form, 'goods_amount')
            form_util.del_form_field(self, form, 'total_amount')
            form_util.del_inline_form_field(form.lines.form,
                                            form.lines.entries, 'total_amount')
        form_util.del_inline_form_field(form.lines.form, form.lines.entries,
                                        'unit_price')
        # Set option list of status available
        if obj.status.code in [
                const.PO_RECEIVED_STATUS_KEY,
                const.PO_PART_RECEIVED_STATUS_KEY,
                const.PO_PART_RECEIVED_STATUS_KEY, const.PO_ISSUED_STATUS_KEY,
                const.PO_DRAFT_STATUS_KEY
        ]:
            form.status.query = [
                EnumValues.get(obj.status.code),
            ]
        if obj.status.code == const.PO_DRAFT_STATUS_KEY:
            form.status.query.append(EnumValues.get(
                const.PO_ISSUED_STATUS_KEY))
        # Set product query option for old lines(forbid to change product for
        #  existing line)
        line_entries = form.lines.entries
        products = Product.organization_filter(parent_org_id).all()
        for sub_line in line_entries:
            sub_line.form.product.query = products
        return form

    def create_form(self, obj=None):
        form = super(FranchisePurchaseOrderAdmin, self).create_form(obj)
        form.status.query = [
            EnumValues.get(const.PO_DRAFT_STATUS_KEY),
        ]
        return form

    def on_model_change(self, form, model, is_created):
        from wtforms import ValidationError
        super(FranchisePurchaseOrderAdmin,
              self).on_model_change(form, model, is_created)
        for l in model.lines:
            if l.unit_price is None:
                l.unit_price = l.product.franchise_price
        if current_user.organization.type.code != const.FRANCHISE_STORE_ORG_TYPE_KEY:
            raise ValidationError(
                gettext(
                    "Your organization is not a franchise store and is not allowed to create franchise purchase order"
                ))
        if current_user.organization.parent is None:
            raise ValidationError(
                gettext(
                    "Franchise purchase order creation failed, your organization does not have a valid parent organization"
                ))
        if is_created:
            model.to_organization = current_user.organization.parent
        status = model.status
        if status.code == const.PO_ISSUED_STATUS_KEY:
            sales_order, incoming, expense = self.create_so_from_fpo(model)
            related_value = self.create_related_value(sales_order, model)
            db_util.save_objects_commit(sales_order, incoming, expense,
                                        related_value)

    @staticmethod
    def create_so_from_fpo(purchase_order):
        so_type = EnumValues.get(const.FRANCHISE_SO_TYPE_KEY)
        sales_order = SalesOrder()
        sales_order.id = db_util.get_next_id(SalesOrder)
        sales_order.order_date = purchase_order.order_date
        sales_order.type = so_type
        sales_order.remark = "PO ID: [{0}]".format(purchase_order.id)
        sales_order.organization = purchase_order.to_organization
        sales_order.status = EnumValues.get(const.SO_CREATED_STATUS_KEY)
        lines = []
        for line in purchase_order.lines:
            sol = SalesOrderLine()
            sol.unit_price = line.unit_price
            sol.quantity = line.quantity
            sol.sales_order = sales_order
            sol.product = line.product
            sol.remark = "PO Line ID:[{0}]".format(line.id)
            lines.append(sol)
        from psi.app.services import SalesOrderService
        incoming = SalesOrderService.create_or_update_incoming(sales_order)
        expense = SalesOrderService.create_or_update_expense(sales_order)
        return sales_order, incoming, expense

    @staticmethod
    def create_related_value(sales_order, purchase_order):
        from psi.app.models import RelatedValues
        rv = RelatedValues()
        rv.from_object_id = purchase_order.id
        rv.from_object_type = "PurchaseOrder"
        rv.to_object_id = sales_order.id
        rv.to_object_type = "SalesOrder"
        from psi.app.const import FRANCHISE_PO_TO_SO_RT_KEY
        related_type = EnumValues.get(FRANCHISE_PO_TO_SO_RT_KEY)
        rv.relation_type = related_type
        return rv
Exemple #19
0
class OrderModelView(RoleBasedModelView):
    details_modal = True
    edit_modal = True

    # Create form fields
    form_columns = ('name', 'product', 'quantity', 'assigned_machine', 'note')

    form_ajax_refs = {
        'product': {
            'fields': (Product.name, )
        },
        'assigned_machine':
        QueryAjaxModelLoader('assigned_machine',
                             db.session,
                             Machine,
                             filters=["status!='NOT_IN_USE'"],
                             fields=['id', 'name'],
                             page_size=10)
    }

    def _colors(view, context, model, name):
        html = color_boxes_html(model.product_colors)
        return Markup(html)

    def _time_to_complete(view, context, model, name):
        return display_time(model.estimated_time_to_complete)

    def _production_entries(view, context, model, name):
        html = ''
        for entry in model.production_entry_orders:
            html += href_link_html(entry.id, 'productionentry')

        return Markup(html)

    def _list_thumbnail(view, context, model, name):
        if not model.photo:
            return ''

        return Markup(
            '<img src="%s">' %
            url_for('static', filename=thumbgen_filename(model.photo)))

    column_formatters = {
        'Product Photo': _list_thumbnail,
        'Time To Complete': _time_to_complete,
        'Colors': _colors,
        'production_start_at': timestamp_formatter,
        'production_end_at': timestamp_formatter,
        'production_entry_orders': _production_entries
    }

    # List table columns
    column_list = (Order.id, Order.name, 'product', 'Product Photo', 'Colors',
                   Order.status, Order.quantity, 'completed',
                   'Time To Complete', 'production_entry_orders',
                   Order.raw_material_quantity, Order.assigned_machine_id,
                   Order.production_start_at, Order.production_end_at)

    column_sortable_list = [
        'id', 'name', 'product', 'status', 'quantity', 'completed',
        'estimated_time_to_complete', 'assigned_machine_id',
        'raw_material_quantity', 'production_start_at', 'production_end_at'
    ]

    column_searchable_list = (Order.id, Order.name, Order.status)
    column_filters = ('id', 'name', 'status', 'quantity',
                      'estimated_time_to_complete', 'raw_material_quantity',
                      'assigned_machine_id')

    # List column renaming
    column_labels = dict(production_entry_orders='Production Entries',
                         estimated_time_to_complete='Estimated Time',
                         production_start_at='Production Start',
                         production_end_at='Production End',
                         assigned_machine_id='Machine Id',
                         raw_material_quantity='Raw Material Bags')

    # Sort the data by id in descending order.
    column_default_sort = ('id', True)
Exemple #20
0
class StationIcesView(AdminView):

    db_session, *_ = get_db_session(get_database_uri(
            config.DB_HOST, config.DB_USERNAME,
            config.DB_PASSWORD, config.DB_NAME))
    form_ajax_refs = {'playlists': QueryAjaxModelLoader(
        'playlists', db_session, Playlist,
        filters=["station_id is NULL"], fields=['name'])}
    form_extra_fields = {
        'password': PasswordField('Password', [DataRequired()])
    }
    form_args = {
        'jingle': {
            'validators': [DataRequired()]
        }
    }
    column_list = ('id', 'name', 'genre', 'description', 'bitrate',
                   'crossfade',
                   'server_host', 'server_port', 'server_rotocol',
                   'server_mountpoint', 'play_jingle_after_songs_count',
                   'active', 'status',
                   )
    form_excluded_columns = ('playlists',)

    def show_status(self, context, model, name):
        markup_string = '<span class="glyphicon {icon}" ' \
                        'style="color:{color};font-size:40px;"></span>'
        if model.running:
            icon, color = "glyphicon-ok-sign", "green"
        else:
            icon, color = "glyphicon-minus-sign", "red"
        return Markup(markup_string.format(icon=icon, color=color))

    column_formatters = {'status': show_status}

    def create_model(self, form):
        """
            Create model from form.

            :param form:
                Form instance
        """
        try:
            app.logger.debug("Creating new station")
            model = self.model()
            app.logger.debug("Populating object")
            form.populate_obj(model)
            app.logger.debug("Add object to session")
            self.session.add(model)
            app.logger.debug("Flush session")
            self.session.flush()
            model.create(self.session)
        except IcesException as e:
            flash(e.message)
            app.logger.error(e.message)
            app.logger.debug("Rollback session during error")
            self.session.rollback()
            return False
        else:
            self.after_model_change(form, model, True)
        return model

    def update_model(self, form, model):
        """
            Update model from form.

            :param form:
                Form instance
            :param model:
                Model instance
        """
        try:
            app.logger.debug("Updating station")
            form.populate_obj(model)
            model.edit(self.session)
            self._on_model_change(form, model, False)
            app.logger.debug("Commit session")
            self.session.commit()
        except Exception as ex:
            app.logger.error(ex)
            if not self.handle_view_exception(ex):
                flash('Failed to update record.')
            app.logger.debug("Rollback session")
            self.session.rollback()
            return False
        else:
            self.after_model_change(form, model, False)
        return True
Exemple #21
0
class InventoryTransactionAdmin(ModelViewWithAccess, ModelWithLineFormatter):
    can_delete = False

    column_list = ('id', 'type', 'date', 'total_amount', 'it_receiving', 'it_shipping', 'remark')
    column_sortable_list = ('id', ('type', 'type.display'), 'total_amount', 'date',)
    form_columns = ('type', 'date', 'total_amount', 'remark', 'lines')
    form_create_rules = ('type', 'date', 'remark', 'lines',)
    form_edit_rules = ('type', 'date', 'remark', 'lines',)

    column_editable_list = ('remark',)

    column_filters = ('date',
                      FloatGreaterFilter(InventoryTransaction.total_amount, lazy_gettext('Total Amount')),
                      FloatSmallerFilter(InventoryTransaction.total_amount, lazy_gettext('Total Amount')),)
    column_searchable_list = ('type.display', 'remark')

    column_details_list = ('id', 'type', 'date', 'total_amount', 'remark', 'lines', 'it_receiving', 'it_shipping',)

    column_labels = {
        'id': lazy_gettext('id'),
        'type': lazy_gettext('Inventory Transaction Type'),
        'date': lazy_gettext('Date'),
        'total_amount': lazy_gettext('Total Amount'),
        'remark': lazy_gettext('Remark'),
        'lines': lazy_gettext('Lines'),
        'it_receiving': lazy_gettext('Related Receiving'),
        'it_shipping': lazy_gettext('Related Shipping'),
    }

    form_excluded_columns = ('it_shipping', 'it_receiving')

    form_args = dict(
        type=dict(query_factory=InventoryTransaction.manual_type_filter),
        date=dict(default=datetime.now()),
    )

    from psi.app.views.components import DisabledStringField

    form_extra_fields = {
        'total_amount': DisabledStringField(label=lazy_gettext('Total Amount')),
    }

    form_ajax_refs = {
        'product': QueryAjaxModelLoader(name='product',
                                        session=service.Info.get_db().session,
                                        model=Product,
                                        # --> Still need to filter the products by organization.
                                        # --> Line 209 is commented out, need to bring it back.
                                        fields=['name', 'mnemonic'])
    }

    column_formatters = {
        'it_receiving': receivings_formatter,
        'it_shipping': shipping_formatter,
        'date': default_date_formatter,
        'lines': line_formatter,
    }

    inline_models = (InventoryTransactionLineInlineAdmin(InventoryTransactionLine),)

    def get_list_columns(self):
        """
        This method is called instantly in list.html
        List of columns is decided runtime during render of the table
        Not decided during flask-admin blueprint startup.
        """
        columns = super(InventoryTransactionAdmin, self).get_list_columns()
        cols = ['total_amount']
        columns = security_util.filter_columns_by_role(
            columns, cols, 'purchase_price_view'
        )
        return columns

    def get_details_columns(self):
        cols = ['total_amount']
        columns = super(InventoryTransactionAdmin, self).get_details_columns()
        columns = security_util.filter_columns_by_role(
            columns, cols, 'purchase_price_view'
        )
        return columns

    @property
    def line_fields(self):
        if not security_util.user_has_role('purchase_price_view'):
            return [type_field, date_field, product_field, quantity_field,
                    saleable_quantity_field, remark_field]
        return [type_field, date_field, product_field, price_field,
                quantity_field, total_amount_field, saleable_quantity_field,
                remark_field]
Exemple #22
0
class AmazonItemView(PrivateModelView):
    list_template = 'amazon_items.html'

    can_edit = False
    can_create = False
    can_delete = False
    can_export = True
    column_display_actions = False

    column_list = ('id', 'journal_entry_id', 'order_status', 'title',
                   'quantity', 'purchase_price_per_unit', 'item_subtotal',
                   'item_subtotal_tax', 'item_total', 'currency',
                   'payment_instrument_type', 'category_id', 'shipment_date')
    column_filters = column_list
    column_searchable_list = ('title', 'category_id')
    # column_default_sort = {'field': 'id', 'sort_desc': True, 'absolute_value': False}
    column_default_sort = ('id', True)
    column_labels = dict(id='ID',
                         journal_entry_id='JE',
                         order_status='Status',
                         quantity='#',
                         purchase_price_per_unit='Price',
                         item_subtotal='Subtotal',
                         item_subtotal_tax='Tax',
                         item_total='Total',
                         payment_instrument_type='Payment',
                         category_id='Category',
                         shipment_date='Shipped')

    ajax_subaccount_loader = QueryAjaxModelLoader(
        'subaccounts',
        db.session,
        Subaccounts,
        fields=['name'],
        page_size=10,
        placeholder='Expense Subaccount')
    form_ajax_refs = {'subaccounts': ajax_subaccount_loader}

    @expose('/', methods=('GET', 'POST'))
    def index_view(self):
        if request.method == 'POST':
            form = request.form.copy().to_dict()
            new_mapping = Mappings()
            new_mapping.source = 'amazon'
            new_mapping.keyword = form['keyword']
            new_mapping.positive_debit_subaccount_id = form['subaccount']
            new_mapping.positive_credit_subaccount_id = 'Amazon Suspense Account'
            new_mapping.negative_debit_subaccount_id = 'Amazon Suspense Account'
            new_mapping.negative_credit_subaccount_id = form['subaccount']

            try:
                db.session.add(new_mapping)
                db.session.commit()
            except IntegrityError:
                db.session.rollback()
            mapping_id, = (db.session.query(
                Mappings.id).filter(Mappings.source == 'amazon').filter(
                    Mappings.keyword == form['keyword']).one())
            apply_single_amazon_mapping(mapping_id)
            return redirect(url_for('amazonitems.index_view'))

        class NewTransactionMapping(Form):
            keyword = HiddenField()
            subaccount = AjaxSelectField(loader=self.ajax_subaccount_loader,
                                         allow_blank=False)

        new_mapping_form = NewTransactionMapping()

        self._template_args['new_mapping_form'] = new_mapping_form
        return super(AmazonItemView, self).index_view()

    @expose('/apply-all-mappings/')
    def apply_all_mappings_view(self):
        apply_all_mappings()
        return redirect(url_for('amazonitems.index_view'))
Exemple #23
0
class EventView(CustomModelView):
    list_template = "admin/my_list.html"  # Override the default template
    form_ajax_refs = {
        'team':
        QueryAjaxModelLoader('team',
                             db.session,
                             Team,
                             fields=['name'],
                             page_size=10)
    }
    column_extra_row_actions = [  # Add a new action button
        TemplateLinkRowAction("custom_row_actions.activate_row",
                              "Activate Record"),
    ]

    @expose('/action/register_row', methods=('POST', ))
    def register_row(self, *args, **kwargs):
        event_id = request.form['rowid']
        #event_id = request.args.get('id')
        try:
            event = Event.query.get(event_id)
            if event.open_registration():
                event.save()

        except Exception as ex:
            if not self.handle_view_exception(ex):
                raise
            flash('Failed to progress event. %(error)s', 'error')

        return redirect(self.get_save_return_url(Event))

    @expose('/action/activate_row', methods=('POST', ))
    def activate_row(self, *args, **kwargs):
        event_id = request.form['rowid']
        #event_id = request.args.get('id')
        try:
            event = Event.query.get(event_id)
            if event.activate():
                event.save()

        except Exception as ex:
            if not self.handle_view_exception(ex):
                raise
            flash('Failed to progress event. %(error)s', 'error')

        return redirect(self.get_save_return_url(Event))

    @expose('/action/close_row', methods=('POST', ))
    def close_row(self, *args, **kwargs):
        event_id = request.form['rowid']
        #event_id = request.args.get('id')
        try:
            event = Event.query.get(event_id)
            if event.close():
                event.save()

        except Exception as ex:
            if not self.handle_view_exception(ex):
                raise
            flash('Failed to progress event. %(error)s', 'error')

        return redirect(self.get_save_return_url(Event))

    @action(
        'open_registration', 'Open Registration',
        'Are you sure you want to start the registration process for the selected rows?'
    )
    def action_open_registration(self, ids):
        try:
            query = Event.query.filter(Event.id.in_(ids))

            count = 0
            events = query.all()
            for event in events:
                if event.open_registration():
                    event.save()
                    count += 1
            flash(
                '{} of {} event(s) were progressed to \"Registering\" status.'.
                format(count, len(ids)))
        except Exception as ex:
            if not self.handle_view_exception(ex):
                raise

            flash('Failed to progress event. %(error)s', 'error')

    @action(
        'activate', 'Close Registration',
        'Are you sure you want to close the registration process for the selected rows?'
    )
    def action_activate(self, ids):
        try:
            query = Event.query.filter(Event.id.in_(ids))

            count = 0
            events = query.all()
            for event in events:
                if event.activate():
                    event.save()
                    count += 1
            flash('{} of {} event(s) were progressed to \"Active\" status.'.
                  format(count, len(ids)))
        except Exception as ex:
            if not self.handle_view_exception(ex):
                raise

            flash('Failed to progress event. %(error)s', 'error')

    @action('close', 'Close Event',
            'Are you sure you want to close the event?')
    def action_activate(self, ids):
        try:
            query = Event.query.filter(Event.id.in_(ids))

            count = 0
            events = query.all()
            for event in events:
                if event.close():
                    event.save()
                    count += 1
            flash('{} of {} event(s) were progressed to \"Closed\" status.'.
                  format(count, len(ids)))
        except Exception as ex:
            if not self.handle_view_exception(ex):
                raise

            flash('Failed to progress event. %(error)s', 'error')