Add error handling for table creation in Alembic migrations

1 parent 884d29c3
...@@ -18,6 +18,7 @@ depends_on = None ...@@ -18,6 +18,7 @@ depends_on = None
def upgrade(): def upgrade():
# ### commands auto generated by Alembic - please adjust! ### # ### commands auto generated by Alembic - please adjust! ###
try:
op.create_table('eselon', op.create_table('eselon',
sa.Column('pangkat', sa.String(length=32), nullable=True), sa.Column('pangkat', sa.String(length=32), nullable=True),
sa.Column('ruang', sa.String(length=1), nullable=True), sa.Column('ruang', sa.String(length=1), nullable=True),
...@@ -29,10 +30,14 @@ def upgrade(): ...@@ -29,10 +30,14 @@ def upgrade():
sa.Column('updated', sa.DateTime(), nullable=True), sa.Column('updated', sa.DateTime(), nullable=True),
sa.Column('create_uid', sa.Integer(), nullable=True), sa.Column('create_uid', sa.Integer(), nullable=True),
sa.Column('update_uid', sa.Integer(), nullable=True), sa.Column('update_uid', sa.Integer(), nullable=True),
sa.Column('id', sa.Integer(), nullable=False), sa.Column('id', sa.Integer(), sa.Identity(always=True),
primary_key=True, nullable=False),
sa.PrimaryKeyConstraint('id', name=op.f('pk_eselon')), sa.PrimaryKeyConstraint('id', name=op.f('pk_eselon')),
# schema='public' # schema='public'
) )
except Exception as e:
print(str(e))
try:
op.create_table('pangkat', op.create_table('pangkat',
sa.Column('pangkat', sa.String(length=32), nullable=True), sa.Column('pangkat', sa.String(length=32), nullable=True),
sa.Column('ruang', sa.String(length=1), nullable=True), sa.Column('ruang', sa.String(length=1), nullable=True),
...@@ -43,10 +48,14 @@ def upgrade(): ...@@ -43,10 +48,14 @@ def upgrade():
sa.Column('updated', sa.DateTime(), nullable=True), sa.Column('updated', sa.DateTime(), nullable=True),
sa.Column('create_uid', sa.Integer(), nullable=True), sa.Column('create_uid', sa.Integer(), nullable=True),
sa.Column('update_uid', sa.Integer(), nullable=True), sa.Column('update_uid', sa.Integer(), nullable=True),
sa.Column('id', sa.Integer(), nullable=False), sa.Column('id', sa.Integer(), sa.Identity(always=True),
primary_key=True, nullable=False),
sa.PrimaryKeyConstraint('id', name=op.f('pk_pangkat')), sa.PrimaryKeyConstraint('id', name=op.f('pk_pangkat')),
# schema='public' # schema='public'
) )
except Exception as e:
print(str(e))
try:
op.create_table('jabatan', op.create_table('jabatan',
sa.Column('jenis', sa.SmallInteger(), nullable=True), sa.Column('jenis', sa.SmallInteger(), nullable=True),
sa.Column('nama_lain', sa.String( sa.Column('nama_lain', sa.String(
...@@ -61,19 +70,24 @@ def upgrade(): ...@@ -61,19 +70,24 @@ def upgrade():
sa.Column('updated', sa.DateTime(), nullable=True), sa.Column('updated', sa.DateTime(), nullable=True),
sa.Column('create_uid', sa.Integer(), nullable=True), sa.Column('create_uid', sa.Integer(), nullable=True),
sa.Column('update_uid', sa.Integer(), nullable=True), sa.Column('update_uid', sa.Integer(), nullable=True),
sa.Column('id', sa.Integer(), nullable=False), sa.Column('id', sa.Integer(), sa.Identity(always=True),
primary_key=True, nullable=False),
sa.ForeignKeyConstraint(['eselon_id'], ['eselon.id'], name=op.f( sa.ForeignKeyConstraint(['eselon_id'], ['eselon.id'], name=op.f(
'fk_jabatan_eselon_id_eselon')), 'fk_jabatan_eselon_id_eselon')),
sa.PrimaryKeyConstraint('id', name=op.f('pk_jabatan')), sa.PrimaryKeyConstraint('id', name=op.f('pk_jabatan')),
# schema='public' # schema='public'
) )
except Exception as e:
print(str(e))
try:
op.create_table('partner_departemen', op.create_table('partner_departemen',
sa.Column('partner_id', sa.Integer(), nullable=True), sa.Column('partner_id', sa.Integer(), nullable=True),
sa.Column('departemen_id', sa.Integer(), nullable=True), sa.Column('departemen_id', sa.Integer(), nullable=True),
sa.Column('jabatan_id', sa.SmallInteger(), nullable=True), sa.Column('jabatan_id', sa.SmallInteger(), nullable=True),
sa.Column('mulai', sa.DateTime(), nullable=True), sa.Column('mulai', sa.DateTime(), nullable=True),
sa.Column('selesai', sa.DateTime(), nullable=True), sa.Column('selesai', sa.DateTime(), nullable=True),
sa.Column('id', sa.Integer(), nullable=False), sa.Column('id', sa.Integer(), sa.Identity(always=True),
primary_key=True, nullable=False),
sa.ForeignKeyConstraint(['departemen_id'], ['departemen.id'], name=op.f( sa.ForeignKeyConstraint(['departemen_id'], ['departemen.id'], name=op.f(
'fk_partner_departemen_departemen_id_departemen')), 'fk_partner_departemen_departemen_id_departemen')),
sa.ForeignKeyConstraint(['jabatan_id'], ['jabatan.id'], name=op.f( sa.ForeignKeyConstraint(['jabatan_id'], ['jabatan.id'], name=op.f(
...@@ -86,6 +100,9 @@ def upgrade(): ...@@ -86,6 +100,9 @@ def upgrade():
'jabatan_id', 'mulai', name='partner_dept_uq'), 'jabatan_id', 'mulai', name='partner_dept_uq'),
# schema='public' # schema='public'
) )
except Exception as e:
print(str(e))
# ### end Alembic commands ### # ### end Alembic commands ###
......
...@@ -30,7 +30,8 @@ def upgrade(): ...@@ -30,7 +30,8 @@ def upgrade():
sa.Column('updated', sa.DateTime(), nullable=True), sa.Column('updated', sa.DateTime(), nullable=True),
sa.Column('create_uid', sa.Integer(), nullable=True), sa.Column('create_uid', sa.Integer(), nullable=True),
sa.Column('update_uid', sa.Integer(), nullable=True), sa.Column('update_uid', sa.Integer(), nullable=True),
sa.Column('id', sa.Integer(), nullable=False), sa.Column('id', sa.Integer(), sa.Identity(always=True),
primary_key=True , nullable=False),
sa.PrimaryKeyConstraint('id', name=op.f('pk_text_printers')), sa.PrimaryKeyConstraint('id', name=op.f('pk_text_printers')),
# schema='public' # schema='public'
) )
......
from datetime import datetime, timezone
import sqlalchemy as sa
class ForceUTCDatetime(sa.TypeDecorator):
"""Ensures datetimes are timezone-aware UTC objects across both DBs."""
impl = sa.TIMESTAMP(timezone=True)
cache_ok = True
def process_bind_param(self, value, dialect):
if value is not None:
if value.tzinfo is None:
# Interpret naive datetime as UTC or handle according to business logic
value = value.replace(tzinfo=timezone.utc)
else:
# Convert any other timezone directly to UTC
value = value.astimezone(timezone.utc)
return value
def process_result_value(self, value, dialect):
if value is not None and value.tzinfo is None:
# Force the Python object to be aware if Oracle stripped the offset
return value.replace(tzinfo=timezone.utc)
return value
from .meta import * from .meta import *
from .common import * from .common import *
from .base import * from .base import *
......
...@@ -59,7 +59,7 @@ class _Departemen(NamaModel): ...@@ -59,7 +59,7 @@ class _Departemen(NamaModel):
eng = cls.db_session.get_bind() eng = cls.db_session.get_bind()
if eng.dialect.name.lower() == "oracle": if eng.dialect.name.lower() == "oracle":
sql = """ sql = """
SELECT SELECT
--LPAD(' ', (LEVEL - 1) * 2) || nama AS hierarchy, --LPAD(' ', (LEVEL - 1) * 2) || nama AS hierarchy,
SYS_CONNECT_BY_PATH(nama, '/') AS hierarchy, SYS_CONNECT_BY_PATH(nama, '/') AS hierarchy,
id, id,
...@@ -69,62 +69,56 @@ SELECT ...@@ -69,62 +69,56 @@ SELECT
status, status,
(LEVEL - 1) AS lvl, (LEVEL - 1) AS lvl,
SYS_CONNECT_BY_PATH(id, ',') AS path SYS_CONNECT_BY_PATH(id, ',') AS path
FROM FROM
departemen departemen
START WITH START WITH
parent_id IS NULL parent_id IS NULL
CONNECT BY CONNECT BY
PRIOR id = parent_id PRIOR id = parent_id
ORDER SIBLINGS BY ORDER SIBLINGS BY
id""" id """
else: else:
sql = """ sql = """
WITH RECURSIVE dep_tree AS ( WITH RECURSIVE dep_tree AS (
SELECT SELECT
id, id,
kode, kode,
nama, nama::text AS nama,
parent_id, parent_id,
status, status,
0 AS lvl, 0 AS lvl,
ARRAY[id] AS path ARRAY[id] AS path
FROM FROM departemen
public.departemen
WHERE
{str_where}
UNION ALL UNION ALL
SELECT SELECT
c.id, c.id,
c.kode, c.kode,
c.nama, ct.nama || '/' || c.nama::text AS nama,
c.parent_id, c.parent_id,
c.status, c.status,
ct.level + 1, ct.lvl + 1,
ct.path || c.id ct.path || c.id
FROM FROM departemen c
public.departemen c JOIN dep_tree ct ON c.parent_id = ct.id
JOIN
dep_tree ct ON c.parent_id = ct.id
) )
SELECT SELECT DISTINCT ON (kode)
REPEAT(' ', lvl) || nama AS hierarchy, -- Indent names based on level
id, id,
kode, kode,
nama, nama as hierarchy,
parent_id, parent_id,
status, status,
level, lvl,
path path
FROM FROM dep_tree
dep_tree """
""".format(str_where=str_where) #.format(str_where=str_where)
if search: if search:
sql = f"{sql} WHERE nama ILIKE '%{search}%' " sql = f"{sql} WHERE nama ILIKE '%{search}%' "
sql = sql+"""ORDER BY path;""" sql = sql+"""ORDER BY kode, path """
return cls.db_session.execute(text(sql)).fetchall() return cls.db_session.execute(text(sql)).fetchall()
......
from datetime import datetime from datetime import datetime
import logging import logging
from math import log
from requests import session
import pytz
import sqlalchemy as sa import sqlalchemy as sa
from pyramid.authorization import (Allow, Authenticated, ALL_PERMISSIONS) from pyramid.authorization import (Allow, Authenticated, ALL_PERMISSIONS)
# from sqlalchemy import TIMESTAMP
from sqlalchemy import ( from sqlalchemy import (
Column, Integer, DateTime, SmallInteger, String) Column, Integer, DateTime, SmallInteger, String)
from sqlalchemy.orm import (relationship, backref) from sqlalchemy.orm import (relationship, backref)
...@@ -28,7 +26,7 @@ from opensipkd.tools import as_timezone ...@@ -28,7 +26,7 @@ from opensipkd.tools import as_timezone
from .base import CommonModel, DBSession, DefaultModel from .base import CommonModel, DBSession, DefaultModel
from .meta import Base from .meta import Base
from .base import TABLE_ARGS from .base import TABLE_ARGS
from . import ForceUTCDatetime
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
class _GroupPermission(GroupPermissionMixin): class _GroupPermission(GroupPermissionMixin):
pass pass
...@@ -93,7 +91,7 @@ class _UserResourcePermission(UserResourcePermissionMixin): ...@@ -93,7 +91,7 @@ class _UserResourcePermission(UserResourcePermissionMixin):
class UserResourcePermission(_UserResourcePermission, Base): class UserResourcePermission(_UserResourcePermission, Base):
pass pass
from sqlalchemy import TIMESTAMP
class _User(UserMixin, BaseModel): class _User(UserMixin, BaseModel):
db_session = DBSession db_session = DBSession
last_login_date = Column(DateTime(timezone=True), nullable=True) last_login_date = Column(DateTime(timezone=True), nullable=True)
...@@ -106,7 +104,8 @@ class _User(UserMixin, BaseModel): ...@@ -106,7 +104,8 @@ class _User(UserMixin, BaseModel):
# 'Asia/Jakarta')), # 'Asia/Jakarta')),
# server_default="2000-01-01 01:01+7", # server_default="2000-01-01 01:01+7",
# ) # )
security_code_date = Column(TIMESTAMP(timezone=True)) # security_code_date = Column(TIMESTAMP(timezone=True))
security_code_date = Column(ForceUTCDatetime)
api_key = Column(String(256)) api_key = Column(String(256))
partner_id = Column(Integer) # , ForeignKey(Partner.id)) partner_id = Column(Integer) # , ForeignKey(Partner.id))
company_id = Column(Integer) # , ForeignKey(Partner.id)) company_id = Column(Integer) # , ForeignKey(Partner.id))
......
...@@ -179,7 +179,10 @@ class Views(BaseView): ...@@ -179,7 +179,10 @@ class Views(BaseView):
url_dict = request.matchdict url_dict = request.matchdict
if url_dict['act'] == 'grid': if url_dict['act'] == 'grid':
query = Departemen.cte_get() query = Departemen.cte_get()
data = [{"id": d.id, "kode": d.kode, "nama": d.hierarchy[1:], "status": d.status, data = [{"id": d.id, "kode": d.kode,
"nama": d.hierarchy.startswith(
'/') and d.hierarchy[1:] or d.hierarchy,
"status": d.status,
"level_id": d.lvl, "parent_id": d.parent_id} for d in query] "level_id": d.lvl, "parent_id": d.parent_id} for d in query]
return { return {
......
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!