user_area.py 6.05 KB
import colander
import logging
from deform import widget
from pyramid.view import view_config
from . import BaseView, btn_upload
from ...models import DBSession,ResDesa, User, UserArea
from .desa import desa_widget, get_desa_list
from pyramid.i18n import TranslationStringFactory

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

class ListSchema(colander.Schema):
    id = colander.SchemaNode(
        colander.Integer(),
        title="Action"
    )
    user_name = colander.SchemaNode(
        colander.String(),
        field=User.user_name,
        title="User"
    )
    desa_kd = colander.SchemaNode(
        colander.String(),
        field=ResDesa.kode)
    desa_name = colander.SchemaNode(
        colander.String(),
        field=ResDesa.nama)

@colander.deferred
def desa_checkbox_widget(node, kw):
    values = kw.get('desa_list', [])
    return widget.CheckboxChoiceWidget(values=values)

class AddSchema(colander.Schema):
    user_id = colander.SchemaNode(
        colander.Integer(),
        widget=widget.SelectWidget(values=User.get_list()),
        oid="user_id",
        title="User",
    )
    desa_id = colander.SchemaNode(
        colander.Set(),
        widget=desa_checkbox_widget,
        oid="desa_id",
        title="Kelurahan/Desa", )


class EditSchema(AddSchema):
    id = colander.SchemaNode(colander.String(),
                             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.list_route = 'user-area'
        self.table = UserArea
        self.list_buttons = self.list_buttons + (btn_upload,)
        
    def list_join(self, query, **kwargs):
        return query.outerjoin(ResDesa, ResDesa.id == self.table.desa_id) \
            .outerjoin(User, User.id == self.table.user_id) \

    @view_config(route_name='user-area', renderer='templates/table.pt',
                 permission='user-view')
    def view_list(self, **kwargs):
        return super().view_list(**kwargs)

    @view_config(route_name='user-area-act', renderer='json',
                 permission='user-view')
    def view_act(self):
        return super().view_act()
    
    def get_bindings(self, row=None):
        return {
            "desa_list": get_desa_list()
        }
    @view_config(route_name='user-area-add', renderer='templates/form.pt',
                 permission='user-edit')
    def view_add(self):
        return super().view_add()

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

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

    @view_config(route_name='user-area-edit', renderer='templates/form.pt',
                 permission='user-edit')
    def view_edit(self):
        return super().view_edit()
    
    def save_request(self, values, row=None):
        # Ambil user_id dari values
        user_id = values.get("user_id")
        if not user_id:
            return None  # Tidak ada user_id, kembalikan None atau tangani sesuai kebutuhan

        # Jika ada departemen_id dalam values
        if "desa_id" in values:
            # Ambil departemen yang sudah ada untuk user ini
            existing_desa = self.get_existing_desa(user_id)

            # Konversi departemen_id dari set ke set of strings, filter None
            selected_desa = set(
                str(desa_id) for desa_id in values["desa_id"]
                if desa_id is not None and str(desa_id) != "None"
            )

            # Departemen yang tidak dipilih lagi (akan dihapus)
            unused_desa = existing_desa - selected_desa

            # Hapus departemen yang tidak dipilih lagi, pastikan hanya integer yang valid
            if unused_desa:
                valid_unused = [int(d) for d in unused_desa if d.isdigit()]
                if valid_unused:
                    DBSession.query(UserArea).filter_by(user_id=user_id) \
                        .filter(UserArea.desa_id.in_(valid_unused)) \
                        .delete(synchronize_session=False)

            # Departemen baru yang dipilih (akan ditambahkan)
            new_desa = selected_desa - existing_desa
            log.debug(f"get_values new_desa: {new_desa}")
            #sys.exit("Age less than 18")
            # Tambahkan departemen baru, periksa duplikat sebelum insert
            for desa_id in new_desa:
                if desa_id.isdigit():  # Pastikan hanya angka yang diproses
                    # Cek apakah kombinasi user_id dan departemen_id sudah ada
                    exists = DBSession.query(UserArea).filter_by(
                        user_id=user_id,
                        desa_id=int(desa_id)
                    ).first()
                    if not exists:  # Hanya tambahkan jika belum ada
                        new_row = UserArea(
                            user_id=user_id,
                            desa_id=int(desa_id)  # Konversi ke integer
                        )
                        DBSession.add(new_row)

        # Commit semua perubahan
        DBSession.flush()
        return row  # Kembalikan row jika ada, atau None jika tidak digunakan

    def get_existing_desa(self, user_id):
        q = DBSession.query(UserArea).filter_by(user_id=user_id)
        r = []
        for ug in q:
            r.append(str(ug.desa_id))
        return set(r)
    
    def get_values(self, row, istime=False):
        d = super(Views, self).get_values(row, istime)
        d["desa_id"] = self.get_existing_desa(row.user_id)
        return d