user_dep.py 10.8 KB
import colander
import os
import logging
from deform import widget
from pyramid.view import view_config
from . import BaseView, button_import
from ...models import User, DepartemenUser, Departemen, DBSession
from opensipkd.tools.report import open_rml_row, csv_response, open_rml_pdf, pdf_response, file_response
from .departemen import get_departemen_list
from .user import user_list
from pyramid.i18n import TranslationStringFactory
from pyramid.path import AssetResolver
from . import BaseView, button_import, get_params
from opensipkd.tools import get_random_string
from pyramid.httpexceptions import HTTPFound

_ = TranslationStringFactory('myapp')
log = logging.getLogger(__name__)

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

class ListSchema(colander.Schema):
    id = colander.SchemaNode(
        colander.Integer(),
        title="Action"
    )
    user_name = colander.SchemaNode(
        colander.String(),
        field=User.user_name,
        title="User"
    )
    departemen_name = colander.SchemaNode(
        colander.String(),
        field=Departemen.nama,
        title="Departemen"
    )

@colander.deferred
def departemen_checkbox_widget(node, kw):
    values = kw.get('departemen_list', [])
    return widget.CheckboxChoiceWidget(values=values, multiple=True)

def validate_departemen_required(node, value):
    """Validator untuk memastikan setidaknya satu departemen dipilih"""
    if not value or len(value) == 0:
        raise colander.Invalid(node, "Departemen wajib diisi. Pilih setidaknya satu departemen.")

class AddSchema(colander.Schema):
    user_id = colander.SchemaNode(
        colander.Integer(),
        widget=widget.SelectWidget(values=User.get_list()),
        oid="user_id",
        title="User",
    )
    departemen_id = colander.SchemaNode(
        colander.Set(),
        widget=departemen_checkbox_widget,
        oid="departemen_id",
        title="Departemen",
        validator=validate_departemen_required  # Tambahkan validator wajib
    )

class EditSchema(AddSchema):
    id = colander.SchemaNode(
        colander.String(),
        missing=colander.drop,
        widget=widget.HiddenWidget()
    )
    # Override user_id agar tidak bisa diubah dan tidak wajib saat edit
    user_id = colander.SchemaNode(
        colander.Integer(),
        widget=widget.SelectWidget(values=User.get_list(), readonly=True),  # Readonly untuk mencegah perubahan
        oid="user_id",
        title="User",
        missing=colander.drop  # Tidak wajib saat edit
    )
    # Override departemen_id agar tidak wajib saat edit
    departemen_id = colander.SchemaNode(
        colander.Set(),
        widget=departemen_checkbox_widget,
        oid="departemen_id",
        title="Departemen",
        validator=None  # Tidak wajib saat edit
    )

class Views(BaseView):
    def __init__(self, request):
        super().__init__(request)
        self.request = request
        self.list_schema = ListSchema
        self.add_schema = AddSchema
        self.edit_schema = EditSchema
        self.list_route = 'user-departemen'
        self.table = DepartemenUser
        self.list_buttons = self.list_buttons + self.list_report + (button_import,)
        path = os.path.dirname(__file__)
        path = os.path.dirname(path)

    def list_join(self, query, **kwargs):
        return query.outerjoin(Departemen, Departemen.id == self.table.departemen_id) \
            .outerjoin(User, User.id == self.table.user_id)

    @view_config(route_name='user-departemen', renderer='templates/table.pt',
                 permission='user-view')
    def view_list(self, **kwargs):
        return super().view_list(**kwargs)
    
    def get_module_path(self, module_name):
        a = AssetResolver(module_name)
        resolver = a.resolve('')
        return resolver.abspath()

    def pdf_response(self, **kwargs):
        from opensipkd.base.tools.report import jasper_export
        path = self.get_module_path('opensipkd.base')
        logo = os.path.join(path, 'static', 'img', 'logo.png')
        report_file = os.path.join(path, 'reports', 'userdep1.jrxml')
        
        parameters = {
            "judul": get_params('company', "openSIPKD"), 
            "alamat_lengkap": get_params('address', "Bekasi"),
            "logo": logo
        }
        filename = jasper_export(report_file, parameters=parameters)
        return file_response(self.req, filename=filename[0])
        
    @staticmethod
    def query_register():
        return DBSession.query(DepartemenUser.user_id, DepartemenUser.departemen_id).order_by(DepartemenUser.user_id)

    def csv_response(self, **kwargs):
        query = self.query_register()
        row = query.first()
        header = row._mapping.keys()
        rows = [list(item) for item in query.all()]
        filename = f"{get_random_string(16)}.csv"
        value = {
            'header': header,
            'rows': rows,
        }
        return csv_response(self.req, value, filename)

    @view_config(route_name='user-departemen-act', renderer='json',
                 permission='user-view')
    def view_act(self):
        return super().view_act()

    def get_bindings(self, row=None):
        bindings = {
            "departemen_list": get_departemen_list(),
            "user_list": user_list()
        }
        if row and hasattr(row, 'user_id'):
            existing_depts = self.get_existing_departemen(row.user_id)
            bindings["default_values"] = {
                "user_id": row.user_id,
                "departemen_id": list(existing_depts)
            }
        return bindings

    @view_config(route_name='user-departemen-add', renderer='templates/form.pt',
                 permission='user-edit')
    def view_add(self):
        return super().view_add()

    @view_config(route_name='user-departemen-view', renderer='templates/form.pt',
                 permission='user-view')
    def view_view(self):
        return super().view_view()

    @view_config(route_name='user-departemen-delete', renderer='templates/form.pt',
                 permission='user-edit')
    def view_delete(self):
        return super().view_delete()

    @view_config(route_name='user-departemen-edit', renderer='templates/form.pt',
                 permission='user-edit')
    def view_edit(self):
        response = super().view_edit()
        if isinstance(response, dict):
            # print(f"Edit response: {response}")
            if self.request.method == 'POST':
                form = response.get('form')
                if form.validate():
                    values = form.data
                    row = DBSession.query(DepartemenUser).filter_by(id=self.request.matchdict['id']).first()
                    updated_row = self.save_request(values, row)
                    if updated_row:
                        self.request.session.flash("Data berhasil diperbarui.", "success")
                        return HTTPFound(location=self.request.route_url('user-departemen'))
                    else:
                        self.request.session.flash("Gagal menyimpan perubahan.", "error")
        return response

    @view_config(route_name='user-departemen-upload',
                 renderer='templates/form.pt', permission='user-upload')
    def view_upload(self):
        self.upload_keys = ["user_id"]
        return super(Views, self).view_upload(exts=(".csv", ".tsv"))

    def save_request(self, values, row=None):
        # print(f"Values received in save_request: {values}")
        # print(f"Row before save: {row}")

        # Saat edit, gunakan user_id dari row yang ada
        user_id = row.user_id if row else values.get("user_id")
        # if not user_id:
            # print("No user_id found, returning None")
            # return None

        if "departemen_id" in values:
            selected_departemen = set(
                str(departemen_id) for departemen_id in values["departemen_id"]
                if departemen_id is not None and str(departemen_id) != "None"
            )
            # Batasi ke maksimal dua pilihan
            selected_list = sorted(selected_departemen)[:2]
            dept1 = int(selected_list[0]) if selected_list else None
            dept2 = int(selected_list[1]) if len(selected_list) > 1 else None

            # Cari entri yang sudah ada untuk user_id
            existing_row = DBSession.query(DepartemenUser).filter_by(user_id=user_id).first()

            if row and row.user_id != user_id:
                # Jika user_id berubah (tidak seharusnya terjadi saat edit)
                DBSession.query(DepartemenUser).filter_by(user_id=row.user_id).delete()
                if selected_list:
                    new_row = DepartemenUser(
                        user_id=user_id,
                        departemen_id=dept1,
                        sub_departemen=dept2
                    )
                    DBSession.add(new_row)
                    row = new_row
                else:
                    row = None
            else:
                # Jika user_id sama atau ini adalah tambah baru
                if existing_row:
                    # Update entri yang sudah ada jika user_id sama
                    if selected_list:
                        existing_row.departemen_id = dept1
                        existing_row.sub_departemen = dept2
                        #print(f"Updated existing row: {existing_row}")
                    row = existing_row
                else:
                    # Buat entri baru jika belum ada
                    if selected_list:  # Ini akan selalu ada saat tambah karena validator
                        new_row = DepartemenUser(
                            user_id=user_id,
                            departemen_id=dept1,
                            sub_departemen=dept2
                        )
                        DBSession.add(new_row)
                        #print(f"Created new row: {new_row}")
                        row = new_row
                    else:
                        row = None

        try:
            DBSession.flush()
            #print(f"Row after save: {row}")raise exception
        except Exception as e:
            DBSession.rollback()
            print(e)
            self.request.session.flash(f"Gagal menyimpan: {str(e)}", "error")
            return e

        return row

    def get_existing_departemen(self, user_id):
        row = DBSession.query(DepartemenUser).filter_by(user_id=user_id).first()
        result = set()
        if row:
            if row.departemen_id:
                result.add(str(row.departemen_id))
            if row.sub_departemen:
                result.add(str(row.sub_departemen))
        return result

    def get_values(self, row, istime=False):
        d = super(Views, self).get_values(row, istime)
        d["departemen_id"] = self.get_existing_departemen(row.user_id)
        return d