penambahan module esppt dan pbb monitoring

1 parent 0583a055
Showing 260 changed files with 4482 additions and 7 deletions
...@@ -22,9 +22,9 @@ pyramid.includes = ...@@ -22,9 +22,9 @@ pyramid.includes =
pyramid_chameleon pyramid_chameleon
pyramid_rpc.jsonrpc pyramid_rpc.jsonrpc
pyramid_debugtoolbar pyramid_debugtoolbar
; tangsel.pbb.models tangsel.pbb.models
; tangsel.pbb.esppt tangsel.pbb.esppt
; tangsel.pbb.monitoring tangsel.pbb.monitoring
session.type = ext:database session.type = ext:database
......
...@@ -3,7 +3,8 @@ requires = ['setuptools >= 64', 'wheel'] ...@@ -3,7 +3,8 @@ requires = ['setuptools >= 64', 'wheel']
build-backend = 'setuptools.build_meta' build-backend = 'setuptools.build_meta'
[tool.setuptools] [tool.setuptools]
packages = ["tangsel", "tangsel.detable", "tangsel.base"] packages = ["tangsel", "tangsel.detable", "tangsel.tools",
"tangsel.base", "tangsel.pbb", "tangsel.pbb.models"]
[tool.mypy] [tool.mypy]
exclude = [ exclude = [
......
...@@ -4,5 +4,5 @@ from .users import * ...@@ -4,5 +4,5 @@ from .users import *
from .wilayah import * from .wilayah import *
from .partner import * from .partner import *
# from .common import * # from .common import *
# from .targets import * from .targets import *
# from .user_area import * from .user_area import *
from . import Base, User, ResDesa, DefaultModel, UserGroup, Group
from sqlalchemy import ForeignKey, Integer, Column
from sqlalchemy.orm import relationship, backref
class UserArea(DefaultModel, Base):
__tablename__ = "user_area"
__table_args__ = {'extend_existing': True}
user_id = Column(Integer, ForeignKey(User.id))
desa_id = Column(Integer, ForeignKey(ResDesa.id))
desa = relationship(ResDesa, backref=backref("user_area"))
user = relationship(User, backref=backref("user_area"))
def validator(self, values):
pass
@classmethod
def allow_area(cls, user_id, desa_id=None, desa_kd=None,
group_names=("Superuser", "pbbm-admin"), ):
user = UserGroup.query().filter(user_id == user_id).outerjoin(
Group, Group.id == UserGroup.group_id).filter(
Group.group_name.in_(group_names)).first()
if user and user.user_id:
return True
if not desa_id and not desa_kd:
raise Exception("parameter desa_id atau desa_kd wajib dikirim")
if desa_id:
rs = cls.query().filter(cls.user_id == user_id, cls.desa_id == desa_id)
if rs and rs.id:
return True
if desa_kd:
rs = cls.query().filter(cls.user_id == user_id) \
.outerjoin(ResDesa, ResDesa.id == cls.desa_id).filter(
ResDesa.kode == desa_kd).first()
if rs and rs.id:
return True
return False
@classmethod
def get_by_user_id(cls, user_id):
return cls.query().filter_by(user_id=user_id).all()
@classmethod
def user_desa(cls, user_id):
return cls.query().filter(cls.user_id == user_id)
from tangsel.base import get_params
from tangsel.base.models import (DBSession, User, GroupPermission)
# UserDeviceModel
from tangsel.tools import (
devel, get_random_string)
from tangsel.tools.api import *
log = logging.getLogger(__name__)
lima_menit = 300
#
def auth_from(request, field=None):
global lima_menit
env = request.environ
log.info(env)
if not ('HTTP_USERID' in env and 'HTTP_SIGNATURE' in env and
'HTTP_KEY' in env):
raise JsonRpcInvalidLoginError
http_userid = env['HTTP_USERID']
q = DBSession.query(User).filter_by(user_name=http_userid)
user = q.first()
if not user or user.status == 0:
raise JsonRpcInvalidLoginError
# bypass cek authentication for development
if http_userid == 'admin' and request.devel:
return user
time_stamp = validate_time(request)
if field:
header = json_rpc_header(http_userid, user.security_code, time_stamp)
else:
header = json_rpc_header(http_userid, user.api_key, time_stamp)
if header['signature'] != env['HTTP_SIGNATURE']:
raise JsonRpcInvalidLoginError
return user
def auth_from_rpc(request):
return auth_from(request)
def rpc_auth(request):
return auth_from(request)
# def auth_from_token(request):
# return auth_from(request, "security_code")
#
# def renew_token(user_device, logout=False):
# now = datetime.now(tz=get_timezone())
# tte = timedelta(minutes=10)
# if not user_device.expired or not user_device.token or \
# now - user_device.expired > tte:
# user_device.expired = now
# user_device.token = get_random_string(128)
# if logout:
# user_device.token=""
# DBSession.add(user_device)
# DBSession.flush()
# return user_device
# def token_auth(request, logout=False):
# if not request.environ["HTTP_TOKEN"]:
# raise JsonRpcInvalidLoginError
# user_device = UserDeviceModel.query() \
# .filter_by(kode=request.environ["HTTP_USER_AGENT"],
# token=request.environ["HTTP_TOKEN"]).first()
# if not user_device:
# raise JsonRpcInvalidLoginError
#
# return renew_token(user_device, logout=logout)
def get_user_device(request, user_id):
user_device = UserDeviceModel.query() \
.filter_by(user_id=user_id,
kode=request.environ["HTTP_USER_AGENT"]).first()
if not user_device:
user_device = UserDeviceModel()
user_device.user_id = user_id
user_device.kode = request.environ["HTTP_USER_AGENT"]
# user_device = renew_token(user_device)
return user_device
def auth_device(request):
env = request.environ
log.info(env)
if not ('HTTP_USERID' in env and 'HTTP_SIGNATURE' in env and
'HTTP_KEY' in env):
raise JsonRpcInvalidLoginError
http_userid = env['HTTP_USERID']
q = DBSession.query(User).filter_by(user_name=http_userid)
user = q.first()
if not user or user.status == 0:
raise JsonRpcInvalidLoginError
if http_userid == 'admin' and request.devel:
return user
user_device = get_user_device(request, user)
time_stamp = validate_time(request)
header = json_rpc_header(http_userid, user_device.token, time_stamp)
if header['signature'] != env['HTTP_SIGNATURE']:
log.info(f"{http_userid}, {user_device.token}, {time_stamp}")
log.info(f"{header['signature']} != {env['HTTP_SIGNATURE']}")
raise JsonRpcInvalidLoginError
return user
def check_token(token, perm_name=None):
user = User.get_by_token(token).first()
if not user:
raise JsonRpcInvalidLoginError
if not perm_name:
return user
groups = user.get_groups()
perm = DBSession.query(GroupPermission). \
filter(GroupPermission.group_id.in_(groups),
GroupPermission.perm_name == perm_name).first()
if not perm:
return
return user
def check_token_rpc(token, perm_name=None):
result = check_token(token, perm_name)
if not result:
raise JsonRpcPermissionError
return result
def update_token(user):
if not devel():
user.security_code = get_random_string(64)
DBSession.add(user)
DBSession.flush()
return dict(token=user.security_code)
def config_pars_rpc_url(params, method=None):
values = get_params(params)
return pars_rpc_url(values, method)
\ No newline at end of file \ No newline at end of file
from sqlalchemy import func
# from opensipkd.base.models import Parameter
def column_concat(cols=None):
if not cols:
return ''
elif len(cols) == 1:
return cols[0]
# saat ini menggunakan recursive spertinya ada syntax pythonic
# func.concat(cols[i], for col in cols)
return func.concat(cols[0], column_concat(cols[1:]))
def column_date(field, dt_format='YYYY-MM-DD HH:MI:SS'):
return func.to_char(field, dt_format)
# def get_parameter(kode):
# return Parameter.query_kode(kode).first()
# def get_parameter_pasar(kode):
# return Parameter.query_kode(kode).all()
# def get_parameter_kebersihan(kode):
# return Parameter.query_kode(kode).all()
from pyreportjasper import PyReportJasper
from tangsel.tools import get_random_string
from tangsel.base import get_settings, get_params
from platform import python_version
import logging
import os
from tangsel.tools.report import *
log = logging.getLogger(__name__)
log.warning("Opensipkd.base.tools.pbb depreciated use opensipkd.tools.pbb")
# -*- coding: utf-8 -*-
# db_driver_port = {
# "postgresql": ["postgres", "5432", "org.postgresql.Driver", "jdbc:postgresql://localhost:5432/pjdl_ciamis"],
# "oracle": ["oracle", "1512", "oracle.jdbc.driver.OracleDriver"],
# }
def jasper_compile(input_file):
# REPORTS_DIR = os.path.join(os.path.abspath(os.path.dirname(__file__)), 'reports')
# input_file = os.path.join(input_file)
# file_ext = os.path.splitext(input_file)
# output_file = os.path.join(REPORTS_DIR, 'csv')
pyreportjasper = PyReportJasper()
pyreportjasper.compile(write_jasper=True)
def jasper_db_conn(db_schema=None, dburl="sqlalchemy.url"):
db = get_params(dburl).split("@")
db_driver, db_user, db_password = db[0].split(':')
db_servers, db_name = db[1].split('/')
# db_user, db_password = db_users.split(":")
# db_host = db_server
# if not jdbc_dir:
# java_home = os.getenv("JAVA_HOME")
# jdbc_dir = os.path.join(java_home, 'lib', db_driver_port[db_driver][2])
if db_servers.find(':') > 1:
db_host, db_port = db_servers.split(":")
else:
db_host = db_servers
db_port = db_driver_port[db_driver][1]
jdbc_dir = get_params("jdbc_dir", "")
jdbc_driver = db_driver_port[db_driver][2]
db_driver = db_driver_port[db_driver][0]
log.debug(jdbc_dir)
return {
'driver': db_driver,
'username': db_user.strip('/'),
'password': db_password,
'host': db_host,
'database': db_name,
'db_sid': db_name, # for oracle: added by Tatang
'schema': db_schema,
'port': db_port,
'jdbc_dir': jdbc_dir,
'jdbc_driver': jdbc_driver,
}
def jasper_export(input_file, output_file=None, schema=None,
output_formats=["pdf"], dburl="sqlalchemy.url",
parameters={}, db_schema=None, report_locale="en_US", use_db=True,
out_file=None):
module_file = None
input_file = input_file.split(":")
# Cek apakah input_file berupa module
# if os.name == 'nt' and len(input_file)>1:
# input_file=[input_file[0]]
# if len(input_file) > 1:
# path = __import__()
# path = os.path.dirname(path.__file__)
# input_file = os.path.join(path, input_file[1])
# else:
# input_file=input_file[0]
if len(input_file) > 1:
if os.name == 'nt':
if len(input_file) > 2: # Cek apakah file berbentuk "C:\module_folder\filename.jrxml"
module_file = input_file[0]
input_file = ":".join([input_file[1], input_file[2]])
else:
input_file = ":".join([input_file[0], input_file[1]])
else:
module_file = input_file[0]
input_file = input_file[1]
if module_file:
path = __import__(module_file)
path = os.path.dirname(path.__file__)
input_file = os.path.join(path, input_file)
else:
input_file = input_file[0]
log.debug(f"Input File: {input_file}")
if not output_file:
output_file = get_params("tmp_report", "/tmp")
if out_file:
log.debug(f"File name to generate: {out_file}")
out_file = os.path.splitext(out_file)[0]
output_file = os.path.join(output_file, out_file)
else:
output_file = os.path.join(output_file, get_random_string(32))
db_connection = use_db and jasper_db_conn(
db_schema=db_schema, dburl=dburl) or {}
pyreportjasper = PyReportJasper()
parameters.update({'python_version': python_version()})
pyreportjasper.config(
input_file,
output_file,
output_formats=output_formats,
db_connection=db_connection,
parameters=parameters,
locale=report_locale
)
try:
log.debug(input_file)
pyreportjasper.compile(write_jasper=True)
pyreportjasper.process_report()
except Exception as e:
log.debug(e)
raise
output_files = [".".join([output_file, f]) for f in output_formats]
log.debug(output_files)
return output_files
import colander
from deform import widget
from pyramid.view import view_config
from . import BaseView
from ..models import ResDesa, User, UserArea
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)
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.Integer(),
widget=widget.SelectWidget(values=ResDesa.get_list()),
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
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()
# @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-edit', renderer='templates/form.pt',
# permission='user-edit')
# def view_edit(self):
# return super().view_edit()
from opensipkd.base.models import *
\ No newline at end of file \ No newline at end of file
from .base.models import *
\ No newline at end of file \ No newline at end of file
File mode changed
import os
from pyramid.events import BeforeRender, subscriber
from tangsel.base import get_params
from tangsel.tools import get_settings
from tangsel.tools import create_static_path
from tangsel.base import get_params, BaseApp
class AppModels(BaseApp):
# sspd_by_kode digunakan untuk no_urut dari1 setiap tahun berdasarkan kode
def __init__(self):
super().__init__()
self.base_dir = os.path.split(__file__)[0]
self.mirror_url = "" # URL ke API PBB
self.files = ""
self.files_bukti = ""
self.files_tpl = ""
self.files_draft = ""
self.files_final = ""
self.uri = "" # URL untuk internal
self.url = "" # URL untuk download/verifikasi
self.unoconv = ""
self.http_server = ""
self.mirror_url = ""
self.bsre_url = ""
def init(self):
settings = get_settings()
self.mirror_url = settings.get('pbb_esppt_mirror.url', "")
self.bsre_url = settings.get('pbb_esppt_bsre.url', "")
self.bsre_ttd_img = settings.get('pbb_esppt_bsre_ttd_img', "")
self.files = get_params(
"pbb_esppt_files", settings.get("pbb_esppt_files", ""))
if not self.files:
raise ValueError('pbb_esppt_files Not Found in config.')
sep = os.sep
if sep != '/':
# sep = "/"
self.files = self.files.replace('/', '\\')
self.files += sep
else:
self.files += sep
self.files_tpl = self.files + f"tpl{sep}"
self.files_bukti = self.files + f"bukti{sep}"
self.files_draft = self.files+ f"draft{sep}"
self.files_final = self.files + f"final{sep}"
self.captcha_files = get_params(
"captcha_files", settings.get("captcha_files", ""))
self.uri = 'pbb/esppt/files'
sppt_url = settings.get("esppt_url", "/".join([self.uri, "final"]))
self.url = settings.get("esppt_file_url",sppt_url)
if self.url.find("http") < 0:
self.http_server = settings.get("_host", "http://localhost:6543")
self.url = self.http_server+'/'+self.url
# self.menus = get_module_menus("esppt")
# add_view_config(config, "esppt", "tangsel.pbb.esppt.views")
def static_views(self, config):
create_static_path(config, self.files, self.uri, 0)
# URL Khusus untuk eksternal
create_static_path(config, self.files_final, self.uri+'/final', 0)
# def get_menus(self):
# _logging.info(self.menus)
# return self.menus
SPPT_CLASS = AppModels()
def includeme(config):
SPPT_CLASS.init()
SPPT_CLASS.static_views(config)
# SPPT_CLASS.route_from_list(config, routes, paket="tangsel.pbb.esppt")
SPPT_CLASS.route_from_csv(config, "tangsel.pbb.esppt.views")
config.scan(".")
print("+", __name__, "includeme class loaded")
@subscriber(BeforeRender)
def add_global(event):
event['get_esppt_menus'] = SPPT_CLASS.get_menus
from tangsel.base.models import (StandarModel, DefaultModel, DBSession, Partner,
User, DBSession, Partner, UserGroup, Group)
from sqlalchemy import Column, String, Integer, case, func
from sqlalchemy.orm import (relationship,
backref, column_property)
# from zope.sqlalchemy import ZopeTransactionExtension
from tangsel.base.models import Base
TABLE_ARGS = {'extend_existing': True,
'schema': 'public'}
def subs(o, s, p):
return func.substr(o, s, p)
STATUS_NOP = [
(0, "Draft"),
(1, "Verified"),
(2, "Canceled"),
(-1, "Declined"),
]
class PartnerNop(StandarModel, Base):
__tablename__ = 'partner_nop'
nop = Column(String(18), nullable=False)
thn_awal = Column(Integer())
thn_akhir = Column(Integer())
partner_id = Column(Integer(), server_default="0")
dokumen = Column(String())
status = Column(Integer())
status_text = column_property(case((status == 0, STATUS_NOP[0][1]),
(status == 1, STATUS_NOP[1][1]),
(status == 2, STATUS_NOP[2][1]),
else_=STATUS_NOP[len(STATUS_NOP)-1][1]))
nop_formatted = column_property(
subs(nop, 1, 2) + "." + subs(nop, 3, 2) + "-" + subs(nop, 5, 3) + "." +
subs(nop, 8, 3) + "-" + subs(nop, 11, 3) + "." + subs(nop, 14, 4) + "-" + subs(nop, 18, 1))
kecamatan = column_property(
subs(nop, 1, 2)+"."+subs(nop, 3, 2)+"."+subs(nop, 5, 3))
kelurahan = column_property(
subs(nop, 1, 2)+"."+subs(nop, 3, 2)+"."+subs(nop, 5, 3)+"."+subs(nop, 8, 3))
partner = relationship("Partner", backref=backref("nop"),
foreign_keys=[partner_id],
primaryjoin="Partner.id==PartnerNop.partner_id")
@ classmethod
def query_register(cls):
return cls.query(cls)
from .es_log import *
from sqlalchemy import (Column, ForeignKey, Integer, String, DateTime, func, case)
from sqlalchemy.orm import column_property, relationship
from tangsel.base.models import PartnerModel, Partner
from ..models import Base, DefaultModel, TABLE_ARGS, DBSession
from ..tools import FixNop
PROSES_STATUS = [
(-1, "Pengajuan"),
(0, "Proses Penetapan"),
(1, "Proses TTD"),
(2, "Tersedia"),
(3, "Gagal"),
]
def get_status(status):
if status == 1:
return "Proses"
elif status == -1:
return "Gagal/Permohonan"
elif status == 2:
return "Terkirim"
else:
return "Draft"
class LogEspptMassal(DefaultModel, Base):
__tablename__ = 'log_esppt_massal'
tahun = Column(String(4), nullable=False)
jenis = Column(String(1), nullable=False) # 1 Semua SPPT 2 SPPT Terdaftar
jml_sppt = Column(Integer())
jml_proses = Column(Integer())
status = Column(Integer()) # 0 dalam proses 1 selesai proses
status_text = column_property(case(
(status == 1, "Proses Generator"),
(status == 2, "Proses TTD"),
(status == 3, "Selesai"),
else_="Proses Parsing"))
partner_id = Column(Integer(), server_default="0")
nop = Column(String(32))
class LogEsppt(DefaultModel, Base):
__tablename__ = 'log_esppt'
kd_propinsi = Column(String(2), nullable=False)
kd_dati2 = Column(String(2), nullable=False)
kd_kecamatan = Column(String(3), nullable=False)
kd_kelurahan = Column(String(3), nullable=False)
kd_blok = Column(String(3), nullable=False)
no_urut = Column(String(4), nullable=False)
kd_jns_op = Column(String(1), nullable=False)
tahun = Column(String(4), nullable=False)
siklus_sppt = Column(Integer, nullable=False)
partner_id = Column(Integer(), ForeignKey(Partner.id), server_default="0")
destination = Column(String)
status = Column(Integer)
created = Column(DateTime)
sent = Column(DateTime)
file_name = Column(String(254))
nm_wp_sppt = Column(String(30))
pbb_yg_harus_dibayar_sppt = Column(Integer)
nop = column_property(
kd_propinsi + "." + kd_dati2 + "-" + kd_kecamatan + "." +
kd_kelurahan + "-" + kd_blok + "." + no_urut + "-" + kd_jns_op)
nop_raw = column_property(
kd_propinsi + kd_dati2 + kd_kecamatan +
kd_kelurahan + kd_blok + no_urut + kd_jns_op)
status_text = column_property(
case(
(status == -1, "Pengajuan"),
(status == 0, "Proses Penetapan"),
(status == 1, "Proses TTD"),
(status == 2, "Tersedia"),
(status == 3, "Gagal"),
else_="Unknown"
)
)
kecamatan = column_property(kd_propinsi+"."+kd_dati2+"."+kd_kecamatan)
kelurahan = column_property(
kd_propinsi+"."+kd_dati2+"."+kd_kecamatan+"."+kd_kelurahan)
partner = relationship("Partner", backref="log_esppt")
__table_args__ = (TABLE_ARGS)
@property
def nop_as_id(self):
return "".join([self.kd_propinsi, self.kd_dati2, self.kd_kecamatan,
self.kd_kelurahan, self.kd_blok, self.kd_no_urut,
self.kd_jns_op, self.tahun])
@property
def nop_to_id(self):
return self.nop_as_id
@classmethod
def query(cls):
return DBSession.query(cls)
@classmethod
def query_id(cls, id):
return cls.query().filter_by(id=id)
@classmethod
def query_nop(cls, nop):
nop = FixNop(nop)
return cls.query().filter(
cls.kd_propinsi == nop['kd_propinsi'],
cls.kd_dati2 == nop['kd_dati2'],
cls.kd_kecamatan == nop['kd_kecamatan'],
cls.kd_kelurahan == nop['kd_kelurahan'],
cls.kd_blok == nop['kd_blok'],
cls.no_urut == nop['no_urut'],
cls.kd_jns_op == nop['kd_jns_op'],
)
class Passphrase(PartnerModel, Base):
__tablename__ = 'log_passphrase'
password = Column(String(64))
class EspptUnduh(PartnerModel, Base):
__tablename__ = 'log_sppt_unduh'
nop = Column(String(18))
tahun = Column(String(4))
kd_propinsi = Column(String(2))
kd_dati2 = Column(String(2))
kd_kecamatan = Column(String(3))
kd_kelurahan = Column(String(3))
kd_blok = Column(String(3))
no_urut = Column(String(4))
kd_jns_op = Column(String(1))
@classmethod
def query_nop(cls, nop):
return cls.query().filter_by(nop=nop)
Kepada Yth:
Bapak/Ibu/Saudara/i: {nm_wp}
Di
Tempat
Bersama ini kami sampaikan SPPT Elektronik :
NOP : {nop}
Tahun Pajak : {tahun}
Nama Wajib Pajak : {nm_wp}
Tagihan SPPT: {jumlah}
Jatuh Tempo: {jth_tempo}
Tempat Pembayaran: {tp}
Untuk menghindari denda pajak 2% perbulan harap membayar sebelum tanggal {jth_tempo}.
Kami ucapkan terimakasih telah mengikuti program elektronik SPPT Bada Pendapatan Daerah Kota Bogor
Hormat Kami
{jabatan}
TTD
{nm_pejabat}
NIP: {nip}
Info Tagihan PBB
NOP : {nop}
Subjek Pajak : {nm_wp}
Tahun Pajak : {tahun}
Tagihan : {jumlah}
J Tempo : {jth_tempo}
No preview for this file type
BJB
\ No newline at end of file \ No newline at end of file
No preview for this file type
TokoPedia, Indomaret
Alfamart
\ No newline at end of file \ No newline at end of file
# package
from tangsel.pbb.esppt.tools import left, right
from tangsel.tools.pbb import FixNop as oldFixNop
class FixNop(oldFixNop):
def __init__(self, raw):
print(raw)
if type(raw) == dict:
structures = self.get_structure()
value = ""
for struct in structures:
value += raw[struct[0]]
raw = value
super().__init__(raw)
def get_raw_full(self, ch=''):
s = ''
for name, size, typ in self.struct:
v = self.get_value(name, typ)
pad_func = typ == 'N' and right or left
s += pad_func(v, size)
s += ch
return s
group_name,description,member_count
esppt,"Elektronik SPPT",0
esppt-admin,"Admin Elektronik SPPT",0
esppt-tetap,"Penetapan ESPPT",0
\ No newline at end of file \ No newline at end of file
group_id/groups.group_name,perm_name
"esppt","esppt"
"esppt-admin","esppt-admin"
"esppt-admin","esppt-tetap"
esppt-tetap,"esppt-tetap"
\ No newline at end of file \ No newline at end of file
perm_name,description
"esppt","Elektronik SPPT"
"esppt-admin","Admin E-SPPT"
"esppt-upload","Upload E-SPPT"
"esppt-log","Log E-SPPT"
"esppt-massal","Massal E-SPPT"
"esppt-import","Import E-SPPT"
esppt-tetap,"Penetapan ESPPT",0
\ No newline at end of file \ No newline at end of file
kode,path,nama,status,type,module,file_name,class_name,func_name,permission,parent_id/routes.kode,is_menu,template,csrf
esppt,/pbb/esppt,E-SPPT Home,1,0,esppt,__init__,,view_add,,,1,home.pt,
esppt-unduh-add,/pbb/esppt/unduh/add, Unduh E-SPPT,1,0,esppt,unduh,,view_add,,,1,form6.pt,
esppt-mynop,/pbb/esppt/mynop,My NOP,1,0,esppt,my_nop,,view_list,view,,1,form.pt,
esppt-mynop-add,/pbb/esppt/mynop/add,E-SPPT NOP Add,1,0,esppt,my_nop,,view_add,view,esppt-mynop,,form6.pt,
esppt-mynop-edit,/pbb/esppt/mynop/{id}/edit,E-SPPT NOP Edit,1,0,esppt,my_nop,,view_edit,view,esppt-mynop,,form6.pt,
esppt-mynop-delete,/pbb/esppt/mynop/{id}/delete,E-SPPT NOP Delete,1,0,esppt,my_nop,,view_delete,view,esppt-mynop,,form6.pt,
esppt-mynop-act,/pbb/esppt/mynop/{act}/act,E-SPPT NOP Act,1,0,esppt,my_nop,,view_act,view,esppt-mynop,,json,
esppt-mynop-view,/pbb/esppt/mynop/{id}/view,Lihat Data E-SPPT NOP ,1,0,esppt,my_nop,,view_view,view,esppt-mynop,,form6.pt,
esppt-mysppt,/pbb/esppt/mysppt,My SPPT,1,0,esppt,my_sppt,,view_list,view,,1,form.pt,
esppt-mysppt-add,/pbb/esppt/mysppt/add,E-SPPT Permohonan,1,0,esppt,my_sppt,,view_add,view,esppt-mysppt,,form6.pt,
esppt-mysppt-act,/pbb/esppt/mysppt/{act}/act,E-SPPT Act,1,0,esppt,my_sppt,,view_act,view,esppt-mysppt,,json,
esppt-mysppt-view,/pbb/esppt/mysppt/{id}/view,Lihat Data E-SPPT,1,0,esppt,my_sppt,,view_view,view,esppt-mysppt,,form.pt,
esppt-admin,#,Admin,1,,esppt,,,,esppt-admin,,1,,
esppt-template,/pbb/esppt/template,Template eSPPT,1,,esppt,template,,view_upload,esppt-admin,esppt-admin,1,form.pt,
esppt-unduh,/pbb/esppt/unduh,List Unduh E-SPPT,1,0,esppt,unduh,,view_list,esppt-admin,esppt-admin,1,form.pt,
esppt-unduh-edit,/pbb/esppt/unduh/{id}/edit, Edit Unduh E-SPPT,1,0,esppt,unduh,,view_edit,esppt-admin,esppt-unduh,,form6.pt,
esppt-unduh-view,/pbb/esppt/unduh/{id}/view, Lihat Unduh E-SPPT,1,0,esppt,unduh,,view_view,esppt-admin,esppt-unduh,,form6.pt,
esppt-unduh-delete,/pbb/esppt/unduh/{id}/delete, Hapus Unduh E-SPPT,1,0,esppt,unduh,,view_delete,esppt-admin,esppt-unduh,,form6.pt,
esppt-unduh-act,/pbb/esppt/unduh/{act}/act, Act Unduh E-SPPT,1,0,esppt,unduh,,view_act,esppt-admin,esppt-unduh,,json,
esppt-nop-valid,/pbb/esppt/nop/valid,Validasi NOP,1,0,esppt,valid_nop,,view_list,esppt-admin,esppt-admin,1,form.pt,
esppt-nop-valid-act,/pbb/esppt/nop/valid/{act}/act,Validasi NOP Act,1,0,esppt,valid_nop,,view_act,esppt-admin,esppt-nop-valid,,json,
esppt-nop-valid-view,/pbb/esppt/nop/valid/{id}/view,Lihat Data E-SPPT NOP ,1,0,esppt,valid_nop,,view_view,esppt-admin,esppt-nop-valid,,form6.pt,
esppt-report-nop,/pbb/esppt/report/nop, Laporan NOP,0,,esppt,report,,view_list,esppt-admin,esppt-nop-valid,1,form.pt,
esppt-report-nop-act,/pbb/esppt/report/nop/{act}/act, Laporan NOP Act,0,,esppt,report,,view_act,esppt-admin,esppt-nop-valid,,json,
esppt-massal,/esppt/massal,E-SPPT Massal,0,0,esppt,massal,,view_massal,esppt-admin,esppt-admin,1,form.pt,
esppt-parsial,/esppt/parsial,E-SPPT Pengajuan/Gagal,1,0,esppt,parsial,,view_list,esppt-admin,esppt-admin,1,form.pt,
esppt-parsial-act,/esppt/parsial/{act}/act,E-SPPT Terseleksi ACT,1,0,esppt,parsial,,view_act,esppt-admin,esppt-parsial,,json,
esppt-parsial-view,/esppt/parsial/{id}/view,E-SPPT Terseleksi Lihat,1,0,esppt,parsial,,view_view,esppt-admin,esppt-parsial,,form6.pt,
esppt-parsial-edit,/esppt/parsial/{id}/edit,E-SPPT Proses Terseleksi,1,0,esppt,parsial,,view_edit,esppt-admin,esppt-parsial,,form6.pt,
esppt-parsial-delete,/esppt/parsial/{id}/delete,E-SPPT Proses Terseleksi Edit,1,0,esppt,parsial,,view_delete,esppt-admin,esppt-parsial,,form6.pt,
esppt-parsial-add,/esppt/parsial/add,E-SPPT Proses Terseleksi,1,0,esppt,parsial,,view_add,esppt-admin,esppt-parsial,,form6.pt,
esppt-massal,/esppt/massal,E-SPPT Massal,1,0,esppt,massal,,view_list,esppt-admin,esppt-admin,1,form.pt,
esppt-massal-act,/esppt/massal/{act}/act,E-SPPT massal Act,1,0,esppt,massal,,view_act,esppt-admin,esppt-massal,,json,
esppt-massal-view,/esppt/massal/{id}/view,E-SPPT Terseleksi Lihat,1,0,esppt,massal,,view_view,esppt-admin,esppt-massal,,form6.pt,
esppt-massal-delete,/esppt/massal/{id}/delete,E-SPPT Terseleksi Hapus,1,0,esppt,massal,,view_delete,esppt-admin,esppt-massal,,form6.pt,
esppt-massal-add,/esppt/massal/add,E-SPPT Proses Terseleksi,1,0,esppt,massal,,view_add,esppt-admin,esppt-massal,,form6.pt,
esppt-log,/esppt/log,E-SPPT Log,0,0,esppt,logs,,view_list,esppt-admin,esppt-admin,1,,
esppt-log-act,/esppt/log/{act}/act,E-SPPT Log Act,0,0,esppt,logs,,view_act,esppt-admin,esppt-log,,,
esppt-report-mysppt,/pbb/esppt/report/mysppt, Laporan SPPT,0,,esppt,report,,,esppt-admin,,,,
esppt-report-mysppt-act,/pbb/esppt/report/mysppt/{act}/act, Laporan SPPT Act,0,,esppt,report,,,esppt-admin,esppt-report-mysppt,,,
esppt-kecamatan,/pbb/esppt/kecamatan,E-SPPT Kecamatan,0,0,esppt,kecamatan,,view_list,esppt-admin,,1,,
esppt-kecamatan-delete,/pbb/esppt/kecamatan/{id}/delete,E-SPPT Hapus Kecamatan,0,0,esppt,kecamatan,,view_delete,esppt-admin,esppt-kecamatan,,,
esppt-kecamatan-act,/pbb/esppt/kecamatan/{act}/act,E-SPPT Action Kecamatan,0,0,esppt,kecamatan,,view_act,esppt-admin,esppt-kecamatan,,,
esppt-kelurahan,/pbb/esppt/kelurahan,E-SPPT Kelurahan,0,0,esppt,kecamatan,,view_list,esppt-admin,,1,,
esppt-kelurahan-delete,/pbb/esppt/kelurahan/{id}/delete,E-SPPT Hapus Kelurahan,0,0,esppt,kecamatan,,view_delete,esppt-admin,esppt-kelurahan,,,
esppt-kelurahan-act,/pbb/esppt/kelurahan/{act}/act,E-SPPT Action Kelurahan,0,0,esppt,kecamatan,,view_act,esppt-admin,esppt-kelurahan,,,
pbb-api-sismiop,/pbb/api/sismiop, API SISMIOP,0,1,esppt,unduh,,,,,,,
esppt-reg-import,/esppt/reg/import,Import Registrasi User,0,0,esppt,,,,esppt-admin,,,form6.pt,
"esppt-help","/pbb/esppt/help","Home E-SPPT Help",1
"esppt-admin","/pbb/esppt/admin","E-SPPT Admin",1
"esppt-admin-act","/pbb/esppt/admin/{act}/act","E-SPPT Admin Act",1
"esppt-report","/pbb/esppt/report","E-SPPT Report",1
"esppt-report-act","/esppt/report/{act}/act","E-SPPT Report Act",1
"esppt-reg","/esppt/reg","E-SPPT Register",1
"esppt-reg-act","/esppt/reg/{act}/act","E-SPPT Register Act",1
"esppt-reg-add","/esppt/reg/add","E-SPPT Register Tambah",1
"esppt-reg-edt","/esppt/reg/{id}/edt","E-SPPT Register Edit",1
"esppt-reg-nik","/esppt/reg/{id}/nik","E-SPPT Register Edit NIK",1
No preview for this file type
import os
import sys
import logging
import random
from subprocess import (
Popen,
PIPE,
)
logformatter = logging.Formatter('%(asctime)s %(levelname)s %(message)s')
def Log(name, file=None):
if not file:
file = name
name = str(random.randrange(1,99999))
log = logging.getLogger(name)
handler = logging.FileHandler( file )
handler.setFormatter( logformatter )
log.addHandler( handler )
log.setLevel( logging.INFO )
return log
def get_pid(pid):
if isinstance(pid, int):
return pid
try:
f = open(pid,'r')
pid_int = int(f.read().split()[0])
f.close()
return pid_int
except IOError:
return
except ValueError:
return
except IndexError:
return
def isLive(pid):
pid = get_pid(pid)
if not pid:
return
try:
os.kill(pid, 0)
except OSError:
return
for i in range(3):
p1 = Popen(['ps', 'ax'], stdout=PIPE)
p2 = Popen(['grep', '^%s%d' % (' ' * i, pid)], stdin=p1.stdout,
stdout=PIPE)
p3 = Popen(['grep', '-v', 'grep'], stdin=p2.stdout, stdout=PIPE)
s = p3.communicate()
s = s[0]
if s:
return pid
def make_pid(filename):
pid = isLive(filename)
if pid:
sys.exit('PID saya %d masih ada' % pid)
pid = os.getpid()
f = open(filename,'w')
f.write(str(pid))
f.close()
return pid
def my_ip():
r = []
for t in commands.getoutput('/sbin/ifconfig |grep "inet "').splitlines():
# inet addr:192.168.0.254 Bcast:192.168.0.255 Mask:255.255.255.0
if t.find(':') > -1:
ip = t.split()[1].split(':')[1]
else:
# inet 192.168.1.7 netmask 255.255.255.0 broadcast 192.168.1.255
ip = t.split()[1]
r.append(ip)
return r
import os
import sys
import transaction
from pyramid.paster import (
get_appsettings,
setup_logging,
)
from sqlalchemy import (
engine_from_config,
)
from tangsel.base.models import (
DBSession,
Group,
Permission,
GroupPermission,
)
from tangsel.base.scripts.initializedb import append_csv
from tangsel.base.models import Base
from ..models.es_log import *
def get_file(filename):
base_dir = os.path.split(__file__)[0]
fullpath = os.path.join(base_dir, 'data', filename)
return open(fullpath)
def main(argv=sys.argv):
print('*** Module va/pemda begin ***')
config_uri = argv[1]
setup_logging(config_uri)
settings = get_appsettings(config_uri)
engine = engine_from_config(settings, 'sqlalchemy.')
Base.metadata.bind = engine
Base.metadata.create_all(bind=engine)
DBSession.configure(bind=engine)
append_csv(Group, 'group.csv', ['group_name'], get_file_func=get_file)
append_csv(Permission, 'permission.csv', [
'perm_name'], get_file_func=get_file)
append_csv(GroupPermission, 'group_permission.csv', [
'group_id', 'perm_name'], get_file_func=get_file)
transaction.commit()
print('*** Module e-sppt done ***')
# from tangsel.pbb.esppt.views.bak.report import SPPTSchema
# def flush(row):
# DBSession.add(row)
# try:
# DBSession.flush()
# except Exception as e:
# log.debug(str(e))
# DBSession.rollback()
# raise e
# def send_bsre(f):
# todo: Module sending BSRE
# return get_bsre(f):
# def get_draft_files(draft_path):
# resp = []
# for f in os.listdir(draft_path):
# if os.path.isfile(os.path.join(draft_path, f)) and f[-4:] == ".pdf":
# resp.append[f]
# else:
# if os.path.isdir(f):
# resp.extend(get_draft_files(f))
# return resp
sismiop = ""
PY3 = sys.version_info[0] >= 3
USER_ID = 'sa'
EMAIL_SUBJECT = 'SPPT {nop} {tahun}'
EMAIL_BODY = """Bapak / Ibu {nama_wp} yth,
Terlampir SPPT dengan Nomor Objek Pajak {nop} untuk tahun {tahun} senilai
Rp {nilai}.
"""
log = logging.getLogger(__name__)
def out():
transaction.commit()
if running:
del running[0] # Akhiri loop utama
logtte = logging.getLogger('BSRE')
def send_ttd(option):
log.debug("def send_email")
pid_file = os.path.realpath("esppt-ttd.pid")
log_dir = os.path.realpath(option.log_dir)
os.path.join(log_dir, 'esppt-ttd.log')
if option.stop:
log.info('Stop Daemon')
stop_daemon(pid_file)
sys.exit()
log.info("Start Proses Kirim ke BSRE")
make_pid(pid_file)
send_sppt()
os.remove(pid_file)
import sys
import logging
from tangsel.pbb.models import (
PbbBase, PbbDBSession, Sppt, PosisiPegawai, DatObjekPajak, SpptOpBersama,
JenisSektor, Kelurahan, Kecamatan, Dati2, Kanwil, Kantor, TempatPembayaran,
KodeMap, Tarif, Jabatan, Pegawai)
from sqlalchemy import and_
from . import FixNop
from .pbb_daemon import PdfProses, sppt_ttd, send_email, parsing
log = logging.getLogger(__name__)
from .. import SPPT_CLASS
class PbbProses(PdfProses):
def __init__(self, config, option):
super().__init__(config, option)
self.pbb_dbsession = PbbDBSession
self.pbb_base = PbbBase
self.sppt = Sppt
self.posisi_pegawai = PosisiPegawai
self.dat_objek_pajak = DatObjekPajak
self.sppt_op_bersama = SpptOpBersama
self.jenis_sektor = JenisSektor
self.kelurahan = Kelurahan
self.kecamatan = Kecamatan
self.dati2 = Dati2
self.kanwil = Kanwil
self.kantor = Kantor
self.tempat_pembayaran = TempatPembayaran
self.kode_map = KodeMap
self.tarif = Tarif
self.jabatan = Jabatan
self.pegawai = Pegawai
self.set_engine()
def get_sppt(self, nop, tahun):
log.debug("Get SPPT")
fxNop = FixNop(nop)
if not SPPT_CLASS.mirror_url:
return PbbDBSession.query(
self.sppt.nm_wp_sppt,
self.sppt.jln_wp_sppt,
self.sppt.blok_kav_no_wp_sppt,
self.sppt.kelurahan_wp_sppt,
self.sppt.kota_wp_sppt,
self.sppt.npwp_sppt,
self.sppt.no_persil_sppt,
self.sppt.siklus_sppt,
self.sppt.kd_kls_tanah,
self.sppt.thn_awal_kls_tanah,
self.sppt.kd_propinsi,
self.sppt.kd_dati2,
self.sppt.kd_kecamatan,
self.sppt.kd_kelurahan,
self.sppt.kd_blok,
self.sppt.no_urut,
self.sppt.kd_jns_op,
self.sppt.kd_kls_bng,
self.sppt.thn_awal_kls_bng,
self.sppt.tgl_jatuh_tempo_sppt,
self.sppt.luas_bumi_sppt,
self.sppt.luas_bng_sppt,
self.sppt.njop_bumi_sppt,
self.sppt.njop_bng_sppt,
self.sppt.njop_sppt,
self.sppt.njoptkp_sppt,
self.sppt.pbb_terhutang_sppt,
self.sppt.faktor_pengurang_sppt,
self.sppt.pbb_yg_harus_dibayar_sppt,
self.sppt.tgl_terbit_sppt,
self.sppt.tgl_cetak_sppt,
# self.sppt.nop,
self.sppt.thn_pajak_sppt,
self.sppt.kd_kanwil,
self.sppt.kd_kantor,
self.sppt.kd_tp,
self.sppt.status_pembayaran_sppt,
self.dat_objek_pajak.subjek_pajak_id,
self.dat_objek_pajak.jalan_op,
self.dat_objek_pajak.blok_kav_no_op,
self.dat_objek_pajak.rt_op,
self.dat_objek_pajak.rw_op,
self.dat_objek_pajak.no_persil,
self.sppt_op_bersama.kd_kls_tanah.label('kd_kls_tanah_ber'),
self.sppt_op_bersama.thn_awal_kls_tanah.label(
'thn_awal_kls_tanah_ber'),
self.sppt_op_bersama.kd_kls_bng.label('kd_kls_bng_ber'),
self.sppt_op_bersama.thn_awal_kls_bng.label(
'thn_awal_kls_bng_ber'),
self.sppt_op_bersama.luas_bumi_beban_sppt,
self.sppt_op_bersama.luas_bng_beban_sppt,
self.sppt_op_bersama.njop_bumi_beban_sppt,
self.sppt_op_bersama.njop_bng_beban_sppt,
self.jenis_sektor.nm_sektor,
self.kelurahan.nm_kelurahan,
self.kecamatan.nm_kecamatan,
self.dati2.nm_dati2,
self.kanwil.nm_kanwil,
self.kantor.nm_kantor,
self.kantor.kota_terbit,
self.tempat_pembayaran.nm_tp,
self.tempat_pembayaran.alamat_tp,
self.tempat_pembayaran.no_rek_tp,
self.kode_map.kd_map,
# self.tarif.nilai_tarif,
). \
select_from(self.sppt) \
.outerjoin(
self.sppt_op_bersama,
and_(
self.sppt_op_bersama.kd_propinsi == self.sppt.kd_propinsi,
self.sppt_op_bersama.kd_dati2 == self.sppt.kd_dati2,
self.sppt_op_bersama.kd_kecamatan == self.sppt.kd_kecamatan,
self.sppt_op_bersama.kd_kelurahan == self.sppt.kd_kelurahan,
self.sppt_op_bersama.kd_blok == self.sppt.kd_blok,
self.sppt_op_bersama.no_urut == self.sppt.no_urut,
self.sppt_op_bersama.kd_jns_op == self.sppt.kd_jns_op,
self.sppt_op_bersama.thn_pajak_sppt == self.sppt.thn_pajak_sppt
)) \
.outerjoin(self.kelurahan,
and_(
self.sppt.kd_propinsi == self.kelurahan.kd_propinsi,
self.sppt.kd_dati2 == self.kelurahan.kd_dati2,
self.sppt.kd_kecamatan == self.kelurahan.kd_kecamatan,
self.sppt.kd_kelurahan == self.kelurahan.kd_kelurahan
)) \
.outerjoin(self.jenis_sektor, self.jenis_sektor.kd_sektor == self.kelurahan.kd_sektor) \
.outerjoin(self.kecamatan,
and_(
self.kecamatan.kd_propinsi == self.sppt.kd_propinsi,
self.kecamatan.kd_dati2 == self.sppt.kd_dati2,
self.kecamatan.kd_kecamatan == self.sppt.kd_kecamatan
)) \
.outerjoin(self.dati2,
and_(
self.sppt.kd_propinsi == Dati2.kd_propinsi,
self.sppt.kd_dati2 == Dati2.kd_dati2
)) \
.outerjoin(self.tempat_pembayaran,
and_(
self.tempat_pembayaran.kd_kantor == self.sppt.kd_kantor,
self.tempat_pembayaran.kd_kanwil == self.sppt.kd_kanwil,
self.tempat_pembayaran.kd_tp == self.sppt.kd_tp
)) \
.outerjoin(Kantor,
and_(
Kantor.kd_kantor == self.sppt.kd_kantor,
Kantor.kd_kanwil == self.sppt.kd_kanwil
)) \
.outerjoin(Kanwil, self.sppt.kd_kanwil == Kanwil.kd_kanwil) \
.outerjoin(DatObjekPajak,
and_(
self.dat_objek_pajak.kd_propinsi == self.sppt.kd_propinsi,
self.dat_objek_pajak.kd_dati2 == self.sppt.kd_dati2,
self.dat_objek_pajak.kd_kecamatan == self.sppt.kd_kecamatan,
self.dat_objek_pajak.kd_kelurahan == self.sppt.kd_kelurahan,
self.dat_objek_pajak.kd_blok == self.sppt.kd_blok,
self.dat_objek_pajak.no_urut == self.sppt.no_urut,
self.dat_objek_pajak.kd_jns_op == self.sppt.kd_jns_op
))\
.outerjoin(KodeMap, KodeMap.kd_sektor == self.jenis_sektor.kd_sektor)\
.filter(self.sppt.kd_propinsi == fxNop['kd_propinsi'],
self.sppt.kd_dati2 == fxNop['kd_dati2'],
self.sppt.kd_kecamatan == fxNop['kd_kecamatan'],
self.sppt.kd_kelurahan == fxNop['kd_kelurahan'],
self.sppt.kd_blok == fxNop['kd_blok'],
self.sppt.no_urut == fxNop['no_urut'],
self.sppt.kd_jns_op == fxNop['kd_jns_op'],
self.sppt.thn_pajak_sppt == tahun,
self.sppt.status_pembayaran_sppt.in_(['0', '1'])
)\
.first()
def main(argv=sys.argv):
option, remain = parsing(argv)
pdf_proses = PbbProses(argv[1], option)
act = option.action
if act == "massal":
pdf_proses.sppt_massal()
elif act == "pdf":
pdf_proses.sppt2pdf()
elif act == "ttd":
sppt_ttd(option)
elif act == "email":
send_email(argv[1], option)
else:
sys.exit("Action tidak sesuai")
from tangsel.pbb.esppt import SPPT_CLASS
from tangsel.tools import *
from tangsel.base.tools import *
from tangsel.base.tools.api import config_pars_rpc_url
from tangsel.tools.pbb import *
from tangsel.base.tools.report import *
# from tangsel.tools.db import *
# from tangsel.tools.captcha import *
from tangsel.tools.api import send_rpc
def convert_to_pdf(filename, typ, password=None, remove=True):
log.info("Start Export {}".format(filename))
settings = get_settings()
import getpass
username = getpass.getuser()
odt_file = '.'.join([filename, 'odt'])
out_dir = os.path.dirname(filename)
out_file = '.'.join([filename, typ])
if 'unoconv_py' in settings and settings['unoconv_py']:
log.info("Unoconv PY {}".format(filename))
unoconv_py = settings['unoconv_py']
if 'unoconv_bin' in settings and settings['unoconv_bin']:
unoconv_bin = settings['unoconv_bin']
else:
unoconv_bin = ''
params = [unoconv_py, unoconv_bin, '-f', 'pdf']
# if password:
# params.extend(['-e', 'EncryptFile=True',
# '-e', 'DocumentOpenPassword=' + password])
params.append(odt_file)
log.info("DEBUG EXPORT>>{}".format(' '.join(params)))
subprocess.call(params)
else:
log.info("Unoconv BIN {}".format(filename))
if 'unoconv_bin' in settings and settings['unoconv_bin']:
unoconv_bin = settings['unoconv_bin']
params = [unoconv_bin,
'-env:UserInstallation=file:///tmp/' + username,
'--headless', '--convert-to', 'pdf']
params.extend(['--outdir', out_dir, 'pdf', odt_file])
log.info("DEBUG EXPORT>>{}".format(' '.join(params)))
subprocess.call(params)
# if 'unoconv_bin' in settings and settings['unoconv_bin']:
# unoconv_bin = settings['unoconv_bin']
# params = [unoconv_bin,
# '--format=pdf']
# if password:
# params.append(f"--password={password}")
# params.extend(['-o', out_file, odt_file])
# log.debug("DEBUG EXPORT>>{}".format(' '.join(params)))
# subprocess.call(params)
if not os.path.isfile(odt_file):
log.info("ODT FILE NOTFOUND")
return dict(error=dict(code=-1,
message='File %s tidak ditemukan ' % odt_file))
else:
if not os.path.isfile(out_file):
return dict(error=dict(code=-1,
message='File %s tidak ditemukan ' % out_file))
if remove:
os.remove(odt_file)
return dict(filename=out_file)
def get_data(method, data):
auth = config_pars_rpc_url("rpc_pbb_mirror.url", method)
resp = send_rpc(auth, data)
if resp and "result" in resp:
log.info('Method: {}'.format(method))
log.info(resp["result"].get("data", ''))
return "data" in resp["result"] and resp["result"]["data"] or True
if resp and "error" in resp:
log.debug("Error get data method: %s", method)
else:
log.debug("No result from server")
return False
def get_paging(data=None, value=None):
if value:
if 'page' in value and value['page']:
if value['page'] == 0:
data['page'] = 1
else:
data['page'] = value['page']
if "page_size" in value and value['page_size']:
data['page_size'] = value['page_size']
return data
def get_sppts(nop=None, tahun=None, page=None):
data = {
"order": [
"kd_propinsi", "kd_dati2", "kd_kecamatan", "kd_kelurahan",
"kd_blok",
"no_urut", "kd_jns_op"
],
"where": []}
if nop:
data['where'].append(
dict(
key="nop",
val=nop
))
if tahun:
data['where'].append(
dict(
key="thn_pajak_sppt",
val=tahun
))
data = get_paging(data, {"page": page})
return get_data("get_sppt", data)
def get_sppt(nop, tahun):
if not SPPT_CLASS.mirror_url:
from tangsel.pbb.models import Sppt, SpptOpBersama, DatObjekPajak
sppt = Sppt.get_by_nop(nop).filter_by(thn_pajak_sppt=tahun).first()
if not sppt:
return False
dsppt = dict(sppt.__dict__)
dsppt.pop("_sa_instance_state", None)
return dsppt
data = {'where': [
dict(
key="nop",
val=nop
),
dict(
key="thn_pajak_sppt",
val=tahun
)
]}
resp = get_data("get_sppt", data)
return resp and "record" in resp and resp["record"][0] or False
def get_nop(nop):
data = {'where': [
dict(
key="nop",
val=nop
)
]}
resp = get_data("get_nop", data)
return resp and "record" in resp and resp["record"][0] or False
def get_nops_by_subjek(subjek_pajak_id, page=None, page_size=None):
data = {
'where': [
dict(
key="subjek_pajak_id",
val=subjek_pajak_id
)
],
"order": [
"kd_propinsi", "kd_dati2", "kd_kecamatan", "kd_kelurahan",
"kd_blok",
"no_urut", "kd_jns_op"
]
}
value = {}
if page:
value["page"] = page
if page_size:
value["page_sige"] = page_size
data = get_paging(data, {"page": page})
return get_data("get_nop", data)
def get_sppt_bersama(nop, tahun):
data = {'where': [
dict(
key="nop",
val=nop
),
dict(
key="thn_pajak_sppt",
val=tahun
)
]}
resp = get_data("get_sppt_bersama", data)
return resp and "record" in resp and resp["record"] or False
def get_pbb(values):
return get_paging(values)
from tangsel.base.tools.api import config_pars_rpc_url
from tangsel.base.views import base_views
from tangsel.base.views.common import DataTables, ColumnDT
from tangsel.tools.api import send_rpc
from pyramid.view import view_config
class BaseView(base_views.BaseView):
def __init__(self, request):
super(BaseView, self).__init__(request)
class Views(BaseView):
def __init__(self, request):
super().__init__(request)
# @view_config(route_name='esppt', renderer='templates/home.pt')
def view_add(self):
# self.ses.flash("Selamat datang di halaman ESPPT")
return {}
from datetime import datetime
import colander
from tangsel.base.views import BaseView
from pyramid.httpexceptions import HTTPFound
from pyramid.view import view_config
from deform import widget
from .my_nop import btn_close
from ..models.es_log import LogEspptMassal
class MassalSchema(colander.Schema):
id = colander.SchemaNode(
colander.Integer(),
widget=widget.HiddenWidget(),
missing=colander.drop,
title="ACT",)
tahun = colander.SchemaNode(
colander.String(),
title="Tahun Pajak",
default=datetime.now().year)
jenis = colander.SchemaNode(
colander.String(),
widget=widget.RadioChoiceWidget(
values=(("1", "NOP yang terdaftar"),
("2", "Semua NOP"))),
title="Jenis Proses",
default="1")
class ListSchema(MassalSchema):
jml_sppt = colander.SchemaNode(
colander.Integer(),
missing=colander.drop
)
jml_proses = colander.SchemaNode(
colander.Integer(),
missing=colander.drop
)
partner_id = colander.SchemaNode(
colander.String(),
missing=colander.drop,
title="ID WP/Halaman"
)
nop = colander.SchemaNode(
colander.String(),
missing=colander.drop,
title="Nop Terakhir"
)
status_text = colander.SchemaNode(
colander.String(),
missing=colander.drop,
title="Status"
)
class AddSchema(MassalSchema):
force = colander.SchemaNode(
colander.Integer(),
widget=widget.RadioChoiceWidget(values=((0, "Tidak"), (1, "Ya"))),
default=0,
title="Proses jika sudah ditetapkan",
oid="force")
def after_bind(self, schema, kw):
del schema["id"]
# passphrase = colander.SchemaNode(
# colander.String(),
# widget=widget.PasswordWidget(),
# oid="passphrase")
class EditSchema(MassalSchema):
jml_proses = colander.SchemaNode(
colander.Integer(),
missing=colander.drop
)
partner_id = colander.SchemaNode(
colander.String(),
missing=colander.drop,
title="ID WP/Halaman"
)
nop = colander.SchemaNode(
colander.String(),
missing=colander.drop,
title="Nop Terakhir"
)
jml_sppt = colander.SchemaNode(
colander.Integer(),
missing=colander.drop
)
status_text = colander.SchemaNode(
colander.String(),
missing=colander.drop
)
def after_bind(self, schema, kw):
req = kw.get("request")
self["tahun"].default = req.session.get("tahun")
self["tahun"].missing = colander.drop
self["jenis"].missing = colander.drop
jenis = kw.get("jenis")
if jenis and jenis == "1":
self["partner_id"].title = "ID WP"
else:
self["partner_id"].title = "Halaman"
class Views(BaseView):
def __init__(self, request):
super().__init__(request)
self.list_schema = ListSchema
self.list_route = "esppt-massal"
self.add_schema = AddSchema
self.edit_schema = EditSchema
self.table = LogEspptMassal
self.allow_edit = False
def form_validator(self, form, value):
exc = colander.Invalid(form, "")
found = self.table.query().filter_by(tahun=value.get("tahun")).first()
if found and not value.get("force"):
exc["tahun"] = "Sudah terdapat penetapan tahun berjalan"
raise exc
if not self.req.matchdict.get("id") or value.get("force"):
value["status"] = 0
value["jml_sppt"] = 0
value["jml_proses"] = 0
value["row"] = found
def save_request(self, values, row=None):
if "row" in values:
row = values["row"]
del values["row"]
values['status'] = 0
row = super().save_request(values, row)
self.ses.flash("E-SPPT berhasil dimasukan kedalam antrian")
return row
def get_values(self, row, istime=False):
values = super().get_values(row, istime)
values["jml_proses"] = row.jml_proses
values["jml_sppt"] = row.jml_sppt
values["status_text"] = row.status_text
return values
def id_not_found(self):
msg = f"Tidak ada data penetapan massal"
self.req.session.flash(msg, 'error')
return self.route_list()
def before_delete(self, row):
if row.status and row.status > 0:
msg = f"Data penetapan massal tidak bisa dihapus"
raise Exception(msg)
import logging
import re
import os
import colander
from deform import widget, FileData, Button
from tangsel.base import has_permission_
from tangsel.base.tools.api import config_pars_rpc_url
from tangsel.base.models import Partner, flush
from tangsel.tools import mem_tmp_store, image_validator, Upload, img_exts
from tangsel.tools.buttons import (
btn_add, btn_close, btn_save, btn_cancel, btn_delete, btn_recall)
from tangsel.tools.api import send_rpc
from pyramid.view import view_config
from sqlalchemy import or_
from tangsel.pbb.esppt import SPPT_CLASS
from ..models import STATUS_NOP, PartnerNop
from ..views import BaseView
log = logging.getLogger(__name__)
btn_add.title = "Tambah"
btn_close.title = "Tutup"
btn_save.title = "Simpan"
btn_cancel.title = "Batal"
btn_delete.title = 'Hapus'
class ListSchema(colander.Schema):
id = colander.SchemaNode(
colander.Integer(),
title="Action")
nop_formatted = colander.SchemaNode(
colander.String(),
title="NOP")
thn_awal = colander.SchemaNode(
colander.String(),
title="Thn Kepemilikan", width=100)
thn_akhir = colander.SchemaNode(
colander.String(),
title="Penetapan Akhir", width=100)
dokumen = colander.SchemaNode(
colander.String(),
oid="dokumen",
title="Dokumen"
)
status = colander.SchemaNode(
colander.String(),
widget=widget.SelectWidget(values=STATUS_NOP)
)
# status_text = colander.SchemaNode(
# colander.String(),
# oid="status_text",
# title="Status",
# width=100)
def after_bind(self, schema, kw):
request = kw.get("request")
self["dokumen"].url = request.static_url(SPPT_CLASS.files_bukti)
class AddSchema(colander.Schema):
nop = colander.SchemaNode(
colander.String(),
widget=widget.TextInputWidget(mask="99.99-999.999-999.9999.9"),
oid="nop",
description="PP.KK-CCC.DDD-BBB.UUUU.J")
thn_awal = colander.SchemaNode(
colander.Integer(),
title="Tahun Kepemilikan",
)
# thn_akhir = colander.SchemaNode(
# colander.String(),
# missing=colander.drop,
# title="Tahun Akhir"
# )
dokumen = colander.SchemaNode(
FileData(),
widget=widget.FileUploadWidget(
mem_tmp_store,
accept="application/pdf, image/png, image/jpg, image/jpeg"),
title="Dokumen",
validator=image_validator)
status = colander.SchemaNode(
colander.Integer(),
widget=widget.HiddenWidget(readonly=True),
missing=colander.drop)
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.list_route = "esppt-mynop"
self.table = PartnerNop
def form_validator(self, form, values):
exc = colander.Invalid(form, "")
def err_nop():
exc["nop"] = "NOP tidak ditemukan"
raise exc
def err_nopexists():
exc["nop"] = "NOP sudah ada"
raise exc
def err_partner():
exc.msg = "Silahkan lakukan pengisian data pribadi"
raise exc
nop = re.sub("\D", "", values["nop"])
values["nop"] = nop
partner = self.get_partner()
if not partner:
err_partner()
nop_exist = PartnerNop.query().filter(PartnerNop.nop == nop,
PartnerNop.partner_id == partner.id).first()
if nop_exist:
err_nopexists()
if not SPPT_CLASS.rpc_pbb_mirror_url:
from tangsel.pbb.models import DatObjekPajak
dop = DatObjekPajak.query_nop(nop).first()
if not dop:
err_nop()
result = dict(dop.__dict__)
result.pop("_sa_instance_state", None)
else:
data = {'where': [
{
"key": "nop",
"val": nop},
]}
auth = config_pars_rpc_url("rpc_pbb_mirror.url", "get_nop")
resp = send_rpc(auth, data)
if not resp or "error" in resp:
err_nop()
result = resp["result"]["data"]["record"][0]
values.update(result)
values["partner_id"] = partner.id
if partner.kode.strip() == result["subjek_pajak_id"].strip():
values["status"] = 1
# @view_config(route_name='esppt-nop-edit', renderer='templates/form.pt',
# permission='view')
# def view_edit(self):
# self.buttons = (btn_save, btn_cancel)
# row = self.query_id().first()
# if not row:
# return self.id_not_found()
# if row.status:
# self.ses.flash("Data hanya bisa dilihat", "error")
# return self.route_list()
# return super().view_edit()
def before_delete(self, row):
if (getattr(row, 'status', '') == 1):
msg = "{} tidak bisa dihapus".format(getattr(row, 'status_text'))
self.req.session.flash(msg, 'error')
raise self.route_list()
def view_view(self):
request = self.req
row = self.query_id().first()
if not row:
return self.id_not_found()
bindings = self.get_bindings(row)
btn_recall = Button('recall', title='Proses Ulang', css_class="btn-info",
type="submit")
button = row.status == 2 and btn_recall or btn_cancel
form = self.get_form(self.edit_schema, buttons=(button, btn_close),
bindings=bindings)
if request.POST:
msg = ""
if "cancel" in request.POST:
row.status = 2
flush(row)
msg = "Berhasil memproses pembatalan"
elif "recall" in request.POST:
row.status = 0
flush(row)
msg = "Berhasil memasukan ke dalam draft"
return self.route_list(msg=msg)
form.set_appstruct(self.get_values(row))
return dict(form=form.render(readonly=True),
table=None,
scripts=self.form_scripts)
def list_filter(self, query):
# todo: integrasi dengan NIK yang sama
if not has_permission_(self.req, 'esppt-admin'):
query = query.filter(self.table.create_uid == self.req.user.id)
return query.order_by(self.table.nop)
def query_id(self):
qry = super().query_id()
return qry.filter(self.table.create_uid == self.req.user.id)
def save_request(self, values, row=None):
if "dokumen" in values and values["dokumen"]:
from webob.compat import cgi_FieldStorage
dok_type = type(self.req.POST['upload'])
log.debug(f"Upload Data Type : {dok_type}")
if dok_type == cgi_FieldStorage:
folder = SPPT_CLASS.files_bukti
upload = Upload(folder)
file_name = upload.save(self.req, 'upload', img_exts)
log.debug(f"Bukti: {folder}/{file_name}")
values["dokumen"] = file_name
else:
del values["dokumen"]
if not 'status' in values or not values['status']:
values.update(dict(status=0))
row = super().save_request(values, row)
return row
def get_partner(self):
return Partner.query_email(self.req.user.email).first()
def get_values(self, row, istime=False):
d = super().get_values(row, istime)
if "dokumen" in d and d["dokumen"]:
filename = d["dokumen"]
url = self.req.static_url(SPPT_CLASS.files_bukti)
preview_url = os.path.join(url, filename)
d["dokumen"] = {"uid": filename.split(".")[0],
"filename": filename,
"preview_url": preview_url
}
return d
import logging
import os
import colander
from deform import widget, FileData
from tangsel.tools import mem_tmp_store, number_only
from deform import ValidationFailure, widget
from tangsel.base.models import flush
# from tangsel.pbb.tools import WIDGET_NOP
from tangsel.pbb.esppt import SPPT_CLASS
from tangsel.tools import number_only
from tangsel.tools.buttons import btn_cancel, btn_proses
from tangsel.tools.pbb import FixNop
from ..models import Partner, LogEsppt, PartnerNop
from ..models.es_log import Passphrase
from ..tools import get_data
from . import BaseView
from .my_sppt import ListSchema, btn_close
# , list_column
log = logging.getLogger(__name__)
btn_proses.title = "Proses"
class AddSchema(colander.Schema):
nop = colander.SchemaNode(
colander.String(),
# widget=WIDGET_NOP,
oid="nop")
tahun = colander.SchemaNode(
colander.String(),
title="Tahun SPPT",
oid="tahun")
# nm_wp_sppt = colander.SchemaNode(
# colander.String(),
# title="Nama WP")
# siklus_sppt = colander.SchemaNode(
# colander.String(),
# global_search=False,
# title="Siklus")
# file_name = colander.SchemaNode(
# colander.String(),
# title="Link")
# password = colander.SchemaNode(
# colander.String(),
# title="Passphrase",
# oid="password")
class EditSchema(ListSchema):
id = colander.SchemaNode(
colander.Integer(),
missing=colander.drop,
widget=widget.HiddenWidget(readonly=True)
)
def after_bind(self, schema, kw):
log.debug(schema)
log.debug(kw)
schema["nop"].widget = widget.TextInputWidget(readonly=True)
schema["nop"].missing = colander.drop
schema["tahun"].widget = widget.TextInputWidget(readonly=True)
schema["tahun"].missing = colander.drop
schema["file_name"] = colander.SchemaNode(
FileData(),
widget=widget.FileUploadWidget(tmpstore=mem_tmp_store),
missing=colander.drop,
title="e-SPPT"
)
del schema["status_text"]
SESS_ADD_FAILED = 'Tambah proses gagal'
SESS_EDIT_FAILED = 'Edit proses gagal'
def get_pbb_data(method, data):
resp = get_data(method, data)
if resp:
return resp
raise Exception("Gagal mendapatkan data dari server")
class Views(BaseView):
def __init__(self, request):
super().__init__(request)
self.list_schema = ListSchema
self.add_schema = AddSchema
self.edit_schema = EditSchema
self.list_buttons = (btn_close,)
self.table = LogEsppt
self.list_route = "esppt-parsial"
def list_join(self, query, **kwargs):
return query.outerjoin(Partner, Partner.id == LogEsppt.partner_id)
# def list_filter(self, query, **kwargs):
# return query.filter(self.table.status != 1)
def next_edit(self, form, **kwargs):
row = kwargs.get("row")
request = self.req
resources = form.get_widget_resources()
if row.status != 1 and "proses" in self.req.POST:
controls = request.POST.items()
try:
controls = form.validate(controls)
except ValidationFailure as e:
log.debug(f"Edit Error: {str(e.error)}")
log.debug(f"Edit Data: {e.cstruct}")
values = self.get_values(row)
form.set_appstruct(values)
return dict(form=form.render(),
table=None,
scripts=self.form_scripts, css=resources["css"],
js=resources["js"])
row.status = 0
flush(row)
self.ses.flash('Data Sudah masuk kedalam antrian kembali')
return self.route_list()
# @view_config(route_name='esppt-parsial-edit',
# renderer='templates/form.pt',
# permission='esppt-tetap')
def view_edit(self):
self.buttons = (btn_proses, btn_cancel)
return super().view_edit()
def get_values(self, row, istime=False):
v = super().get_values(row, istime)
v["nop"] = row.nop
v["status_text"] = row.status_text
if row.file_name:
filename=row.file_name
url=self.req.static_url(SPPT_CLASS.files_final)
preview_url=os.path.join(url, filename)
v["file_name"]={"uid": filename.split(".")[0],
"filename": filename,
"preview_url": preview_url
}
v["nama"]=row.partner and row.partner.nama or ""
return v
def esppt_parsial_add(self):
btn_proses.type = "submit"
self.buttons = (btn_proses, btn_cancel)
return super().view_add()
def form_response(self, form, values, msg):
self.ses.flash(msg, "error")
form.set_appstruct(values)
return dict(form=form.render())
def get_sppt(self, values):
if SPPT_CLASS.mirror_url:
data = {
'where': [
{
"key": "nop",
"val": values["nop"]},
{
"key": "thn_pajak_sppt",
"val": values["tahun"]
}
]}
try:
resp = get_pbb_data("get_sppt", data)
except Exception as e:
msg = str(e)
raise Exception(msg)
return resp["record"][0]
else:
from tangsel.pbb.models import Sppt
sppt = Sppt.get_by_nop(values["nop"]). \
filter_by(thn_pajak_sppt=values["tahun"]).first()
if not sppt:
raise Exception("Data tidak ada")
sppt = dict(sppt.__dict__)
sppt.pop("_sa_instance_state", None)
return sppt
def next_add(self, form, **kwargs):
if self.req.POST:
if "proses" in self.req.POST:
controls = self.req.POST.items()
try:
c = form.validate(controls)
except ValidationFailure as e:
return self.form_response(form, e.cstruct, str(e))
values = dict(c)
try:
sppt = self.get_sppt(values)
destination = self.get_destination(values)
except Exception as e:
return self.form_response(form, values, str(e))
values["destination"] = destination
values["siklus_sppt"] = sppt["siklus_sppt"]
self.save_request(values)
msg = "Berhasil Tambah Data"
return self.route_list(msg)
def get_destination(self, values):
values["nop"] = number_only(values["nop"])
data = {
'where': [
{
"key": "nop",
"val": values["nop"]},
]}
try:
resp = get_pbb_data("get_nop", data)
except Exception as msg:
raise Exception(str(msg))
objek = resp["record"][0]
msg = "Data tidak ada"
if objek:
subjek_pajak_id = objek["subjek_pajak_id"]
log.debug(f"NOP to be executed: {values['nop']}")
partner_nop = PartnerNop.query().filter(
PartnerNop.nop == values["nop"],
PartnerNop.status == 1).first()
if partner_nop:
partner = Partner.query_id(partner_nop.partner_id).first()
if partner and partner.email:
return partner.email
msg = f"NIK {subjek_pajak_id} tidak ditemukan di data wajib pajak"
raise Exception(msg)
def save_request(self, values, row=None):
row = LogEsppt.query_nop(values['nop']). \
filter_by(status=0,
siklus_sppt=values["siklus_sppt"]). \
first()
nop = FixNop(values["nop"])
values.update(nop.to_dict())
if not row:
self.save(values, self.req.user)
passphrase = Passphrase.query().first()
if not passphrase:
passphrase = Passphrase()
passphrase.password = values["password"]
flush(passphrase)
LogEsppt.query().filter(LogEsppt.status < 0).update(
{LogEsppt.status: 0})
from calendar import c
from datetime import datetime
import os
import colander
from deform import (widget, Form, ValidationFailure, FileData, )
from . import BaseView
from .. import SPPT_CLASS
from tangsel.tools.buttons import btn_cancel, btn_upload
from pyramid.httpexceptions import HTTPFound
from tangsel.tools import mem_tmp_store, date_from_str
# class ListSchema(colander.Schema):
# id =colander.SchemaNode(
# colander.Integer(),
# title="Act",
# missing=colander.drop,
# widget=widget.HiddenWidget()
# )
# tahun = colander.SchemaNode(
# colander.String(),
# widget=widget.TextInputWidget(mask="9999"),
# default=str(datetime.now().year)
# )
# file_upload = colander.SchemaNode(
# FileData(),
# widget=widget.FileUploadWidget(mem_tmp_store),
# title='Unggah',
# )
# class EditSchema(ListSchema):
# pass
class AddSchema(colander.Schema):
tahun = colander.SchemaNode(
colander.String(),
widget=widget.TextInputWidget(mask="9999"),
default=str(datetime.now().year)
)
jrmxl_file = colander.SchemaNode(
FileData(),
widget=widget.FileUploadWidget(mem_tmp_store, accept=".jrxml"),
title='Format (jrxml)',
# description="""
# File yang diupload berupa
# 1. sppt.jrxml berisi XML penempatan posisi field
# 2. sppt.jpg background gambar SPPT
# 3. sppt.txt berisi penulisan pembayaran
# 4. ttd.png berisi ttd electronic
# File akan disimpan sesuai dengan tahun yang diisi
# """
)
bg_file = colander.SchemaNode(
FileData(),
widget=widget.FileUploadWidget(mem_tmp_store, accept=".jpg"),
title='Background (jpg)',
)
txt_file = colander.SchemaNode(
colander.String(),
missing=colander.drop,
widget=widget.TextAreaWidget(),
title='Tempat Pembayaran (txt)',
)
ttd_file = colander.SchemaNode(
FileData(),
widget=widget.FileUploadWidget(mem_tmp_store, accept=".png"),
title='TTD Image (png)',
)
set_default = colander.SchemaNode(
colander.Boolean(),
widget=widget.CheckboxWidget(),
title='Set Default',
# description="Set sebagai default template",
)
class Views(BaseView):
def __init__(self, request):
super().__init__(request)
self.add_schema = AddSchema
self.upload_exts = (".jrxml", ".jpg", ".txt", ".png")
self.buttons = (btn_upload, btn_cancel)
def view_upload(self):
return super().view_add()
def form_validator(self, form, value):
folder = SPPT_CLASS.files_tpl
file_name = value.get("tahun")
tahun = value.get("tahun")
exc = colander.Invalid(form, "")
set_default = value.get("set_default")
if set_default:
file_name="sppt"
txt = value.get("txt_file")
try:
value["jrmxl_file"] = self.save_file(
value, 'jrmxl_file', folder, file_name)
except Exception as e:
exc["jrmxl_file"] = str(e)
raise exc
try:
value["bg_file"] = self.save_file(
value, 'bg_file', folder, file_name)
except Exception as e:
exc["bg_file"] = str(e)
raise exc
try:
with open(os.path.join(folder, f"{file_name}.txt"), "w") as f:
f.write(txt)
except Exception as e:
exc["txt_file"] = str(e)
raise exc
try:
value["ttd_file"] = self.save_file(
value, 'ttd_file', folder, file_name)
except Exception as e:
exc["ttd_file"] = str(e)
raise exc
def next_add(self, form, **kwargs):
table = None
if "upload" in self.req.POST:
controls = self.req.POST.items()
try:
c = form.validate(controls)
except ValidationFailure as e:
value = self.before_add()
for f in e.field.children:
if isinstance(f.typ, colander.Date):
e.cstruct[f.name] = date_from_str(
e.cstruct[f.name])
value = self.update_value(value, e.cstruct)
form.set_appstruct(value)
return self.returned_form(form, **kwargs)
# values = self.form_validate(form, self.before_add, **kwargs)
# if type(values) != dict or values.get("form"):
# return values
# self.ses.flash(f"Upload File {values['file_name']} berhasil ")
return HTTPFound(self.req.route_url("esppt-template"))
<html metal:use-macro="load: tangsel.base:views/templates/base5.pt" tal:define="
route_name request.matched_route.name;
">
<ul metal:fill-slot="navs" style="margin-top: 0; padding-top: 0;">
<li tal:repeat="menu get_esppt_menus()" tal:attributes="class route_name in menu['route_name'] and 'active'">
<a tal:condition="python: not menu['children'] and (not menu['permission'] or has_permission(request, menu['permission']))"
href="${home}${menu['path']}">
<i tal:condition="menu['icon']" class="fa fa-lg fa-fw ${menu['icon']}"></i>
<span>${menu['nama']}</span>
</a>
<a tal:condition="python:menu['children'] and (not menu['permission'] or has_permission(request, menu['permission']))"
href="#">
<i tal:condition="menu['icon']" class="fa fa-lg fa-fw ${menu['icon']}"></i>
<span class="menu-item-parent">${menu['nama']}</span>
</a>
<ul
tal:condition="python:menu['children'] and (not menu['permission'] or has_permission(request, menu['permission']))">
<li tal:repeat="submenu menu['children']" tal:attributes="class route_name in submenu['route_name'] and 'active'">
<a tal:condition="python:not submenu['children'] and (not menu['permission'] or has_permission(request, submenu['permission']))"
href="${home}${submenu['path']}">
<i tal:condition="submenu['icon']" class="fa fa-lg fa-fw ${submenu['icon']}"></i>
<span>${submenu['nama']}</span>
</a>
<a tal:condition="submenu['children']" href="#">
<i tal:condition="submenu['icon']" class="fa fa-lg fa-fw ${submenu['icon']}"></i>
<span class="menu-item-parent">${submenu['nama']}</span>
</a>
<ul tal:condition="submenu['children']">
<li tal:repeat="submenu2 submenu['children']"
tal:attributes="class route_name in submenu2['route_name'] and 'active'">
<a href="${home}${submenu2['path']}">${submenu2['nama']}</a>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</html>
\ No newline at end of file \ No newline at end of file
<html metal:use-macro="load: ./base.pt">
<div metal:fill-slot="content">
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title"><i class="fa fa-fw fa-plus"></i>&nbsp;${request.title}</h3>
</div>
<div class="panel-body">
<div tal:content="structure form"></div>
</div>
</div>
</div>
<script metal:fill-slot="scripts">
$(document).ready(function () {
${ structure: scripts }
});
</script>
</html>
\ No newline at end of file \ No newline at end of file
<html metal:use-macro="load: ./base.pt" tal:define="scripts scripts|scripts">
<div metal:fill-slot="content">
<div class="col-md-6 col-md-offset-3">
<div class="panel panel-default">
<!-- <div class="panel-heading"> -->
<!-- <h3 class="panel-title"><i class="fa fa-fw fa-plus"></i>&nbsp;${request.title}</h3> -->
<!-- </div> -->
<div class="panel-body">
<div tal:content="structure form"></div>
</div>
</div>
</div>
</div>
<div metal:fill-slot="scripts">
<script>
$(document).ready(function () {
// $(".read-only").attr("readonly", true);
$(".readonly").attr("readonly", true);
$(".date").attr("readonly", true);
// $(".date").datepicker({
// format: 'dd-mm-yyyy'
// });
${ structure: scripts }
});
</script>
<div metal:define-slot="scripts"></div>
</div>
</html>
\ No newline at end of file \ No newline at end of file
<html metal:use-macro="load: ./base.pt" tal:define="scripts scripts|scripts">
<div metal:fill-slot="content">
<div class="col-md-8 col-md-offset-2">
<div class="panel panel-default">
<!-- <div class="panel-heading"> -->
<!-- <h3 class="panel-title"><i class="fa fa-fw fa-plus"></i>&nbsp;${request.title}</h3> -->
<!-- </div> -->
<div class="panel-body">
<div tal:content="structure form"></div>
</div>
</div>
</div>
</div>
<div metal:fill-slot="scripts">
<script>
$(document).ready(function () {
// $(".read-only").attr("readonly", true);
$(".readonly").attr("readonly", true);
$(".date").attr("readonly", true);
// $(".date").datepicker({
// format: 'dd-mm-yyyy'
// });
${ structure: scripts }
});
</script>
<div metal:define-slot="scripts"></div>
</div>
</html>
\ No newline at end of file \ No newline at end of file
<html metal:use-macro="load: ./base.pt">
<div metal:fill-slot="content">
<div class="col-md-8 col-md-offset-2">
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title"><i class="fa fa-fw fa-plus"></i>&nbsp;${request.title}</h3>
<H4>Module ini berfungsi untuk:</H4>
<ul>
<li>Melihat Mengunduh e-SPPT jika sudah diproses</li>
<li>Memproses Pembuatan e-SPPT Massal</li>
<li>Memproses Pembuatan e-SPPT Terseleksi</li>
<li>Monitoring status proses pembuatan e-SPPT</li>
</ul>
</div>
<div class="panel-body">
Silahkan <a href="${home}/register">Registrasi</a> atau <a href="${home}/pbb/esppt/unduh/add">Unduh</a>
</div>
</div>
</div>
</div>
</html>
\ No newline at end of file \ No newline at end of file
<html metal:use-macro="load: ../base.pt">
<div metal:fill-slot="content">
<script src="${home}/deform_static/scripts/deform.js"></script>
<script>
/**
* Nicer looking file inputs for bootstrap 3
* By Jeff Dairiki <dairiki@dairiki.org> based on ideas from
* http://www.abeautifulsite.net/blog/2013/08/whipping-file-inputs-into-shape-with-bootstrap-3/
*/
(function ($) {
var Upload = function (element, options) {
this.$element = $(element);
this.options = $.extend({}, Upload.DEFAULTS,
this.$element.data(),
options);
this.orig_style = this.$element.attr('style');
this.$input_group = $(this.options.template)
.replaceAll(this.$element)
.attr('style', this.orig_style)
.css({position: 'relative', overflow: 'hidden'});
this.$input_group.find(':text').before(this.$element);
this.$element
.on('change.deform.upload', $.proxy(this, 'update'))
.css(this.options.element_style);
this.update();
};
Upload.DEFAULTS = {
filename: null,
selectfile: 'Ganti file…',
changefile: 'Unggah file…',
template: '<div>'
+ '<div class="input-group">'
+ '<span class="input-group-btn">'
+ '<span class="btn btn-default btn-file"></span>'
+ '</span>'
+ '<input type="text" readonly=""'
+ ' class="form-control upload-filename"/>'
+ '</div>'
+ '</div>',
element_style: {
position: 'absolute',
/* Older FF (3.5) seems to put a margin on the bottom of
* the file input (the margin is proportional to
* font-size, so in this case it's significant.) Shift
* bottom a bit to allow for some slop.
*/
//bottom: '0',
bottom: '-40px',
right: '0',
minWidth: '100%',
minHeight: '100%',
fontSize: '999px',
textAlign: 'right',
filter: 'alpha(opacity=0)',
opacity: '0',
background: 'red',
cursor: 'inherit',
display: 'block'
}
};
Upload.prototype.update = function () {
var selected_filename = this.$element.val().replace(/.*[\\\/]/, ''),
options = this.options,
filename = selected_filename || options.filename;
this.$input_group.find(':text')
.val(filename);
this.$input_group.find('.btn-file')
.text(filename ? options.changefile : options.selectfile);
};
Upload.prototype.destroy = function () {
this.$element
.off('.deform.upload')
.attr('style', this.orig_style || null)
.replaceAll(this.$input_group)
.removeData('deform.upload');
};
////////////////////////////////////////////////////////////////
// plugin definition
var old = $.fn.upload;
$.fn.upload = function (option) {
return this.each(function () {
var $this = $(this),
data = $this.data('deform.upload');
if (!data) {
var options = typeof option == 'object' && option;
data = new Upload(this, options);
$this.data('deform.upload', data);
}
if (typeof option == 'string') {
data[option]();
}
});
};
$.fn.upload.Constructor = Upload;
$.fn.upload.noConflict = function () {
$.fn.upload = old;
return this;
};
})(window.jQuery);
</script>
<div class="row">
<div class="col-sm-10 col-sm-offset-1 col-md-8 col-md-offset-2 col-lg-8 col-lg-offset-2">
<div class="well">
<form id="upload_sppt" action="" method="POST" enctype="multipart/form-data" accept-charset="utf-8" class="form-horizontal">
<div class="form-group" tal:define="field form_upload['upload']" id="form-${field.oid}">
<label for="${field.oid}" class="${field.required and 'required' or ''} control-label col-md-3" id="req-${field.oid}">
${field.title}</label>
<div class="col-md-4">
${structure:field.serialize()}
<p id="error-${field.oid}" class="help-block" tal:condition="field.error"
tal:repeat="error field.error.messages()">
${error}</p>
</div>
</div>
<div class="modal-footer">
<button type="submit" class="btn btn-primary">Import</button>
<button type="button" class="btn btn-default" data-dismiss="modal">Tutup</button>
</div>
</form>
</div>
</div>
</div>
</div>
</html>
<html metal:use-macro="load: ../base-no-frame.pt">
<div metal:fill-slot="content">
<h3>Update Profile e-SPPT</h3>
<form method="post" accept-charset="utf-8" id="deform" class="form-horizontal"
enctype="multipart/form-data" tal:define="field form">
<input type="hidden" name="_charset_">
<input type="hidden" value="deform" name="__formid__">
<div class="alert alert-danger" tal:condition="field.error">
<div class="errorMsgLbl" i18n:translate=""
>Terdapat kesalahan pengisian</div>
<p class="errorMsg">${field.errormsg}</p>
</div>
<div class="col-md-6">
<div class="form-group" tal:repeat="field form">
<label class="control-label col-md-3">${field.title}</label>
<div class="col-md-8">
${structure:field.serialize()}
<p id="error-${field.oid}" class="help-block" tal:condition="field.error"
tal:repeat="error field.error.messages()">
${error}</p>
</div>
</div>
<label class="control-label text-danger" for="password2">** Data di Isi sesuai dengan yang tertera pada KTP</label>
<div class="form-group">
<label class="control-label col-xs-4">&nbsp;</label>
<div class="col-xs-8">
<button type="submit" class="btn btn-primary btn-lg" id="btn_save" name="simpan">Simpan</button>
<button type="submit" class="btn btn-info btn-lg" id="btn_cancel" name="batal">Batal</button>
</div>
</div>
</div>
</form>
<div class="panel-body">
</div>
</div>
<div metal:fill-slot="scripts">
<script>
$(document).ready(function () {
//$("#kode").attr('readonly',true);
$("#email").prop('readonly',true);
$("#email").prop('readonly',true);
});
</script>
</div>
</html>
<html metal:use-macro="load: ../base-no-frame.pt">
<div metal:fill-slot="content">
<h3>Update Profile e-SPPT</h3>
<div class="panel-body">
<form method="post" accept-charset="utf-8" id="deform" class="form-horizontal"
enctype="multipart/form-data" tal:define="field form">
<input type="hidden" name="_charset_">
<input type="hidden" value="deform" name="__formid__">
<div class="alert alert-danger" tal:condition="field.error">
<div class="errorMsgLbl" i18n:translate=""
>Terdapat kesalahan pengisian</div>
<p class="errorMsg">${field.errormsg}</p>
</div>
<div class="col-md-6">
<div class="form-group" tal:repeat="field form">
<label class="control-label col-md-3">${field.title}</label>
<div class="col-md-8">
${structure:field.serialize()}
<p id="error-${field.oid}" class="help-block" tal:condition="field.error"
tal:repeat="error field.error.messages()">
${error}</p>
</div>
</div>
<label class="control-label text-danger" for="password2">** Data di Isi sesuai dengan yang tertera pada KTP</label>
<div class="form-group">
<label class="control-label col-xs-4">&nbsp;</label>
<div class="col-xs-8">
<button type="submit" class="btn btn-primary btn-lg" id="btn_save" name="simpan">Simpan</button>
<button type="submit" class="btn btn-info btn-lg" id="btn_cancel" name="batal">Batal</button>
</div>
</div>
</div>
</form>
</div>
<script>
$(document).ready(function () {
$("#kode").attr('readonly',true);
});
</script>
</div>
</html>
<html metal:use-macro="load: ../base.pt">
<div metal:fill-slot="content">
<div class="panel-body">
<img src="/static/img/logo.png" style="height:80px;" />
<img src="/static/img/esppt.png" style="height:80px;" />
<div class="row">
<form method="post" accept-charset="utf-8" id="deform" class="form-horizontal"
enctype="multipart/form-data" tal:define="field form">
<input type="hidden" name="_charset_">
<input type="hidden" value="deform" name="__formid__">
<div class="alert alert-danger" tal:condition="field.error">
<div class="errorMsgLbl" i18n:translate=""
>Terdapat kesalahan pengisian</div>
<p class="errorMsg">${field.errormsg}</p>
</div>
<div class="col-md-6">
<div class="panel panel-primary">
<div class="panel-heading">
<h3 class="panel-title">IDENTITAS PEMILIK/PEMANFAAT/PENGELOLA OBJEK PAJAK PBB</h3>
</div>
<div class="panel-body">
${form.start_mapping('regschema')}
<div class="form-group" tal:repeat="field form['regschema']">
<label class="control-label col-md-3">${field.title}</label>
<div class="col-md-8">
${structure:field.serialize()}
<p id="error-${field.oid}" class="help-block" tal:condition="field.error"
tal:repeat="error field.error.messages()">
${error}</p>
</div>
</div>
${form.end_mapping('regschema')}
<div class="col-xs-8">
<label class="control-label text-danger" for="password2">** Data di Isi sesuai dengan yang tertera pada KTP</label>
<p> </p>
</div>
</div>
</div>
</div>
<div class="col-md-6">
<div class="panel panel-primary">
<div class="panel-heading">
<h3 class="panel-title">OBJEK PAJAK</h3>
</div>
<div class="panel-body">
${form.start_mapping('nopschema')}
<div class="form-group" tal:repeat="field form['nopschema']">
<label class="control-label col-md-3">${field.title}</label>
<div class="col-md-8">
${structure:field.serialize()}
<p id="error-${field.oid}" class="help-block" tal:condition="field.error"
tal:repeat="error field.error.messages()">
${error}</p>
</div>
</div>
${form.end_mapping('nopschema')}
<div class="form-group">
<label class="control-label col-xs-4">&nbsp;</label>
<div class="col-xs-8">
<button type="submit" class="btn btn-primary btn-lg" id="btn_save" name="register">Register</button>
<button type="submit" class="btn btn-info btn-lg" id="btn_cancel" name="batal">Batal</button>
</div>
</div>
<div class="form-group">
<strong>&nbsp;Ketentuan Umum:</strong>
<ol>
<li>Formulir Registrasi ini di gunakan untuk menyampaikan Surat Pemberitahuan Pajak Terhutang (SPPT) PBB melalui Surat Elektronik (e-mail)</li>
<li>Penyampaian SPPT PBB melalui e-mail ini disamakan dengan SPPT PBB yang dicetak massal;</li>
<li>Formulir Registrasi e-SPPT PBB di isi dengan lengkap dan benar;</li>
<li>Formulir registrasi ini diisi oleh wajib pajak atau kuasa wajib pajak dengan dilampirkan kuasa wajib pajak.</li>
</ol>
<strong>&nbsp;Ketentuan Khusus:</strong>
<ol>
<li>Kesalahan penulisan pada formulir registrasi yang menyebabkan tidak sampainya e-SPPT PBB dianggap SPPT sudah tersampaikan;</li>
<li>Tanggal Status terkirim pada aplikasi e-SPPT PBB merupakan tanggal dikirimnya SPPT oleh wajib pajak;</li>
<li>Dengan mengisi dan menandatangani Formulir e-SPPT PBB ini kami mengetahui, menyetujui dan bertanggungjawab atas informasi dan ketentuan tersebut</li>
<ol>
</div>
</div>
</div>
</div>
</form>
</div>
</div>
</div>
<div metal:fill-slot="scripts">
<script>
$(document).ready(function () {
$('#tgl_bayar').datepicker({
changeMonth: true,
changeYear: true,
dateFormat:'dd-mm-yy'
});
//$('#nop').mask("99.99.999.999-999.9999.9",
// {placeholder:"#"});
});
</script>
</div>
</html>
\ No newline at end of file \ No newline at end of file
Generic single-database configuration.
\ No newline at end of file \ No newline at end of file
"""Pyramid bootstrap environment. """
import logging
import os
import importlib.machinery
import cx_Oracle
from alembic import context
from pyramid.paster import (
get_appsettings,
setup_logging,
)
from sqlalchemy import engine_from_config
from tangsel.models.meta import Base
config = context.config
setup_logging(config.config_file_name)
settings = get_appsettings(config.config_file_name)
logging.info(settings)
target_metadata = Base.metadata
current_dir = os.path.split(__file__)[0]
helper_file = os.path.join(current_dir, 'helpers.py')
loader = importlib.machinery.SourceFileLoader('alembic_helpers', helper_file)
helpers = loader.load_module()
version_table = 'alembic_pbb'
version_table_schema = 'pbb'
def run_migrations_offline():
"""Run migrations in 'offline' mode.
This configures the context with just a URL
and not an Engine, though an Engine is acceptable
here as well. By skipping the Engine creation
we don't even need a DBAPI to be available.
Calls to context.execute() here emit the given string to the
script output.
"""
context.configure(url=settings['pbb.url'],
version_table=version_table)
with context.begin_transaction():
context.run_migrations()
def run_migrations_online():
"""Run migrations in 'online' mode.
In this scenario we need to create an Engine
and associate a connection with the context.
"""
if "lib_dir" in settings and settings["lib_dir"]:
lib_dir = rf"{settings['lib_dir']}"
cx_Oracle.init_oracle_client(lib_dir=lib_dir)
engine = engine_from_config(settings, prefix='pbb.')
connection = engine.connect()
context.configure(
connection=connection,
target_metadata=target_metadata,
helpers=helpers,
version_table=version_table,
version_table_schema=version_table_schema
)
try:
with context.begin_transaction():
context.run_migrations()
finally:
connection.close()
if context.is_offline_mode():
run_migrations_offline()
else:
run_migrations_online()
# http://www.derstappen-it.de/tech-blog/sqlalchemie-alembic-check-if-table-has-column
from alembic import op
from sqlalchemy.engine import reflection
import sqlalchemy as sa
def has_table(table, schema=None, insp=None):
if not insp:
engine = op.get_bind()
insp = reflection.Inspector.from_engine(engine)
return insp.has_table(table, schema=schema)
def table_has_column(table, column, schema=None):
engine = op.get_bind()
insp = reflection.Inspector.from_engine(engine)
has_column = False
if has_table(table, schema, insp):
for col in insp.get_columns(table, schema=schema):
if column != col['name']:
continue
has_column = True
else:
has_column = True
return has_column
def table_has_seq(table, name, schema=None):
engine = op.get_bind()
insp = reflection.Inspector.from_engine(engine)
has_seq = False
if has_table(table, schema, insp):
for seq in insp.get_sequence_names(schema=schema):
if name != seq:
continue
has_seq = True
else:
has_seq = True
return has_seq
def fields_update(table, field, typ, schema="bphtb", *args):
context = op.get_context()
helpers = context.opts['helpers']
if not helpers.table_has_column(table, field, schema):
op.add_column(table, sa.Column(field, typ), schema=schema)
def seq_update(table, seq, schema="bphtb", *args):
# seq_name = "pad_spt_type_id_seq"
# table_nm = "pad_spt_type"
if not table_has_seq(table, seq, schema):
statement = f"CREATE SEQUENCE {schema}.{seq} START WITH 1"
op.execute(statement)
statement = f"SELECT setval('{schema}.{seq}', (SELECT MAX(id) FROM {schema}.{table}))"
op.execute(statement)
statement = f"alter table {schema}.{table} alter column id set default nextval('{schema}.{seq}')"
op.execute(statement)
\ No newline at end of file \ No newline at end of file
"""${message}
Revision ID: ${up_revision}
Revises: ${down_revision | comma,n}
Create Date: ${create_date}
"""
# revision identifiers, used by Alembic.
revision = ${repr(up_revision)}
down_revision = ${repr(down_revision)}
branch_labels = ${repr(branch_labels)}
depends_on = ${repr(depends_on)}
from alembic import op
import sqlalchemy as sa
${imports if imports else ""}
def upgrade():
${upgrades if upgrades else "pass"}
def downgrade():
${downgrades if downgrades else "pass"}
"""upgrade pst_permohonan
Revision ID: 17c4fdf1729d
Revises: 8d76ed25a315
Create Date: 2023-02-28 10:22:41.685259
"""
# revision identifiers, used by Alembic.
revision = '17c4fdf1729d'
down_revision = '8d76ed25a315'
branch_labels = None
depends_on = None
from alembic import op
import sqlalchemy as sa
def upgrade():
schema = 'pbb'
context = op.get_context()
helpers = context.opts['helpers']
if not helpers.table_has_column('pst_permohonan', 'email_pemohon', schema):
op.add_column('pst_permohonan',
sa.Column('email_pemohon', sa.String(256)), schema=schema)
if not helpers.table_has_column('pst_permohonan', 'no_hp_pemohon', schema):
op.add_column('pst_permohonan',
sa.Column('no_hp_pemohon', sa.String(16)), schema=schema)
def downgrade():
pass
"""Upgrade SPPT
Revision ID: 2b7248c8df70
Revises: 17c4fdf1729d
Create Date: 2024-12-12 03:22:18.146849
"""
# revision identifiers, used by Alembic.
revision = '2b7248c8df70'
down_revision = '17c4fdf1729d'
branch_labels = None
depends_on = None
import sqlalchemy as sa
from alembic import op
def upgrade():
schema = 'pbb'
context = op.get_context()
helpers = context.opts['helpers']
helpers.fields_update("sppt", "denda_status", sa.String(1), schema)
helpers.fields_update("sppt", "denda_pbb", sa.Numeric(15, 0), schema)
helpers.fields_update("sppt", "njkp_pct", sa.Numeric(4, 3), schema)
helpers.fields_update("sppt", "njkp_sppt", sa.Numeric(15, 0), schema)
helpers.fields_update("sppt", "tarif_pct", sa.Numeric(4, 3), schema)
helpers.fields_update("sppt", "denda_pct", sa.Numeric(4, 3), schema)
def downgrade():
pass
\ No newline at end of file \ No newline at end of file
"""dop add no_sertifikat
Revision ID: 30611cbc119e
Revises:
Create Date: 2023-02-20 21:35:06.877797
"""
# revision identifiers, used by Alembic.
revision = '30611cbc119e'
down_revision = None
branch_labels = None
depends_on = None
from alembic import op
import sqlalchemy as sa
def upgrade():
schema = 'pbb'
context = op.get_context()
helpers = context.opts['helpers']
if not helpers.table_has_column('dat_objek_pajak', 'no_sertifikat', schema):
op.add_column('dat_objek_pajak',
sa.Column('no_sertifikat', sa.String(32)), schema=schema)
if not helpers.table_has_column('dat_objek_pajak', 'create_date', schema):
op.add_column('dat_objek_pajak',
sa.Column('create_date', sa.TIMESTAMP(timezone=False)),
schema=schema)
def downgrade():
pass
"""dat_subjek_pajak
Revision ID: 8d76ed25a315
Revises: 30611cbc119e
Create Date: 2023-02-20 22:40:25.225733
"""
# revision identifiers, used by Alembic.
revision = '8d76ed25a315'
down_revision = '30611cbc119e'
branch_labels = None
depends_on = None
from alembic import op
import sqlalchemy as sa
def upgrade():
schema = 'pbb'
context = op.get_context()
helpers = context.opts['helpers']
if not helpers.table_has_column('dat_subjek_pajak', 'email_wp', schema):
op.add_column('dat_subjek_pajak',
sa.Column('email_wp', sa.String(64)), schema=schema)
if not helpers.table_has_column('dat_subjek_pajak', 'hp_wp', schema):
op.add_column('dat_subjek_pajak',
sa.Column('hp_wp', sa.String(16)), schema=schema)
def downgrade():
pass
pbb_schema='pbb'
\ No newline at end of file \ No newline at end of file
from tangsel.pbb.models.base_table import BaseSppt, BaseNop
from sqlalchemy import (Column, String, DateTime, Float)
from ..models import PbbBase, PBB_ARGS, BasePbb
class DafnomOp(PbbBase, BaseNop):
__tablename__ = 'dafnom_op'
kd_propinsi = Column(String(2), primary_key=True)
kd_dati2 = Column(String(2), primary_key=True)
kd_kecamatan = Column(String(3), primary_key=True)
kd_kelurahan = Column(String(3), primary_key=True)
kd_blok = Column(String(3), primary_key=True)
no_urut = Column(String(4), primary_key=True)
kd_jns_op = Column(String(1), primary_key=True)
thn_pembentukan = Column(String(4), primary_key=True)
jalan_op = Column(String(30))
blok_kav_no_op = Column(String(15))
rw_op = Column(String(2))
rt_op = Column(String(3))
jns_bumi = Column(String(1))
kd_jpb = Column(String(2))
kd_status_wp = Column(String(1))
kategori_op = Column(String(1))
keterangan = Column(String(255))
no_formulir = Column(String(30))
tgl_pembentukan = Column(DateTime)
nip_pembentuk = Column(String(18))
tgl_pemutakhiran = Column(DateTime)
nip_pemutakhir = Column(String(18))
status_verifikasi = Column(String(1))
__table_args__ = (PBB_ARGS,)
class DafnomPiutang(PbbBase, BaseNop):
__tablename__ = 'dafnom_piutang'
kd_propinsi = Column(String(2), primary_key=True)
kd_dati2 = Column(String(2), primary_key=True)
kd_kecamatan = Column(String(3), primary_key=True)
kd_kelurahan = Column(String(3), primary_key=True)
kd_blok = Column(String(3), primary_key=True)
no_urut = Column(String(4), primary_key=True)
kd_jns_op = Column(String(1), primary_key=True)
thn_pajak_sppt = Column(String(4), primary_key=True)
thn_pembentukan = Column(String(4), primary_key=True)
nm_wp_sppt = Column(String(30))
jln_wp_sppt = Column(String(30))
blok_kav_no_wp_sppt = Column(String(15))
rw_wp_sppt = Column(String(2))
rt_wp_sppt = Column(String(3))
kelurahan_wp_sppt = Column(String(30))
kota_wp_sppt = Column(String(30))
luas_bumi_sppt = Column(Float)
luas_bng_sppt = Column(Float)
njop_bumi_sppt = Column(Float)
njop_bng_sppt = Column(Float)
pbb_yg_harus_dibayar_sppt = Column(Float)
tgl_jatuh_tempo_sppt = Column(DateTime)
status_bayar = Column(String(1))
keterangan = Column(String(255))
no_formulir = Column(String(30))
tgl_pembentukan = Column(DateTime)
nip_pembentuk = Column(String(18))
tgl_pemutakhiran = Column(DateTime)
nip_pemutakhir = Column(String(18))
__table_args__ = (PBB_ARGS,)
class DafnomGelondongan(PbbBase, BasePbb):
__tablename__ = 'dafnom_gelondongan'
kd_propinsi = Column(String(2), primary_key=True)
kd_dati2 = Column(String(2), primary_key=True)
kd_kecamatan = Column(String(3), primary_key=True)
kd_kelurahan = Column(String(3), primary_key=True)
thn_pembentukan = Column(String(4), primary_key=True)
jumlah_gelondongan = Column(Float)
jumlah_sismiop = Column(Float)
saldo_gelondongan = Column(Float)
jumlah_lembar = Column(Float)
__table_args__ = (PBB_ARGS,)
class DafnomRinciGelondongan(PbbBase, BasePbb):
__tablename__ = 'dafnom_rinci_gelondongan'
kd_propinsi = Column(String(2), primary_key=True)
kd_dati2 = Column(String(2), primary_key=True)
kd_kecamatan = Column(String(3), primary_key=True)
kd_kelurahan = Column(String(3), primary_key=True)
thn_pembentukan = Column(String(4), primary_key=True)
thn_pajak = Column(String(4), primary_key=True)
nm_dokumen = Column(String(50))
jumlah_gelondongan = Column(Float)
jumlah_sismiop = Column(Float)
saldo_gelondongan = Column(Float)
__table_args__ = (PBB_ARGS,)
# import sys
# # from tangsel.pbb.models import PadTp
# # from tangsel.pbb.models.payment import PadReversal
# import logging
# from datetime import datetime
# from tangsel.base import get_settings
# from tangsel.base.tools.api import (get_mandatory, auth_from_rpc,
# JsonRpcBillNotFoundError,
# JsonRpcPaymentNotFoundError,
# JsonRpcReversedError,
# JsonRpcBillAllreadyPaidError,
# JsonRpcBillDifferentError)
# from tangsel.pbb.models.payment import PbbReversal
# from pyramid_rpc.jsonrpc import jsonrpc_method, JsonRpcError
# from tangsel.pbb.models.h2h.payment import inquiry, payment, advice, reversal, get_tp
# if sys.version[0] != '3':
# raise Exception("Harus Python 3")
# """
# {
# bit_002 : N..19 Primary Account Number O E
# bit_003 : N 6 Processing Code* O E
# bit_004 : N 12 Amount Transaction M M
# bit_007 : N 10 Transmission Date/Time M M
# bit_011 : N 6 System Trace Audit Number O E
# bit_012 : N 6 Time local transaction M E
# bit_013 : N 4 Date local transaction M E
# bit_015 : N 4 Date, Settlement M E
# bit_018 : N 4 Merchant Type* M E
# bit_022 : N 3 POS Entry Mode Code M E
# bit_032 : N..11 Acquiring Institution Code M E
# bit_033 : N..11 Forwarding Institution ID Code M E
# bit_037 : AN..12 Retrival Ref Number M E
# bit_039 : N..2 Response Code O M
# bit_041 : N..8 Terminal identification number M E
# bit_042 : N..15 Terminal name or user identification M E
# bit_043 : A..40 Card Acceptor Name/Location O E
# bit_049 : A or N 3 Currency Code, Transaction O E
# bit_060 : ANS.999 Additional Data/KD PEMDA O E
# bit_061 : ANS.999 Additional Data/NO BAYAR M E
# bit_062 : ANS.999 Additonal Data/Invoice Profile
# code : N..24 Kode/Nomor Bayar M
# name : AN..35 Nama Penyetor WP/OP/WR/OR M
# address : A..40 Alamat1 M
# address2 : A..40 Alamat2 M
# amount : N..12 Bill Amount M
# fine : N..12 Fine Amount M
# total : N..12 Total M
# account_no : AN..20 Kode Rekening M
# description : AN..40 Nama Rekening M
# unit_code : AN..20 Kode SKPD M
# unit_name : AN..40 Nama SKPD M
# additional : AN..40 Additional Data untuk pesan O
# additional2 : AN..40 Additional Data untuk pesan O
# }
# """
# log = logging.getLogger(__name__)
# # def check_tp(data):
# # return PadTp.query_id(data["bit_033"]).first()
# class H2h:
# def __init__(self, request):
# self.req = request
# self.settings = get_settings()
# self.data = None
# def set_response_ok(self, data):
# data["bit_039"] = "00"
# return data
# def set_response(self, data, result):
# return self.set_response_ok(data)
# def inv_id(self):
# return self.data["bit_061"].strip()
# def get_tanggal(self):
# dt = "{}{}{}".format(datetime.now().strftime("%Y"),
# self.data["bit_013"], self.data["bit_012"])
# return datetime.strptime(dt, "%Y%m%d%H%M%S")
# @jsonrpc_method(method='inquiry', endpoint='api-h2h-pemda-pbb')
# def inquiry(self, data):
# self.data = data
# request = self.req
# log.warning("INQ req CA: {}".format(self.data))
# get_mandatory(data, ["bit_061", "bit_018", "bit_033", ])
# tp = get_tp(data, self.settings)
# auth_from_rpc(request)
# result = inquiry(self.inv_id())
# if not result.calc.invoice:
# log.info("Invoice {} tidak ditemukan".format(result.invoice_id_raw))
# raise JsonRpcBillNotFoundError
# if result.calc.is_paid():
# raise JsonRpcBillAllreadyPaidError
# data = self.set_response_ok(data)
# result.set_invoice_profile()
# profile = result.invoice_profile
# profile["additional"] = self.settings["h2h_additional"]
# profile["additional2"] = self.settings["h2h_additional2"]
# profile["biller_nm"] = self.settings["company"]
# data["bit_062"] = profile
# data["bit_004"] = profile["total"]
# log.warning("INQ resp CA: {}".format(data))
# return dict(data=data)
# @jsonrpc_method(method='payment', endpoint='api-h2h-pemda-pbb')
# def payment(self, data):
# self.data = data
# request = self.req
# log.warning("PAY req CA {}".format(data))
# tp = get_tp(data, self.settings)
# get_mandatory(data, ["bit_004", "bit_007", "bit_011", "bit_012",
# "bit_013", "bit_015", "bit_018",
# "bit_032", "bit_033", "bit_037",
# "bit_061", "bit_062"])
# auth_from_rpc(request)
# result = payment(self.inv_id())
# if not result.calc.invoice:
# raise JsonRpcBillNotFoundError
# if result.calc.is_paid():
# raise JsonRpcBillAllreadyPaidError
# if result.cek_iso_payment(data):
# message = "Pernah Terjadi Payment dengan NTB sama"
# log.warning("PAY resp CA {}".format(message))
# raise JsonRpcError(message=message)
# amount = int(data["bit_004"])
# if amount != result.calc.total:
# raise JsonRpcBillDifferentError
# # result.set_invoice_profile()
# pay = result.create_payment(data)
# # data["bit_048"] = result.save_iso_payment(pay)
# ntp = result.save_iso_payment(pay)
# log.warning("NTP {}".format(ntp))
# data["bit_047"] = ntp
# # data["bit_062"] = result.invoice_profile
# log.warning("PAY resp CA {}".format(data))
# # H2hLog.save(data, get_tanggal(data))
# return dict(data=data)
# def check_payment(self, result):
# if not result.calc.invoice:
# raise JsonRpcBillNotFoundError
# pay = result.cek_iso_payment(self.data)
# if not pay:
# raise JsonRpcPaymentNotFoundError
# rev = PbbReversal.query_id(pay.id).first()
# if rev:
# raise JsonRpcReversedError
# return pay
# @jsonrpc_method(method='advice', endpoint='api-h2h-pemda-pbb')
# def advice(self, data):
# self.data = data
# log.warning("ADV req CA {}".format(data))
# auth_from_rpc(self.req)
# tp = get_tp(data, self.settings)
# get_mandatory(data, ["bit_004", "bit_007", "bit_012",
# "bit_013", "bit_015", "bit_018",
# "bit_032", "bit_033", "bit_037",
# "bit_061", "bit_062"])
# result = advice(self.inv_id())
# # if not result.calc.invoice:
# # raise JsonRpcBillNotFoundError
# #
# pay = self.check_payment(result)
# data = self.set_response(data, result)
# # result.set_invoice_profile()
# # data["bit_062"]=result.invoice_profile
# # data["bit_048"] = pay.ntp
# # profile = data["bit_062"]
# # data["bit_004"] = profile["amount"] + profile["fine"] - profile["discount"]
# # data["bit_062"]["total"] = data["bit_004"]
# log.warning("ADV resp CA {}".format(data))
# return dict(code=0, message="Sukses Advice", data=data)
# @jsonrpc_method(method='reversal', endpoint='api-h2h-pemda-pbb')
# def reversal(self, data):
# self.data = data
# log.warning("REV req CA {}".format(data))
# auth_from_rpc(self.req)
# get_mandatory(data, ["bit_004", "bit_007", "bit_012",
# "bit_013", "bit_015", "bit_018",
# "bit_032", "bit_033", "bit_037",
# "bit_061", "bit_062"])
# result = reversal(self.inv_id())
# if not result.calc.invoice:
# raise JsonRpcBillNotFoundError
# pay = self.check_payment(result)
# result.reversal(pay)
# # data["bit_048"] = pay.ntp
# data["bit_047"] = pay.ntp
# data = self.set_response(data, result)
# # data = self.set_response_ok(data)
# return dict(data=data)
from sqlalchemy.orm import sessionmaker
from .db_tools import sppt2nop
from .query import (
CalculateInvoice,
)
class AvailableInvoice:
def __init__(self, models, query, **kwargs):
self.models = models
self.query = query
self.persen_denda = 'persen_denda' in kwargs and \
kwargs['persen_denda'] or 0
def add_option(self, pars):
pars.add_option('', '--min', type='int', help='Tagihan minimum')
pars.add_option('', '--max', type='int', help='Tagihan maksimum')
pars.add_option('-t', '--tahun', help='Tahun pajak')
def show(self, option):
engine = self.models.Base.metadata.bind
session_factory = sessionmaker(bind=engine)
DBSession = session_factory()
Invoice = self.models.Invoice
q = DBSession.query(Invoice).filter_by(status_pembayaran_sppt='0')
if option.min:
q = q.filter(Invoice.pbb_yg_harus_dibayar_sppt >= option.min)
if option.max:
q = q.filter(Invoice.pbb_yg_harus_dibayar_sppt <= option.max)
if option.tahun:
q = q.filter(Invoice.thn_pajak_sppt == option.tahun)
offset = -1
count = 0
while True:
if count >= option.sample_count:
break
offset += 1
row = q.offset(offset).first()
if not row:
break
calc = CalculateInvoice(
self.models, DBSession, self.persen_denda, row.kd_propinsi,
row.kd_dati2, row.kd_kecamatan, row.kd_kelurahan,
row.kd_blok, row.no_urut, row.kd_jns_op,
row.thn_pajak_sppt)
if calc.total < 1:
continue
count += 1
invoice_id_raw = sppt2nop(calc.invoice) + \
calc.invoice.thn_pajak_sppt
msg = '#{no}/{count} {id} Rp {total}'.format(
no=count, id=invoice_id_raw, total=calc.total,
count=option.sample_count)
print(msg)
from tangsel.base.models import CommonModel
\ No newline at end of file \ No newline at end of file
from datetime import date
def bulan_tunggakan(jatuh_tempo, tgl_hitung):
x = (tgl_hitung.year - jatuh_tempo.year) * 12
y = tgl_hitung.month - jatuh_tempo.month
n = x + y + 1
if tgl_hitung.day <= jatuh_tempo.day:
n -= 1
if n < 1:
n = 0
if n > 24:
n = 24
return n
def hitung_denda(tagihan, jatuh_tempo, persen_denda, tgl_hitung=None):
if jatuh_tempo is None:
return 0, 0
if tgl_hitung is None:
tgl_hitung = date.today()
if type(jatuh_tempo) is not date:
jatuh_tempo = jatuh_tempo.date()
if jatuh_tempo >= tgl_hitung or persen_denda <= 0:
return 0, 0
bulan = bulan_tunggakan(jatuh_tempo, tgl_hitung)
denda = bulan * float(persen_denda) / 100 * tagihan
return bulan, denda
def sppt2nop(sppt):
return ''.join([sppt.kd_propinsi, sppt.kd_dati2, sppt.kd_kecamatan,
sppt.kd_kelurahan, sppt.kd_blok, sppt.no_urut,
sppt.kd_jns_op])
from sqlalchemy.orm import sessionmaker
from .base_models import CommonModel
from tangsel.pbb.models import (Sppt as Invoice, PembayaranSppt as Pembayaran,
Kelurahan, Kecamatan, Dati2 as Kabupaten,
TempatPembayaran, Propinsi,
DatObjekPajak as ObjekPajak)
session_factory = sessionmaker()
class Models:
def __init__(
self, tabel_dat_objek_pajak=True):
# self.Base = Base
# if payment_db_schema is None:
# payment_db_schema = db_schema
# class Invoice(Base, CommonModel):
# __tablename__ = 'sppt'
# __table_args__ = dict(schema=db_schema, autoload=True)
self.Invoice = Invoice
# class Pembayaran(Base, CommonModel):
# __tablename__ = 'pembayaran_sppt'
# __table_args__ = dict(schema=payment_db_schema, autoload=True)
self.Pembayaran = Pembayaran
# class Kelurahan(Base, CommonModel):
# __tablename__ = 'ref_kelurahan'
# __table_args__ = dict(schema=db_schema, autoload=True)
self.Kelurahan = Kelurahan
# class Kecamatan(Base, CommonModel):
# __tablename__ = 'ref_kecamatan'
# __table_args__ = dict(schema=db_schema, autoload=True)
self.Kecamatan = Kecamatan
# class Kabupaten(Base, CommonModel):
# __tablename__ = 'ref_dati2'
# __table_args__ = dict(schema=db_schema, autoload=True)
self.Kabupaten = Kabupaten
# class Propinsi(Base, CommonModel):
# __tablename__ = 'ref_propinsi'
# __table_args__ = dict(schema=db_schema, autoload=True)
self.Propinsi = Propinsi
# class TempatPembayaran(Base, CommonModel):
# __tablename__ = 'tempat_pembayaran'
# __table_args__ = dict(schema=db_schema, autoload=True)
self.TempatPembayaran = TempatPembayaran
if tabel_dat_objek_pajak:
# class ObjekPajak(Base, CommonModel):
# __tablename__ = 'dat_objek_pajak'
# __table_args__ = dict(schema=db_schema, autoload=True)
self.ObjekPajak = ObjekPajak
from datetime import date
from .query import CalculateInvoice as BaseCalculateInvoice
# Request Pak Yasir @20220204
# 1. Pembebasan denda (diskon denda 100%)
# 2. Untuk SPPT 2016 sd 2021
# 3. Periode tidak disebutkan (mungkin sampe akhir desember 2022)
# konstan kompensasi denda/discount
THN_PAJAK = ('2016', '2017', '2018', '2019', '2020', '2021')
BERLAKU_MAX = date(2022, 12, 31)
class CalculateInvoice(BaseCalculateInvoice):
def hitung_discount(self):
if self.denda > 0 \
and self.tgl_bayar.date() <= BERLAKU_MAX \
and self.tahun in THN_PAJAK:
self.discount = self.discount_denda = self.denda
def before_save(self, bayar):
bayar.denda_sppt = self.denda - self.discount_denda
from datetime import date
from .query import CalculateInvoice as BaseCalculateInvoice
# SK NOMOR 973/Kep.949-BAPENDA/2021
# 1. penghapusan denda
# 2. tahun pajak 2021
# 3. berlaku 1 nop - 31 des 2021
# konstan kompensasi denda/discount
THN_PAJAK = ('2021')
BERLAKU_MAX = date(2021, 12, 31)
class CalculateInvoice(BaseCalculateInvoice):
def hitung_discount(self):
if self.denda > 0 \
and self.tgl_bayar.date() <= BERLAKU_MAX \
and self.tahun in THN_PAJAK:
self.discount = self.discount_denda = self.denda
def before_save(self, bayar):
bayar.denda_sppt = self.denda - self.discount_denda
from datetime import date
from .query import CalculateInvoice as BaseCalculateInvoice
# DISKON POKOK JAN-JUN 2021
DISC_TAHUN_PAJAK = '2021'
DISC_POKOK_JAN_JUN = {
2021: {
1: 0.15,
2: 0.15,
3: 0.15,
4: 0.1,
5: 0.05,
6: 0.05,
},
}
# DISKON JUL-DES 2021 @20210625
# 1. TAHUN PAJAK < 2014 DISKON POKOK 75%
# 2. TAHUN PAJAK 2014-2020 DISKON POKOK 40%
# 3. TAHUN PAJAK < 2021 DISKON DENDA 100%
# 4. BERLAKU MULAI 1 JULI 2021 sd 31 DES 2021
BERLAKU_MIN = date(2021, 7, 1)
BERLAKU_MAX = date(2021, 12, 31)
THN_PAJAK_MIN = 2014
THN_PAJAK_MAX = 2021
DISC_DENDA_JUL_DES = 1.0
DISC_POKOK_JUL_DES = {
2014: 0.75,
2021: 0.4,
}
def not_null(invoice):
if invoice.pbb_terhutang_sppt is None:
invoice.pbb_terhutang_sppt = 0
if invoice.faktor_pengurang_sppt is None:
invoice.faktor_pengurang_sppt = 0
class CalculateInvoice(BaseCalculateInvoice):
def hitung_discount(self): # Override
self.discount_denda = self.hitung_discount_denda()
self.discount_pokok = self.hitung_discount_pokok()
self.discount = self.discount_denda + self.discount_pokok
def hitung_discount_denda(self):
if self.denda > 0 and int(self.tahun) < THN_PAJAK_MAX \
and BERLAKU_MIN <= self.tgl_bayar.date() <= BERLAKU_MAX:
self.denda_sblm_diskon = self.denda
return int(self.denda * DISC_DENDA_JUL_DES)
return 0
def hitung_discount_pokok(self):
faktor_pengurang = self.invoice.faktor_pengurang_sppt or 0
if faktor_pengurang > 0:
return 0
return self.hitung_discount_pokok2()
def hitung_discount_pokok2(self):
if BERLAKU_MIN <= self.tgl_bayar.date() <= BERLAKU_MAX:
if int(self.tahun) < THN_PAJAK_MIN:
disc = DISC_POKOK_JUL_DES.get(THN_PAJAK_MIN)
return int(self.tagihan * disc)
elif THN_PAJAK_MIN <= int(self.tahun) < THN_PAJAK_MAX:
disc = DISC_POKOK_JUL_DES.get(THN_PAJAK_MAX)
return int(self.tagihan * disc)
if self.invoice.thn_pajak_sppt == DISC_TAHUN_PAJAK:
bulan_disc = DISC_POKOK_JAN_JUN.get(self.tgl_bayar.year)
if bulan_disc:
disc = bulan_disc.get(self.tgl_bayar.month)
if disc:
return int(self.tagihan * disc)
return 0
def set_faktor_pengurang_sppt(self, payment):
if not payment.discount_pokok:
return
not_null(self.invoice)
self.invoice.faktor_pengurang_sppt += payment.discount_pokok
self.invoice.pbb_yg_harus_dibayar_sppt = \
self.invoice.pbb_terhutang_sppt - \
self.invoice.faktor_pengurang_sppt
def before_save(self, bayar): # Override
bayar.denda_sblm_diskon = self.denda_sblm_diskon
bayar.discount = self.discount_pokok + self.discount_denda
bayar.discount_pokok = self.discount_pokok
bayar.discount_denda = self.discount_denda
tagihan_netto = self.tagihan - self.discount_pokok
denda_netto = self.denda - self.discount_denda
bayar.jml_sppt_yg_dibayar = tagihan_netto + denda_netto
bayar.denda_sppt = denda_netto
self.set_faktor_pengurang_sppt(bayar)
def belum_lunas_di_periode_discount(self):
Sppt = self.models.Invoice
q = self.DBSession.query(Sppt)
q = self.get_filter_op(q)
q = q.filter(
Sppt.thn_pajak_sppt.in_(THN_DISC),
Sppt.status_pembayaran_sppt != '1')
return q.first()
def get_filter_op(self, q):
return q.filter_by(
kd_propinsi=self.propinsi,
kd_dati2=self.kabupaten,
kd_kecamatan=self.kecamatan,
kd_kelurahan=self.kelurahan,
kd_blok=self.blok,
no_urut=self.urut,
kd_jns_op=self.jenis)
def round_up(n):
i = int(n)
if n == i:
return i
if n > 0:
return i + 1
return i - 1
import sys
from datetime import datetime
from sqlalchemy import (
Column,
Integer,
BigInteger,
Float,
Text,
DateTime,
ForeignKey,
UniqueConstraint,
String,
SmallInteger,
types,
func,
ForeignKeyConstraint,
literal_column,
and_
)
from sqlalchemy.orm import aliased
from sqlalchemy.orm.exc import NoResultFound
from sqlalchemy.orm import (
relationship,
backref,
)
import re
from .tools import as_timezone
# from ..models import NamaModel, DefaultModel, DBSession, Base
ARGS = {'extend_existing': True, 'schema': 'public'}
# class PbbPelayanan(Base, NamaModel):
# __tablename__ = 'pbb_pelayanan'
# kode = Column(String(2))
# nama = Column(String(50))
# __table_args__ = (ARGS)
# @classmethod
# def query_kode(kode):
# return cls.query().filter_by(kode=kode)
# class PbbSyarat(Base, NamaModel):
# __tablename__ = 'pbb_syarat'
# kode = Column(String(2))
# nama = Column(String(50))
# __table_args__ = (ARGS)
# @classmethod
# def query_kode(kode):
# return cls.query().filter_by(kode=kode)
# class PbbSyaratPelayanan(Base, DefaultModel):
# __tablename__ = 'pbb_syarat_pelayanan'
# pelayanan_id = Column(Integer, ForeignKey(PbbPelayanan.id))
# syarat_id = Column(Integer, ForeignKey(PbbSyarat.id))
# __table_args__ = (ARGS)
\ No newline at end of file \ No newline at end of file
from tangsel.base import Base
from tangsel.base.models import DefaultModel
from tangsel.pbb.models import PbbBase, PbbModel
from sqlalchemy import (
Column, Integer, DateTime, String, Float, Date,
UniqueConstraint, ForeignKey)
# class Inquiry(PbbBase):
# __tablename__ = 'inquiry'
# id = Column(Integer, primary_key=True)
# tgl = Column(DateTime, nullable=False)
# nop = Column(String(32), nullable=False)
# propinsi = Column(String(2), nullable=False)
# kabupaten = Column(String(2), nullable=False)
# kecamatan = Column(String(3), nullable=False)
# kelurahan = Column(String(3), nullable=False)
# blok = Column(String(3), nullable=False)
# urut = Column(String(4), nullable=False)
# jenis = Column(String(1), nullable=False)
# tahun = Column(Integer, nullable=False)
# tagihan = Column(Float, nullable=False)
# jatuh_tempo = Column(Date, nullable=False)
# bulan_tunggakan = Column(Integer, nullable=False)
# persen_denda = Column(Float, nullable=False)
# denda = Column(Float, nullable=False)
# transmission = Column(DateTime)
# stan = Column(Integer)
# settlement = Column(DateTime)
# pengirim = Column(String(16), nullable=False)
# __table_args__ = (dict(schema='pbb'),)
class PbbPayment(Base, DefaultModel):
__tablename__ = 'pbb_payment'
id = Column(Integer, primary_key=True)
# inquiry_id = Column(Integer, ForeignKey('pbb.inquiry.id'), nullable=False)
propinsi = Column(String(2), nullable=False)
kabupaten = Column(String(2), nullable=False)
kecamatan = Column(String(3), nullable=False)
kelurahan = Column(String(3), nullable=False)
blok = Column(String(3), nullable=False)
urut = Column(String(4), nullable=False)
jenis = Column(String(1), nullable=False)
tahun = Column(Integer, nullable=False)
ke = Column(Integer, nullable=False)
kd_kanwil_bank = Column(String(2), nullable=False)
kd_kppbb_bank = Column(String(2), nullable=False)
kd_bank_tunggal = Column(String(2), nullable=False)
kd_bank_persepsi = Column(String(2), nullable=False)
kd_tp = Column(String(2), nullable=False)
channel = Column(String(4))
ntb = Column(String(64))
ntp = Column(String(64))
bank = Column(Integer)
iso_request = Column(String(2048), nullable=False)
__table_args__ = (
UniqueConstraint('propinsi', 'kabupaten', 'kecamatan', 'kelurahan',
'blok', 'urut', 'jenis', 'tahun', 'ke'),
dict(schema='public'))
class PbbReversal(Base, DefaultModel):
__tablename__ = 'pbb_reversal'
id = Column(Integer, ForeignKey(PbbPayment.id), primary_key=True)
tgl = Column(DateTime, nullable=False)
iso_request = Column(String(2048), nullable=False)
__table_args__ = (
dict(schema='public'),)
from datetime import datetime
from sqlalchemy import (
Column, DateTime, String, func, ForeignKeyConstraint
)
from sqlalchemy.ext.hybrid import hybrid_property
from ..models import PbbBase, PbbDBSession, PBB_ARGS, Kantor, BasePbb
from .tools import number_only, FixKantor, column_concat
class Wewenang(PbbBase, BasePbb):
__tablename__ = 'wewenang'
kd_wewenang = Column(String(2), primary_key=True)
nm_wewenang = Column(String(30))
__table_args__ = (PBB_ARGS,)
@hybrid_property
def kode(self):
return self.kd_wewenang
@hybrid_property
def nama(self):
return self.nm_wewenang
@classmethod
def query_id(cls, sid):
return cls.query(). \
filter(cls.kd_wewenang == sid, )
@classmethod
def get_list(cls):
query = PbbDBSession.query(cls.kd_wewenang, cls.nm_wewenang)
return [(row.kd_wewenang, row.nm_wewenang) for row in query.all()]
class Pegawai(PbbBase, BasePbb):
__tablename__ = 'pegawai'
nip = Column(String(18), primary_key=True)
nm_pegawai = Column(String(30))
__table_args__ = (PBB_ARGS,)
@hybrid_property
def kode(self):
return self.nip
@hybrid_property
def nama(self):
return self.nm_pegawai
@classmethod
def query_id(cls, sid):
return cls.query(). \
filter(cls.nip == sid, )
# @classmethod
# def get_list(cls):
# return PbbDBSession.query(cls.nip, cls.nm_pegawai)
@classmethod
def get_list(cls):
query = PbbDBSession.query(cls.nip, cls.nm_pegawai)
return [(row.nip, row.nm_pegawai) for row in query]
class DatLogin(PbbBase, BasePbb):
__tablename__ = 'dat_login'
nm_login = Column(String(18), primary_key=True)
nip = Column(String(18))
password = Column(String(50))
__table_args__ = (PBB_ARGS,)
@classmethod
def query_id(cls, sid):
return cls.query(). \
filter(cls.nm_login == sid, )
class PosisiPegawai(PbbBase, BasePbb):
__tablename__ = 'posisi_pegawai'
kd_kanwil = Column(String(2), primary_key=True)
kd_kantor = Column(String(2), primary_key=True)
nip = Column(String(18), primary_key=True)
kd_seksi = Column(String(2))
tgl_awal_berlaku = Column(DateTime(timezone=False))
tgl_akhir_berlaku = Column(DateTime(timezone=False))
kd_wewenang = Column(String(2))
kd_jabatan = Column(String(2))
__table_args__ = (
ForeignKeyConstraint((nip,), [Pegawai.nip]),
ForeignKeyConstraint((kd_kanwil, kd_kantor),
[Kantor.kd_kanwil, Kantor.kd_kantor]),
ForeignKeyConstraint((kd_wewenang,), [Wewenang.kd_wewenang]),
PBB_ARGS,)
@hybrid_property
def kode_kantor(self):
return "{}.{}".format(self.kd_kanwil, self.kd_kantor)
@classmethod
def query(cls):
return PbbDBSession.query(cls)
@classmethod
def query_id(cls, sid):
kode = number_only(sid)
kantor = FixKantor(kode)
jabatan = kode[4:6]
nip = kode[6:]
return cls.query(). \
filter(cls.kd_kanwil == kantor["kd_kanwil"],
cls.kd_kantor == kantor["kd_kantor"],
cls.nip == nip,
cls.kd_jabatan == jabatan)
@classmethod
def query_nip(cls, sid):
return cls.query(). \
filter(cls.nip == sid, )
@classmethod
def get_posisi(cls, nip):
sekarang = datetime.now().strftime("%Y-%m-%d")
row = cls.query(). \
filter(cls.nip == nip). \
filter(cls.tgl_awal_berlaku <= func.to_date(sekarang, 'YYYY-MM-DD'),
cls.tgl_akhir_berlaku >= func.to_date(sekarang,
'YYYY-MM-DD')). \
first()
if not row:
return
return row.to_dict()
@classmethod
def get_ttd_restitusi_kompensasi(cls, kantor):
sekarang = datetime.now().strftime("%Y-%m-%d")
return Pegawai.query(). \
filter(cls.nip == Pegawai.nip). \
filter(cls.kd_kanwil == kantor['kd_kanwil']). \
filter(cls.kd_kantor == kantor['kd_kantor']). \
filter(cls.kd_jabatan == '10', cls.kd_wewenang == '10'). \
filter(cls.tgl_awal_berlaku <= func.to_date(sekarang, 'YYYY-MM-DD'),
cls.tgl_akhir_berlaku >= func.to_date(sekarang,
'YYYY-MM-DD')). \
first()
from sqlalchemy import (
Column,
Integer,
BigInteger,
String
)
from ..models import (
CommonModel,
PbbDBSession,
PbbBase,
PBB_ARGS
)
class PenguranganCovid(PbbBase, CommonModel):
"""
Table pengurangan_covid yang digunakan di kota bogor.
"""
__tablename__ = 'pengurangan_covid'
__table_args__ = PBB_ARGS
kd_propinsi = Column(String(2), primary_key=True)
kd_dati2 = Column(String(2), primary_key=True)
kd_kecamatan = Column(String(3), primary_key=True)
kd_kelurahan = Column(String(3), primary_key=True)
kd_blok = Column(String(3), primary_key=True)
no_urut = Column(String(4), primary_key=True)
kd_jns_op = Column(String(1), primary_key=True)
thn_pajak_sppt = Column(String(4), primary_key=True)
pembayaran_sppt_ke = Column(Integer, primary_key=True)
denda = Column(BigInteger)
bayar = Column(BigInteger)
@classmethod
def query(cls):
return PbbDBSession.query(cls)
from sqlalchemy import (Column, SmallInteger, Integer, DateTime, String, func, Float, and_)
from sqlalchemy.ext.hybrid import hybrid_property
from .tools import FixNop, FixSppt, FixBlok, FixKelurahan
from . import (
PbbBase, PbbDBSession, PBB_ARGS,
CommonModel, BaseNop, BaseBlok, BaseKelurahan,
Kelurahan, Kecamatan, Dati2
)
class Kalibrasi(PbbBase, BaseKelurahan):
__tablename__ = 'kalibrasi'
thn_kalibrasi = Column(String(4), primary_key=True)
indeks_kalibrasi = Column(SmallInteger, primary_key=True)
tgl_kalibrasi = Column(DateTime)
nip_pengkalibrasi = Column(String(18))
@hybrid_property
def id(self):
return "{}-{}.{}".format(super().id, self.thn_kalibrasi, self.indeks_kalibrasi)
@classmethod
def query_tahun(cls, kode_kel, tahun, db_session=PbbDBSession):
return cls.query_kel(kode_kel, db_session).filter(cls.thn_kalibrasi == tahun)
@classmethod
def query_id(cls, kode_kel, tahun, index, db_session=PbbDBSession):
return cls.query_tahun(kode_kel, tahun, db_session).filter(cls.indeks_kalibrasi == index)
import logging
from tangsel.tools.this_framework import get_settings
from sqlalchemy import engine_from_config, Column, String, ForeignKey, DateTime
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import (scoped_session, sessionmaker, relationship, backref)
from zope.sqlalchemy import register
from ..base_table import (
BaseJenisPelayanan, BaseBerkasTerima, BaseBerkasKirim,
BasePstPermohonan, BasePstDetail, BaseSeksi, BaseDatObjekPajak, BaseSppt)
_logging = logging.getLogger(__name__)
session_factory = sessionmaker()
ReadPbbDBSession = scoped_session(session_factory)
register(ReadPbbDBSession)
ReadPbbBase = declarative_base()
pbb_schema = 'pbb'
PBB_ARGS = {'extend_existing': True, 'schema': pbb_schema}
class ReadSeksi(ReadPbbBase, BaseSeksi):
__tablename__ = "ref_seksi"
__table_args__ = (PBB_ARGS,)
class ReadJenisPelayanan(ReadPbbBase, BaseJenisPelayanan):
__tablename__ = "ref_jns_pelayanan"
__table_args__ = (PBB_ARGS,)
class ReadDatObjekPajak(ReadPbbBase, BaseDatObjekPajak):
__tablename__ = "dat_objek_pajak"
__table_args__ = (PBB_ARGS,)
class ReadPstPermohonan(ReadPbbBase, BasePstPermohonan):
__tablename__ = "pst_permohonan"
__table_args__ = (PBB_ARGS,)
class ReadPstDetail(ReadPbbBase, BasePstDetail):
__tablename__ = "pst_detail"
__table_args__ = (PBB_ARGS,)
kd_seksi_berkas = Column(String(2), ForeignKey(ReadSeksi.kd_seksi))
tgl_penyerahan = Column(DateTime)
nip_penyerah = Column(String(18))
seksi_berkas = relationship(ReadSeksi, backref=backref("pst_detail"))
class ReadBerkasTerima(ReadPbbBase, BaseBerkasTerima):
__tablename__ = "berkas_terima"
__table_args__ = (PBB_ARGS,)
class ReadBerkasKirim(ReadPbbBase, BaseBerkasKirim):
__tablename__ = "berkas_kirim"
__table_args__ = (PBB_ARGS,)
class ReadSppt(ReadPbbBase, BaseSppt):
__tablename__ = "sppt"
__table_args__ = (PBB_ARGS,)
def get_connection(settings=None):
if not settings:
settings = get_settings()
url = 'pbb_read.url' in settings and settings[
'pbb_read.url'] and 'pbb_read.' or ''
if not url:
raise Exception('"pbb_read.url" belum ada pada settings')
engine = engine_from_config(settings, url)
ReadPbbDBSession.configure(bind=engine)
ReadPbbBase.metadata.bind = engine
# settings['pbb_connected'] = True
def includeme(config):
_logging.info(config)
get_connection()
_logging.info("PBB Mirror Loaded")
SQLAlchemy>=1.4.23
pyramid>=2.0
alembic>=1.6.5
transaction>=3.0.1
colander>=1.8.3
deform>=2.0.15
setuptools>=56.0.0
python-dateutil~=2.8.2
requests~=2.28.0
icecream~=2.1.2
google~=3.0.0
pytz~=2022.1
translationstring~=1.4
iso8601~=1.0.2
Chameleon~=3.10.1
pip~=18.1
wheel~=0.37.1
py~=1.11.0
Genshi~=0.7.7
lxml~=4.9.0
reportlab~=3.6.10
Pillow~=9.1.1
colorama~=0.4.4
pytest~=7.1.2
beautifulsoup4~=4.11.1
soupsieve~=2.3.2.post1
html5lib~=1.1
attrs~=21.4.0
rsa~=4.8
pyasn1~=0.4.8
six~=1.16.0
Pygments~=2.12.0
numpy~=1.21.6
Mako~=1.2.0
Babel~=2.10.2
Beaker~=1.11.0
lingua~=4.15.0
MarkupSafe~=2.1.1
tomli~=2.0.1
GeoAlchemy2~=0.12.1
WebOb~=1.8.7
peppercorn~=0.6
cachetools~=5.2.0
certifi~=2022.5.18.1
urllib3~=1.26.9
google-api-python-client~=2.51.0
pluggy~=1.0.0
iniconfig~=1.1.1
geojson~=2.5.0
Shapely~=1.8.2
papyrus~=2.4
passlib~=1.7.4
packaging~=21.3
venusian~=3.0.0
plaster~=1.0
hupper~=1.10.3
greenlet~=1.1.2
pyparsing~=3.0.9
httplib2~=0.20.4
executing~=0.8.3
paginate~=0.5.6
idna~=3.3
waitress~=2.1.2
asttokens~=2.0.5
uritemplate~=4.1.1
munch~=2.5.0
\ No newline at end of file \ No newline at end of file
from tangsel.tools import number_only
from tangsel.tools.pbb import FixDati2
from sqlalchemy import (Column, String, Float, func)
from sqlalchemy.ext.hybrid import hybrid_property
from . import PbbBase, BasePbb, PbbDBSession, PBB_ARGS
from .tools import column_concat
class Pekerjaan(PbbBase, BasePbb):
__tablename__ = 'pekerjaan'
kd_pekerjaan = Column(String(2), primary_key=True)
nm_pekerjaan = Column(String(30))
status_pekerjaan = Column(String(1))
__table_args__ = (PBB_ARGS,)
@hybrid_property
def kode(self):
return self.kd_pekerjaan
@hybrid_property
def id(self):
return self.kode()
@hybrid_property
def nama(self):
return self.nm_pekerjaan
@classmethod
def query_kode(cls, kode):
kode = number_only(kode)
return cls.query().filter_by(kd_pekerjaan=kode)
@classmethod
def query_id(cls, id):
return cls.query_kode(id)
@classmethod
def get_list(cls):
query = PbbDBSession.query(cls.kd_pekerjaan,
cls.nm_pekerjaan)
return [(row.kd_pekerjaan, row.nm_pekerjaan) for row in query.all()]
class Kegiatan(PbbBase, BasePbb):
__tablename__ = 'pekerjaan_kegiatan'
kd_pekerjaan = Column(String(2), primary_key=True)
kd_kegiatan = Column(String(2), primary_key=True)
nm_kegiatan = Column(String(30))
__table_args__ = (PBB_ARGS,)
@hybrid_property
def kode(self):
return "{}.{}".format(self.kd_pekerjaan, self.kd_kegiatan)
@hybrid_property
def id(self):
return self.kode().replace(".", "")
@hybrid_property
def nama(self):
return self.nm_kegiatan
@classmethod
def get_list(cls):
query = PbbDBSession.query(
column_concat([cls.kd_pekerjaan, cls.kd_kegiatan]).label("kode"),
cls.nm_kegiatan
).order_by(cls.nm_kegiatan)
return [(row.kode, row.nm_kegiatan) for row in query.all()]
@classmethod
def query_kode(cls, kode):
kode = number_only(kode)
keys = dict(kd_pekerjaan=kode[:2],
kd_kegiatan=kode[2:4])
return cls.query().filter_by(kd_pekerjaan=keys['kd_pekerjaan'],
kd_kegiatan=keys['kd_kegiatan'])
@classmethod
def query_id(cls, id):
return cls.query_kode(id)
#
# @classmethod
# def get_list(cls):
# query = PbbDBSession.query(cls.kd_pekerjaan,
# cls.nm_pekerjaan)
# return [(row.kd_pekerjaan, row.nm_pekerjaan) for row in query.all()]
#
class GroupResource(PbbBase, BasePbb):
__tablename__ = 'group_resource'
kd_group_resource = Column(String(2), primary_key=True)
nm_group_resource = Column(String(45))
__table_args__ = (PBB_ARGS,)
@hybrid_property
def kode(self):
return self.kd_group_resource
@hybrid_property
def id(self):
return self.kode()
@hybrid_property
def nama(self):
return self.nm_group_resource
@classmethod
def query_kode(cls, kode):
kode = number_only(kode)
keys = dict(kd_group_resource=kode)
return cls.query().filter_by(
kd_group_resource=keys['kd_group_resource'])
@classmethod
def query_id(cls, id):
return cls.query_kode(id)
@classmethod
def get_list(cls):
query = PbbDBSession.query(
cls.kd_group_resource,
cls.nm_group_resource
).order_by(cls.nm_group_resource)
return [(row.kd_group_resource, row.nm_group_resource) for row in
query.all()]
class ItemResource(PbbBase, BasePbb):
__tablename__ = 'item_resource'
kd_group_resource = Column(String(2), primary_key=True)
kd_resource = Column(String(2), primary_key=True)
nm_resource = Column(String(45))
satuan_resource = Column(String(15))
__table_args__ = (PBB_ARGS,)
@hybrid_property
def kode(self):
return "{}.{}".format(self.kd_group_resource, self.kd_resource)
@hybrid_property
def id(self):
return self.kode().replace(".", "")
@hybrid_property
def nama(self):
return self.nm_resource
@classmethod
def get_list(cls, kd_group_resource=None):
query = PbbDBSession.query(
column_concat([cls.kd_group_resource, cls.kd_resource]).label(
"kode"),
cls.nm_resource
).order_by(cls.nm_resource)
if kd_group_resource:
query=query.filter_by(kd_group_resource=kd_group_resource)
return [(row.kode, row.nm_resource) for row in query.all()]
@classmethod
def query_kode(cls, kode):
kode = number_only(kode)
keys = dict(kd_group_resource=kode[:2],
kd_resource=kode[2:4])
return cls.query().filter_by(
kd_group_resource=keys['kd_group_resource'],
kd_resource=keys['kd_resource'])
@classmethod
def query_id(cls, id):
return cls.query_kode(id)
class VolResource(PbbBase, BasePbb):
__tablename__ = 'vol_resource'
kd_pekerjaan = Column(String(2), primary_key=True)
kd_kegiatan = Column(String(2), primary_key=True)
kd_group_resource = Column(String(2), primary_key=True)
kd_resource = Column(String(2), primary_key=True)
vol_resource = Column(Float)
__table_args__ = (PBB_ARGS,)
@hybrid_property
def kode(self):
return "{}.{}.{}.{}".format(self.kd_pekerjaan, self.kd_kegiatan,
self.kd_group_resource, self.kd_resource)
@hybrid_property
def id(self):
return self.kode().replace(".", "")
@hybrid_property
def nama(self):
return self.vol_resource
@classmethod
def query_kode(cls, kode):
kode = number_only(kode)
keys = dict(kd_pekerjaan=kode[:2],
kd_kegiatan=kode[2:4],
kd_group_resource=kode[4:6],
kd_resource=kode[6:8])
return cls.query().filter_by(kd_pekerjaan=keys['kd_pekerjaan'],
kd_kegiatan=keys['kd_kegiatan'],
kd_group_resource=keys[
'kd_group_resource'],
kd_resource=keys['kd_resource'])
@classmethod
def query_id(cls, id):
return cls.query_kode(id)
class HrgResource(PbbBase, BasePbb):
__tablename__ = 'hrg_resource'
kd_propinsi = Column(String(2), primary_key=True)
kd_dati2 = Column(String(2), primary_key=True)
thn_hrg_resource = Column(String(4), primary_key=True)
kd_group_resource = Column(String(2), primary_key=True)
kd_resource = Column(String(2), primary_key=True)
kd_kanwil = Column(String(2))
kd_kantor = Column(String(2))
jns_dokumen = Column(String(1))
no_dokumen = Column(String(11))
hrg_resource = Column(Float)
__table_args__ = (PBB_ARGS,)
@hybrid_property
def kode(self):
return "{}.{}.{}.{}".format(self.kd_propinsi, self.kd_dati2,
self.thn_hrg_resource,
self.kd_group_resource,
self.kd_resource)
@hybrid_property
def id(self):
return self.kode.replace(".", "")
@hybrid_property
def nama(self):
return self.no_dokumen
@classmethod
def count(cls):
return PbbDBSession.query(func.count(cls.kd_propinsi).label('cnt'))
@classmethod
def query_kode(cls, kode):
kode = number_only(kode)
keys = FixDati2(kode).to_dict()
keys.update(dict(thn_hrg_resource=kode[4:8],
kd_group_resource=kode[8:10],
kd_resource=kode[10:12]))
return cls.query().filter_by(kd_propinsi=keys['kd_propinsi'],
kd_dati2=keys['kd_dati2'],
thn_hrg_resource=keys['thn_hrg_resource'],
kd_group_resource=keys[
'kd_group_resource'],
kd_resource=keys['kd_resource'])
@classmethod
def query_id(cls, id):
return cls.query_kode(id)
@classmethod
def save(cls, values, row=None):
if not row:
row = cls()
row.from_dict(values)
PbbDBSession.add(row)
PbbDBSession.flush()
@classmethod
def pembentukan_dbkb(cls, idk):
kd_pro = idk[:2]
kd_dat = idk[2:4]
thn = idk[4:8]
cls.callproc("PEMBETUKAN_DBKB", [thn, kd_pro, kd_dat])
routes = [
# "kode", "path" ,"nama" ,"status", "type",app_id
("api-h2h-pemda-pbb", "/api/h2h/pemda/pbb", "API H2H PBB", 1, 1, 20),
("api-pbb", "/api/pbb", "API PBB", 1, 1, 20),
("pbb-api", "/pbb/api", "API PBB", 1, 1, 20),
("pbb-ws", "/pbb/ws", "PBB WS", 1, 1, 20),
("ws_pbb", "/pbb/ws/api", "API PBB WS", 1, 1, 20),
("rpc-pbb", "/rpc/pbb", "RPC PBB", 1, 1, 20),
("api-kpk-pbb", "/api/kpk/pbb", "API KPK PBB", 1, 1, 20),
("api-report-pbb", "/api/report/pbb", "API REPORT PBB", 1, 1, 20),
("api-eta-pbb", "/api/eta/pbb", "API ETA PBB", 1, 1, 20),
("rpc-pbb-payment", "/rpc/pbb/payment", "RPC Payment", 1, 1, 20),
("nop-add", "/nop/add", "NOP Finder", 1, 0, 20),
("nop-list", "/nop/list", "NOP List", 1, 0, 20),
("nop-list-act", "/nop/list/{act}/act", "NOP ACT", 1, 0, 20),
]
\ No newline at end of file \ No newline at end of file
kode,path,module,file_name,class_name,func_name,order_id,permission,parent_id/routes.kode,nama,status,type,app_id,is_menu,template,csrf
api-h2h-pemda-pbb,/api/h2h/pemda/pbb,pbb_model,,,,,,,API H2H PBB,1,1,,,,
api-pbb,/api/pbb,pbb_model,,,,,,,API PBB,1,1,,,,
pbb-api,/pbb/api,pbb_model,,,,,,,API PBB,1,1,,,,
pbb-ws,/pbb/ws,pbb_model,,,,,,,PBB WS,1,1,,,,
ws_pbb,/pbb/ws/api,pbb_model,,,,,,,API PBB WS,1,1,,,,
rpc-pbb,/rpc/pbb,pbb_model,,,,,,,RPC PBB,1,1,,,,
api-kpk-pbb,/api/kpk/pbb,pbb_model,,,,,,,API KPK PBB,1,1,,,,
api-report-pbb,/api/report/pbb,pbb_model,,,,,,,API REPORT PBB,1,1,,,,
api-eta-pbb,/api/eta/pbb,pbb_model,,,,,,,API ETA PBB,1,1,,,,
rpc-pbb-payment,/rpc/pbb/payment,pbb_model,,,,,,,RPC Payment,1,1,,,,
nop-add,/nop/add,pbb_model,,,,,,,NOP Finder,1,0,,,,
nop-list,/nop/list,pbb_model,,,,,,,NOP List,1,0,,,,
nop-list-act,/nop/list/{act}/act,pbb_model,,,,,,,NOP ACT,1,0,,,,
No preview for this file type
This diff could not be displayed because it is too large.
This diff could not be displayed because it is too large.
This diff could not be displayed because it is too large.
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!