departemen.py 12.9 KB
from datetime import datetime

import colander
from deform import widget
from opensipkd.models import (
    DBSession, Departemen, Partner, PartnerDepartemen, ResCompany)
from opensipkd.tools import (get_settings)
from opensipkd.tools.buttons import btn_upload
from sqlalchemy import func
from sqlalchemy.orm import aliased

from .company import company_widget
from .. import get_params
from ..views import BaseView

SESS_ADD_FAILED = 'Tambah departemen gagal'
SESS_EDIT_FAILED = 'Edit departemen gagal'


def get_departemen_list():
    r = [("", "--Pilih Departemen--")]
    q = DBSession.query(Departemen).order_by(Departemen.nama)
    for row in q:
        g = (str(row.id), (f"{row.kode}/ {row.nama}"))
        r.append(g)
    return r


@colander.deferred
def departemen_widget(node, kw):
    values = kw.get('departemen_list', [])
    return widget.Select2Widget(values=values, placeholder="Pilih Departemen")


def departemen_widget_form():
    return widget.AutocompleteInputWidget(
        size=60, min_length=3,
        requirements=(("typeahead", None), ("deform", None),
                      {"js": "opensipkd.base:static/js/form/departemen_form.js"}),
    )


dep_alias = aliased(Departemen)


class ListSchema(colander.Schema):
    id = colander.SchemaNode(
        colander.String(),
        title="Action",
        visible=False)
    kode = colander.SchemaNode(
        colander.String()
    )
    nama = colander.SchemaNode(
        colander.String(),
    )
    status = colander.SchemaNode(
        colander.Boolean(),
        title="Status", width='50pt',
        widget=widget.CheckboxWidget(true_val='1', false_val='0'))
    level_id = colander.SchemaNode(
        colander.Integer(),
        title="Level",
        width='40pt')
    parent = colander.SchemaNode(
        colander.String(),
        title="Induk",
        field=dep_alias.nama)
    company_nm = colander.SchemaNode(
        colander.String(),
        title="Company",
        field=ResCompany.nama)


class AddSchema(colander.Schema):
    parent_id = colander.SchemaNode(
        colander.Integer(),
        widget=widget.HiddenWidget(),
        missing=colander.drop,
        oid="parent_id",
    )
    parent_nm = colander.SchemaNode(
        colander.String(), missing=colander.drop,
        widget=widget.AutocompleteInputWidget(
            size=60,
            min_length=3,
            requirements=(("typeahead", None), ("deform", None),
                          {"js": "opensipkd.base:static/js/form/departemen.js"}),
            # options={"allowClear": True}
        ),
        oid="parent_nm", title="Induk")

    parent_kd = colander.SchemaNode(
        colander.String(),
        widget=widget.TextInputWidget(css_class="readonly"),
        missing=colander.drop,
        oid="parent_kd", title="Kode Induk")

    kode = colander.SchemaNode(
        colander.String(),
        validator=colander.Length(max=32),
        oid="kode")

    nama = colander.SchemaNode(
        colander.String(),
        validator=colander.Length(max=128),
        oid="nama")

    singkat = colander.SchemaNode(
        colander.String(),
        missing=colander.drop,
        oid="singkat",
        default="")

    kategori = colander.SchemaNode(
        colander.String(),
        missing=colander.drop,
        oid="kategori",
        default="")

    alamat = colander.SchemaNode(
        colander.String(),
        missing=colander.drop,
        oid="alamat",
        default="")
    company_id = colander.SchemaNode(
        colander.Integer(),
        widget=company_widget,
        missing=colander.drop,
        oid="company_id")

    status = colander.SchemaNode(
        colander.Integer(),
        widget=widget.CheckboxWidget(true_val='1', false_val='0'),
        default = 0,
        oid="status")

    def after_bind(self, schema, kwargs):
        request = kwargs["request"]
        self["parent_nm"].widget.values = f"{request.route_url('departemen-act', act='hon')}"
        if request.user.company_id:
            self["company_id"].widget = widget.HiddenWidget()
        self["company_id"].default = request.user.company_id


class EditSchema(AddSchema):
    id = colander.SchemaNode(
        colander.Integer(),
        missing=colander.drop,
        widget=widget.HiddenWidget(readonly=True))


class Views(BaseView):
    def __init__(self, request):
        super().__init__(request)
        self.list_schema = ListSchema
        self.add_schema = AddSchema
        self.edit_schema = EditSchema
        self.table = Departemen
        self.list_route = 'departemen'
        self.form_scripts = ""
        self.list_buttons = self.list_buttons + (btn_upload,)

    def view_buttons(self, row):
        buttons = super().view_buttons()
        return buttons + (btn_upload,)

    def form_validator(self, form, value):
        def err_kode():
            msg = 'Kode %s sudah digunakan oleh %s' % (
                value['kode'], found.nama)
            exc = colander.Invalid(form, msg)
            exc["kode"] = msg
            raise exc

        def err_nama():
            raise colander.Invalid(
                form, 'Uraian %s sudah digunakan oleh kode %s' % (
                                       value['nama'], found.kode))

        if 'id' in form.request.matchdict:
            uid = form.request.matchdict['id']
            q = DBSession.query(Departemen).filter_by(id=uid)
            current = q.first()
        else:
            current = None

        found = Departemen.query_kode(value['kode'])
        if "company_id" in value and value["company_id"]:
            found = found.filter_by(company_id=value["company_id"]).first()
        else:
            found = self.filter_company(found).first()
        if current:
            if found and found.id != current.id:
                err_kode()
        elif found:
            err_kode()

        found = Departemen.query_nama(value['nama'])
        if "company_id" in value and value["company_id"]:
            found = found.filter_by(company_id=value["company_id"]).first()
        else:
            found = self.filter_company(found).first()
        if current:
            if found and found.id != current.id:
                err_nama()
        elif found:
            err_nama()

    def update_children(self, children):
        for child in children:
            child.level_id = child.parent.level_id + 1
            DBSession.add(child)
            DBSession.flush()
            if child.children:
                self.update_children(child.children)

    def save_request(self, values, row=None):  # save(self, row, values):
        # for k, v in values.items():
        #     if not v:
        #         setattr(row, k, None)

        values["level_id"] = 1
        if "parent_id" in values and values["parent_id"]:
            qry_parent = self.table.query_id(values["parent_id"])
            parent = qry_parent.first()
            if parent and parent.level_id:
                values["level_id"] = parent.level_id + 1

        if "parent_id" not in values:
            values["parent_id"] = None

        row = super().save_request(values, row)
        return row

    def list_join(self, query):
        query = query.outerjoin(
            dep_alias, Departemen.parent_id == dep_alias.id)\
            .outerjoin(
            ResCompany, self.table.company_id == ResCompany.id
        )
        return query

    def view_act(self):
        request = self.req
        # ses = request.session
        params = request.params
        url_dict = request.matchdict
        # dep_alias = aliased(Departemen)
        # if url_dict['act'] == 'grid':
        #     columns = [ColumnDT(Departemen.id, mData='id'),
        #                ColumnDT(Departemen.kode, mData='kode'),
        #                ColumnDT(Departemen.nama, mData='nama'),
        #                ColumnDT(dep_alias.nama, mData='parent'),
        #                ColumnDT(Departemen.status, mData='status'),
        #                ColumnDT(Departemen.level_id, mData='level_id'),
        #                ColumnDT(ResCompany.nama, mData='company_nm'), ]
        #     query = DBSession.query().select_from(Departemen).outerjoin(
        #         dep_alias, Departemen.parent_id == dep_alias.id).outerjoin(
        #         ResCompany, self.table.company_id == ResCompany.id
        #     )
        #     query = self.filter_company(query)
        #     row_table = DataTables(request.GET, query, columns)
        #     return row_table.output_result()

        # el
        if url_dict['act'] == 'hon':
            term = 'term' in params and params['term'] or ''
            q = DBSession.query(Departemen). \
                filter(Departemen.status == 1,
                       Departemen.nama.ilike('%%%s%%' % term)) \
                .order_by(
                Departemen.nama)
            if self.req.user.company_id:
                q = q.filter(Departemen.company_id == self.req.user.company_id)
            rows = q.all()
            r = []
            for k in rows:
                d = dict(id=k.id, value=k.nama, kode=k.kode, nama=k.nama,
                         level_id=k.level_id)
                r.append(d)
            return r

        elif url_dict['act'] == 'honk':
            term = 'term' in params and params['term'] or ''
            q = DBSession.query(Departemen) \
                .filter(Departemen.status == 1,
                        func.concat(Departemen.nama, ';',
                                    Departemen.kode)
                        .ilike('%%%s%%' % term)) \
                .order_by(Departemen.nama)
            q = self.filter_company(q)
            rows = q.all()
            r = []
            for k in rows:
                d = dict(id=k.id, value=k.nama + ';' + k.kode, kode=k.kode,
                         nama=k.nama, level_id=k.level_id)
                r.append(d)
            return r

        elif url_dict['act'] == 'hon_level':
            # todo Check ulang untuk hon
            term = 'term' in params and params['term'] or ''
            settings = get_settings()
            level_id = get_params('departemen_chg_id', 0)
            q = DBSession.query(Departemen).filter(Departemen.status == 1,
                                                   Departemen.nama.ilike(
                                                       '%%%s%%' %
                                                       term)).order_by(
                Departemen.nama)
            if self.req.user.company_id:
                q = q.filter(Departemen.company_id == self.req.user.company_id)
            if int(level_id) > 0:
                q = q.filter(Departemen.level_id == int(level_id))
            if request.user.id > 1 and not request.has_permission(
                    "departemen-all"):
                partner = Partner.query_id(request.user.id).first()
                if partner:
                    PartnerDepartemen.query_jabatan(partner.id, datetime.now())
                user_dep = PartnerDepartemen.query_user_id().first()
                if not user_dep:
                    return []

                kode = user_dep.departemen.kode
                if user_dep.sub_departemen:
                    q = q.filter(Departemen.kode.ilike('{}%'.format(kode)))
                else:
                    q = q.filter(Departemen.kode == kode)

            rows = q.all()
            r = []
            for k in rows:
                d = dict(id=k.id, value=k.nama, kode=k.kode, nama=k.nama,
                         level_id=k.level_id)
                r.append(d)
            return r

        elif url_dict['act'] == 'hon_all':
            term = 'term' in params and params['term'] or ''
            settings = get_settings()
            level_id = 'departemen_chg_id' in settings and settings[
                'departemen_chg_id'] or 0
            q = DBSession.query(Departemen).filter(Departemen.status == 1,
                                                   Departemen.nama.ilike(
                                                       '%%%s%%' %
                                                       term)).order_by(
                Departemen.nama)
            if self.req.user.company_id:
                q = q.filter(Departemen.company_id == self.req.user.company_id)
            if int(level_id) > 0:
                q = q.filter(Departemen.level_id == int(level_id))

            rows = q.all()
            r = []
            for k in rows:
                d = dict(id=k.id, value=k.nama, kode=k.kode, nama=k.nama,
                         level_id=k.level_id)
                r.append(d)
            return r
        else:
            return super().view_act()

    def get_bindings(self, row=None):
        return {"company_list": ResCompany.get_list()}

    def view_upload(self):
        return super().view_upload(exts=('.csv', '.tsv'), delimiter="\t")

    def get_values(self, row, values=None):
        if not values:
            values = row.to_dict()
        if 'parent_id' in values and values['parent_id']:
            parent = row.parent
            values["parent_nm"] = parent.nama
            values["parent_kd"] = parent.kode
        return values