Commit 4f7c810c by Owo Sugiana

Penambahan rumus Kota Bogor

1 parent 07b75e49
......@@ -2,3 +2,4 @@
dist
__pycache__
*.pyc
test.ini
0.1.2 2020-04-19
----------------
- Tambah pengurangan pokok untuk Kota Bogor.
0.1.1 2019-05-27
----------------
- Tambah default model siap pakai.
......
......@@ -3,3 +3,47 @@ SISMIOP a.k.a PBB
Struktur tabel SISMIOP yang merupakan sistem PBB (Pajak Bumi dan Bangunan).
Biasanya dari Oracle.
Pemasangan
----------
Buat Python virtual environment::
$ python3 -m venv ~/env
Setelah paket ini diunduh selanjutnya dipasang::
$ ~/env/bin/pip install -e sismiop-models
Salin konfigurasi::
$ cd sismiop-models
$ cp development.ini test.ini
Sesuaikan isinya terutama pada ``module`` dan ``db_url``.
Untuk mendapatkan daftar tagihan yang belum dibayar::
$ ~/env/bin/pbb_available_invoice test.ini
Jika ingin tahun tertentu gunakan opsi ``--tahun``::
$ ~/env/bin/pbb_available_invoice test.ini --tahun=2020
Lihat opsi lainnya dengan ``--help``::
$ ~/env/bin/pbb_available_invoice test.ini --help
Untuk melihat rincian tagihan::
$ ~/env/bin/pbb_inquiry test.ini -i 3271010001001000402019
Coba pembayaran::
$ ~/env/bin/pbb_inquiry test.ini -i 3271010001001000402019 --payment
Batalkan::
$ ~/env/bin/pbb_inquiry test.ini -i 3271010001001000402019 --reversal
Selamat mencoba.
[main]
# Daftar modul ada di direktori sismiop/services. Yang tersedia adalah
# default dan bogor_kota.
module = default
db_url = postgresql://username:password@localhost/db_name
persen_denda = 2
# Digunakan saat payment
nip_pencatat = 999999999
kd_kanwil = 01
kd_kantor = 01
kd_tp = 71
......@@ -13,6 +13,10 @@ version = line.split()[0]
requires = [
'sqlalchemy',
'transaction',
'zope.sqlalchemy',
'psycopg2-binary',
'opensipkd-hitung @ git+https://git.opensipkd.com/sugiana/opensipkd-hitung',
]
......@@ -26,15 +30,15 @@ setup(
license='PostgreSQL License',
packages=[
'sismiop.models',
'sismiop.models.default',
'sismiop.services',
'sismiop.services.default',
'sismiop.scripts'],
install_requires=requires,
zip_safe=False,
entry_points={
'console_scripts': [
'pbb_init_db = sismiop.scripts.init_db:main',
'pbb_available_invoice = sismiop.scripts.available_invoice:main',
'pbb_inquiry = sismiop.scripts.inquiry:main',
]
}
)
from sqlalchemy import (
Column,
Integer,
String,
Float,
)
from sqlalchemy.ext.declarative import declarative_base
from .objek_pajak import ObjekPajakMixin
from .sppt import SpptMixin
from .pembayaran_sppt import PembayaranSpptMixin
from .kelurahan import KelurahanMixin
from .kecamatan import KecamatanMixin
from .propinsi import PropinsiMixin
Base = declarative_base()
class ObjekPajak(Base, ObjekPajakMixin):
pass
class Sppt(Base, SpptMixin):
pass
class PembayaranSppt(Base, PembayaranSpptMixin):
pass
class Kelurahan(Base, KelurahanMixin):
pass
class Kecamatan(Base, KecamatanMixin):
pass
class Propinsi(Base, PropinsiMixin):
pass
class PenguranganCovid(Base):
__tablename__ = 'pengurangan_covid'
id = Column(Integer, primary_key=True)
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)
thn_pajak_sppt = Column(String(4), nullable=False)
pembayaran_sppt_ke = Column(Integer, nullable=False)
pokok = Column(Float, nullable=False)
denda = Column(Float, nullable=False)
#__table_args__ = (
# ForeignKeyConstraint(
# [kd_propinsi, kd_dati2, kd_kecamatan, kd_kelurahan, kd_blok,
# no_urut, kd_jns_op, thn_pajak_sppt, pembayaran_sppt_ke],
# [PembayaranSppt.kd_propinsi, PembayaranSppt.kd_dati2,
# PembayaranSppt.kd_kecamatan, PembayaranSppt.kd_kelurahan,
# PembayaranSppt.kd_blok, PembayaranSppt.no_urut,
# PembayaranSppt.kd_jns_op, PembayaranSppt.thn_pajak_sppt,
# PembayaranSppt.pembayaran_sppt_ke]),
# )
class PenguranganPst(Base):
__tablename__ = 'pengurangan_pst'
id = Column(Integer, primary_key=True)
kd_kanwil = Column(String(2), nullable=False)
kd_kantor = Column(String(2), nullable=False)
thn_pelayanan = Column(String(4), nullable=False)
no_urut_pelayanan = Column(String(3), nullable=False)
kd_propinsi_pemohon = Column(String(2), nullable=False)
kd_dati2_pemohon = Column(String(2), nullable=False)
kd_kecamatan_pemohon = Column(String(3), nullable=False)
kd_kelurahan_pemohon = Column(String(3), nullable=False)
kd_blok_pemohon = Column(String(3), nullable=False)
no_urut_pemohon = Column(String(4), nullable=False)
kd_jns_op_pemohon = Column(String(1), nullable=False)
thn_peng_pst = Column(String(4), nullable=False)
jns_sk = Column(String(1), nullable=False)
no_sk = Column(String(30), nullable=False)
status_sk_peng_pst = Column(Integer, nullable=False)
pct_pengurangan_pst = Column(String(1), nullable=False)
from sqlalchemy.ext.declarative import declarative_base
from ..sppt import SpptMixin
from ..pembayaran_sppt import PembayaranSpptMixin
from ..kelurahan import KelurahanMixin
from ..kecamatan import KecamatanMixin
from ..propinsi import PropinsiMixin
Base = declarative_base()
class Sppt(Base, SpptMixin):
pass
class PembayaranSppt(Base, PembayaranSpptMixin):
pass
class Kelurahan(Base, KelurahanMixin):
pass
class Kecamatan(Base, KecamatanMixin):
pass
class Propinsi(Base, PropinsiMixin):
pass
import sys
from configparser import ConfigParser
from optparse import OptionParser
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
import sismiop.services
from sismiop.services.default import AvailableInvoice
import sismiop.services.base
def get_option(argv):
default_count = 10
help_count = 'default {}'.format(default_count)
pars = OptionParser()
pars.add_option('', '--tahun')
pars.add_option(
'', '--count', type=int, default=default_count, help=help_count)
return pars.parse_args(argv)
def main(argv=sys.argv):
conf_file = argv[1]
option, remain = get_option(argv[1:])
count = int(option.count)
conf_file = remain[0]
conf = ConfigParser()
conf.read(conf_file)
module_name = conf.get('main', 'module')
module = __import__('sismiop.services.' + module_name)
sub_module = getattr(module.services, module_name)
AvailableInvoice = sub_module.AvailableInvoice
db_url = conf.get('main', 'db_url')
persen_denda = conf.getfloat('main', 'persen_denda')
engine = create_engine(db_url)
session_factory = sessionmaker(bind=engine)
sismiop.services.DBSession = session_factory()
a = AvailableInvoice(persen_denda)
sismiop.services.base.DBSession = session_factory()
a = AvailableInvoice(persen_denda, count, option.tahun)
a.show()
import sys
from configparser import ConfigParser
from sqlalchemy import create_engine
from sismiop.models.default import Base
def main(argv=sys.argv):
config_uri = argv[1]
conf = ConfigParser()
conf.read(config_uri)
db_url = conf.get('main', 'db_url')
engine = create_engine(db_url)
Base.metadata.create_all(engine)
import sys
import locale
from datetime import date
from configparser import ConfigParser
from optparse import OptionParser
import transaction
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
from zope.sqlalchemy import register
import sismiop.services.base
locale.setlocale(locale.LC_ALL, 'id_ID.utf8')
def thousand(n):
return locale.format('%.0f', n, True)
def show_val(label, value):
print('{}: {}'.format(label, value))
def show_rp(label, value):
show_val(label, 'Rp {}'.format(thousand(value)))
def date_from_str(s):
d, m, y = s.split('-')
return date(int(y), int(m), int(d))
def get_option(argv):
help_tgl = 'butuh --payment'
pars = OptionParser()
pars.add_option('-i', '--invoice-id')
pars.add_option('', '--payment', action='store_true')
pars.add_option('', '--tgl-bayar', help=help_tgl)
pars.add_option('', '--reversal', action='store_true')
return pars.parse_args(argv)
def show(inq):
show_val('Invoice ID', inq.invoice_id_raw)
show_val('Kelurahan Objek Pajak', inq.get_kelurahan_op())
show_val('Kecamatan Objek Pajak', inq.get_kecamatan_op())
show_val('Provinsi Objek Pajak', inq.get_propinsi_op())
show_val('Alamat Objek Pajak', inq.get_alamat_op())
show_val('Luas Tanah', inq.get_luas_tanah())
show_val('Luas Bangunan', inq.get_luas_bangunan())
show_rp('Tagihan', inq.tagihan)
show_rp('Denda', inq.denda)
show_rp('Total Bayar', inq.total_bayar)
show_rp('Total Tagihan', inq.total)
show_val('Jatuh Tempo', inq.get_jatuh_tempo())
show_val('Tahun Pajak', inq.get_tahun())
def main(argv=sys.argv):
option, remain = get_option(argv[1:])
invoice_id = option.invoice_id
if option.tgl_bayar:
tgl_bayar = date_from_str(option.tgl_bayar)
else:
tgl_bayar = None
conf_file = remain[0]
conf = ConfigParser()
conf.read(conf_file)
module_name = conf.get('main', 'module')
module = __import__('sismiop.services.' + module_name)
sub_module = getattr(module.services, module_name)
Inquiry = sub_module.Inquiry
Reversal = sub_module.Reversal
db_url = conf.get('main', 'db_url')
engine = create_engine(db_url)
session_factory = sessionmaker(bind=engine)
sismiop.services.base.DBSession = session_factory()
register(sismiop.services.base.DBSession)
with transaction.manager:
inq = Inquiry(invoice_id, conf.getfloat('main', 'persen_denda'))
if not inq.invoice:
print('Invoice ID {} tidak ada.'.format(invoice_id))
return
show(inq)
if option.payment:
if inq.is_paid():
print('Tidak ada tagihan, tidak ada yang perlu dibayar.')
return
if not inq.is_available():
print('Tagihan tidak diperkenankan dibayar melalui jalur ini.')
return
tp = dict(
kd_kanwil=conf.get('main', 'kd_kanwil'),
kd_kantor=conf.get('main', 'kd_kantor'),
kd_tp=conf.get('main', 'kd_tp'))
nip = conf.get('main', 'nip_pencatat')
pay = inq.do_payment(tp, nip, tgl_bayar)
print(
'Berhasil dibayar pada urutan ke-{}'.format(
pay.pembayaran_sppt_ke))
if option.reversal:
rev = Reversal(invoice_id)
pay = rev.payment
if not pay:
print('Pembayaran tidak ditemukan, tidak ada yang perlu dibatalkan.')
return
rev.do_reversal()
print(
'Pembayaran ke-{} berhasil dibatalkan'.format(
pay.pembayaran_sppt_ke))
DBSession = None
def get_db_session(db_session=None):
return db_session or DBSession
from time import time
from datetime import (
date,
datetime,
)
from sqlalchemy import func
import locale
from opensipkd.string import FixLength
from opensipkd.hitung import (
hitung_denda,
round_up,
)
# Ditetapkan dari luar
DBSession = None
locale.setlocale(locale.LC_ALL, 'id_ID.utf8')
INVOICE_ID = [
('Propinsi', 2, 'N'),
('Kabupaten', 2, 'N'),
('Kecamatan', 3, 'N'),
('Kelurahan', 3, 'N'),
('Blok', 3, 'N'),
('Urut', 4, 'N'),
('Jenis', 1, 'N'),
('Tahun', 4, 'N'),
]
def get_db_session():
return DBSession
def thousand(n):
return locale.format('%0.f', n, True)
def get_id(row):
return ''.join(
[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])
class Query:
def __init__(self, invoice_id=None, invoice=None):
self.invoice_id = FixLength(INVOICE_ID)
if invoice:
self.invoice = invoice
self.invoice_id_raw = get_id(invoice)
self.invoice_id.set_raw(self.invoice_id_raw)
else:
self.invoice_id_raw = invoice_id
self.invoice_id.set_raw(invoice_id)
q = self.query_invoice()
self.invoice = q.first()
def get_op_model(self): # Objek Pajak
pass
def get_invoice_model(self):
pass
def get_payment_model(self):
pass
def get_filter_op(self, q):
inv_id = self.invoice_id
return q.filter_by(
kd_propinsi=inv_id['Propinsi'], kd_dati2=inv_id['Kabupaten'],
kd_kecamatan=inv_id['Kecamatan'],
kd_kelurahan=inv_id['Kelurahan'],
kd_blok=inv_id['Blok'], no_urut=inv_id['Urut'],
kd_jns_op=inv_id['Jenis'])
def get_filter(self, q):
inv_id = self.invoice_id
q = self.get_filter_op(q)
return q.filter_by(thn_pajak_sppt=inv_id['Tahun'])
def get_query(self, model):
q = DBSession.query(model)
return self.get_filter(q)
def query_op(self):
OP = self.get_op_model()
q = DBSession.query(OP)
return self.get_filter_op(q)
def query_invoice(self):
Invoice = self.get_invoice_model()
return self.get_query(Invoice)
def query_payment(self):
Payment = self.get_payment_model()
return self.get_query(Payment)
def invoice2payment(self):
Payment = self.get_payment_model()
q = self.query_payment()
q = q.order_by(Payment.pembayaran_sppt_ke.desc())
return q.first()
class Inquiry(Query):
def __init__(self, invoice_id=None, persen_denda=2, invoice=None):
Query.__init__(self, invoice_id, invoice)
self.persen_denda = persen_denda
if self.invoice:
self.hitung()
def get_kelurahan_model(self):
pass
def get_kecamatan_model(self):
pass
def get_propinsi_model(self):
pass
def get_kelurahan_op(self):
Kelurahan = self.get_kelurahan_model()
inv_id = self.invoice_id
q = DBSession.query(Kelurahan).filter_by(
kd_propinsi=inv_id['Propinsi'], kd_dati2=inv_id['Kabupaten'],
kd_kecamatan=inv_id['Kecamatan'],
kd_kelurahan=inv_id['Kelurahan'])
r = q.first()
return r and r.nm_kelurahan or ''
def get_kecamatan_op(self):
Kecamatan = self.get_kecamatan_model()
inv_id = self.invoice_id
q = DBSession.query(Kecamatan).filter_by(
kd_propinsi=inv_id['Propinsi'], kd_dati2=inv_id['Kabupaten'],
kd_kecamatan=inv_id['Kecamatan'])
r = q.first()
return r and r.nm_kecamatan or ''
def get_propinsi_op(self):
Propinsi = self.get_propinsi_model()
inv_id = self.invoice_id
q = DBSession.query(Propinsi).filter_by(kd_propinsi=inv_id['Propinsi'])
r = q.first()
return r and r.nm_propinsi or ''
def get_alamat_op(self):
q = self.query_op()
op = q.first()
if op:
return op.jalan_op
return self.invoice.jln_wp_sppt
def get_jatuh_tempo(self):
return self.invoice.tgl_jatuh_tempo_sppt
def get_tahun(self):
return self.invoice.thn_pajak_sppt
def get_luas_tanah(self):
return self.invoice.luas_bumi_sppt
def get_luas_bangunan(self):
return self.invoice.luas_bng_sppt
def is_paid(self):
return self.total < 1
def is_available(self):
return not self.is_paid() and \
self.invoice.status_pembayaran_sppt in ('0', '1')
def hitung_pokok(self):
Payment = self.get_payment_model()
q = DBSession.query(
func.sum(Payment.jml_sppt_yg_dibayar).
label('jml_sppt_yg_dibayar'),
func.sum(Payment.denda_sppt).
label('denda_sppt'))
q = self.get_filter(q)
bayar = q.first()
self.total_bayar = bayar.jml_sppt_yg_dibayar or 0
denda_lalu = bayar.denda_sppt or 0
sisa = float(self.total_bayar - denda_lalu)
tagihan = self.invoice.pbb_yg_harus_dibayar_sppt - sisa
self.tagihan = round_up(tagihan)
def hitung_denda(self, tgl_bayar):
bln_tunggakan, denda = hitung_denda(
self.tagihan, self.invoice.tgl_jatuh_tempo_sppt, self.persen_denda,
tgl_bayar)
self.denda = round_up(denda)
def hitung(self, tgl_bayar=None):
if tgl_bayar is None:
tgl_bayar = date.today()
self.hitung_pokok()
self.hitung_denda(tgl_bayar)
self.total = self.tagihan + self.denda
def do_payment(self, bank_fields, nip_pencatat, tgl_bayar=None):
if not tgl_bayar:
tgl_bayar = datetime.now()
Payment = self.get_payment_model()
bayar = self.invoice2payment()
if bayar:
ke = bayar.pembayaran_sppt_ke + 1
else:
ke = 1
bayar = Payment()
for key, value in bank_fields.items():
setattr(bayar, key, value)
bayar.kd_propinsi = self.invoice.kd_propinsi
bayar.kd_dati2 = self.invoice.kd_dati2
bayar.kd_kecamatan = self.invoice.kd_kecamatan
bayar.kd_kelurahan = self.invoice.kd_kelurahan
bayar.kd_blok = self.invoice.kd_blok
bayar.no_urut = self.invoice.no_urut
bayar.kd_jns_op = self.invoice.kd_jns_op
bayar.thn_pajak_sppt = self.invoice.thn_pajak_sppt
bayar.pembayaran_sppt_ke = ke
bayar.tgl_rekam_byr_sppt = datetime.now()
bayar.tgl_pembayaran_sppt = tgl_bayar
bayar.jml_sppt_yg_dibayar = self.total
bayar.denda_sppt = self.denda
bayar.nip_rekam_byr_sppt = nip_pencatat
self.before_save(bayar)
DBSession.add(bayar)
self.invoice.status_pembayaran_sppt = '1' # Lunas
DBSession.add(self.invoice)
DBSession.flush()
return bayar
def before_save(self, bayar):
pass
class Reversal(Query):
def __init__(self, invoice_id):
Query.__init__(self, invoice_id)
self.payment = self.invoice2payment()
def do_reversal(self):
self.payment.jml_sppt_yg_dibayar = self.payment.denda_sppt = 0
DBSession.add(self.payment)
self.invoice.status_pembayaran_sppt = '0'
DBSession.add(self.invoice)
self.before_save()
DBSession.flush()
def before_save(self):
pass
class AvailableInvoice(Query):
def __init__(self, persen_denda=2, count=10, tahun=None):
self.count = count
self.persen_denda = persen_denda
self.tahun = tahun
def get_inquiry_class(self):
return Inquiry
def show(self):
Invoice = self.get_invoice_model()
Payment = self.get_payment_model()
base_inq_cls = self.get_inquiry_class()
class Inq(base_inq_cls):
def get_invoice_model(self):
return Invoice
def get_payment_model(self):
return Payment
offset = -1
no = 0
awal = time()
while True:
durasi = time() - awal
if durasi > 10:
break
offset += 1
q = DBSession.query(Invoice).filter_by(status_pembayaran_sppt='0')
if self.tahun:
q = q.filter_by(thn_pajak_sppt=self.tahun)
q = q.offset(offset).limit(1)
inv = q.first()
if not inv:
continue
inq = Inq(invoice=inv)
if inq.is_paid():
continue
no += 1
msg = '#{} {} Pokok Rp {} + Denda Rp {} = Rp {}'.format(
str(no).zfill(2), inq.invoice_id_raw,
thousand(inq.tagihan), thousand(inq.denda),
thousand(inq.total))
print(msg)
if no == self.count:
break
from sismiop.models.default import (
ObjekPajak,
Sppt,
PembayaranSppt,
Kelurahan,
Kecamatan,
Propinsi,
)
from ..sppt import (
CalculateInvoice as BaseCalc,
from ..base import (
AvailableInvoice as BaseAvailableInvoice,
Inquiry as BaseInquiry,
Reversal as BaseReversal,
)
class CalculateInvoice(BaseCalc):
def __init__(
self, persen_denda, propinsi, kabupaten, kecamatan, kelurahan,
blok, urut, jenis, tahun):
BaseCalc.__init__(
self, Sppt, PembayaranSppt, persen_denda, propinsi, kabupaten,
kecamatan, kelurahan, blok, urut, jenis, tahun, Kelurahan,
Kecamatan, Propinsi)
class Inquiry(BaseInquiry):
def get_op_model(self):
return ObjekPajak
def get_invoice_model(self):
return Sppt
def get_payment_model(self):
return PembayaranSppt
def get_kelurahan_model(self):
return Kelurahan
def get_kecamatan_model(self):
return Kecamatan
def get_propinsi_model(self):
return Propinsi
class Reversal(BaseReversal):
def get_invoice_model(self):
return Sppt
def get_payment_model(self):
return PembayaranSppt
class AvailableInvoice(BaseAvailableInvoice):
def __init__(self, persen_denda):
BaseAvailableInvoice.__init__(self, Sppt, PembayaranSppt, persen_denda)
def get_invoice_model(self):
return Sppt
def get_payment_model(self):
return PembayaranSppt
from time import time
from datetime import date
from sqlalchemy import func
import locale
from opensipkd.hitung import (
hitung_denda,
round_up,
)
from . import get_db_session
locale.setlocale(locale.LC_ALL, 'id_ID.utf8')
def thousand(n):
return locale.format('%0.f', n, True)
class Query:
def __init__(
self, Sppt, Pembayaran, Kelurahan=None, Kecamatan=None,
Propinsi=None):
self.Sppt = Sppt
self.Pembayaran = Pembayaran
self.Kelurahan = Kelurahan
self.Kecamatan = Kecamatan
self.Propinsi = Propinsi
self.DBSession = get_db_session()
def query_invoice(
self, propinsi, kabupaten, kecamatan, kelurahan, blok, urut, jenis,
tahun):
return self.DBSession.query(self.Sppt).filter_by(
kd_propinsi=propinsi, kd_dati2=kabupaten,
kd_kecamatan=kecamatan, kd_kelurahan=kelurahan, kd_blok=blok,
no_urut=urut, kd_jns_op=jenis, thn_pajak_sppt=tahun)
def query_payment(
self, propinsi, kabupaten, kecamatan, kelurahan, blok, urut, jenis,
tahun):
return self.DBSession.query(self.Pembayaran).filter_by(
kd_propinsi=propinsi, kd_dati2=kabupaten,
kd_kecamatan=kecamatan, kd_kelurahan=kelurahan, kd_blok=blok,
no_urut=urut, kd_jns_op=jenis, thn_pajak_sppt=tahun)
def invoice2payment(self, inv):
q = self.query_payment(
inv.kd_propinsi, inv.kd_dati2, inv.kd_kecamatan,
inv.kd_kelurahan, inv.kd_blok, inv.no_urut, inv.kd_jns_op,
inv.thn_pajak_sppt)
q = q.order_by(self.Pembayaran.pembayaran_sppt_ke.desc())
return q.first()
def nama_kelurahan(self, propinsi, kabupaten, kecamatan, kelurahan):
q = self.DBSession.query(self.Kelurahan).filter_by(
kd_propinsi=propinsi, kd_dati2=kabupaten,
kd_kecamatan=kecamatan, kd_kelurahan=kelurahan)
r = q.first()
return r and r.nm_kelurahan or ''
def nama_kecamatan(self, propinsi, kabupaten, kecamatan):
q = self.DBSession.query(self.Kecamatan).filter_by(
kd_propinsi=propinsi, kd_dati2=kabupaten,
kd_kecamatan=kecamatan)
r = q.first()
return r and r.nm_kecamatan or ''
def nama_propinsi(self, propinsi):
q = self.DBSession.query(self.Propinsi).\
filter_by(kd_propinsi=propinsi)
r = q.first()
return r and r.nm_propinsi or ''
def is_available(self):
return self.invoice.status_pembayaran_sppt == '1'
def is_paid(self):
return self.is_available()
def get_id(row):
return ''.join(
[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])
class CalculateInvoice(Query):
def __init__(
self, Sppt, Pembayaran, persen_denda, propinsi, kabupaten,
kecamatan, kelurahan, blok, urut, jenis, tahun, Kelurahan=None,
Kecamatan=None, Propinsi=None):
Query.__init__(self, Sppt, Pembayaran, Kelurahan, Kecamatan, Propinsi)
self.persen_denda = persen_denda
self.propinsi = propinsi
self.kabupaten = kabupaten
self.kecamatan = kecamatan
self.kelurahan = kelurahan
self.blok = blok
self.urut = urut
self.jenis = jenis
self.tahun = tahun
self.invoice = self.invoice_tahun(tahun)
if self.invoice:
self.hitung()
def nama_kelurahan(self):
inv = self.invoice
return Query.nama_kelurahan(
self, inv.kd_propinsi, inv.kd_dati2, inv.kd_kecamatan,
inv.kd_kelurahan)
def nama_kecamatan(self):
inv = self.invoice
return Query.nama_kecamatan(
self, inv.kd_propinsi, inv.kd_dati2, inv.kd_kecamatan)
def nama_propinsi(self):
return Query.nama_propinsi(self, self.invoice.kd_propinsi)
def is_paid(self):
return self.total < 1
def is_available(self):
return not self.is_paid() and \
self.invoice.status_pembayaran_sppt in ('0', '1')
def invoice_tahun(self, tahun):
q = self.query_invoice(
self.propinsi, self.kabupaten, self.kecamatan, self.kelurahan,
self.blok, self.urut, self.jenis, tahun)
return q.first()
def hitung_invoice(self, invoice):
q = self.DBSession.query(
func.sum(self.Pembayaran.jml_sppt_yg_dibayar).
label('jml_sppt_yg_dibayar'),
func.sum(self.Pembayaran.denda_sppt).
label('denda_sppt')).\
filter_by(kd_propinsi=invoice.kd_propinsi,
kd_dati2=invoice.kd_dati2,
kd_kecamatan=invoice.kd_kecamatan,
kd_kelurahan=invoice.kd_kelurahan,
kd_blok=invoice.kd_blok,
no_urut=invoice.no_urut,
kd_jns_op=invoice.kd_jns_op,
thn_pajak_sppt=invoice.thn_pajak_sppt)
bayar = q.first()
jml_bayar = bayar.jml_sppt_yg_dibayar or 0
denda_lalu = bayar.denda_sppt or 0
sisa = float(jml_bayar - denda_lalu)
tagihan = round_up(invoice.pbb_yg_harus_dibayar_sppt - sisa)
kini = date.today()
bln_tunggakan, denda = hitung_denda(
tagihan, invoice.tgl_jatuh_tempo_sppt, self.persen_denda, kini)
denda = round_up(denda)
return tagihan, denda, bln_tunggakan, kini
def hitung(self):
self.tagihan, self.denda, self.bln_tunggakan, self.kini = \
self.hitung_invoice(self.invoice)
self.total = self.tagihan + self.denda
def set_paid(self):
self.invoice.status_pembayaran_sppt = '1' # Lunas
def create_payment(self, denda, tgl_bayar, bank_fields, nip_pencatat):
bayar = self.invoice2payment()
if bayar:
ke = bayar.pembayaran_sppt_ke + 1
else:
ke = 1
bayar = self.Pembayaran()
bayar.kd_propinsi = self.invoice.kd_propinsi
bayar.kd_dati2 = self.invoice.kd_dati2
bayar.kd_kecamatan = self.invoice.kd_kecamatan
bayar.kd_kelurahan = self.invoice.kd_kelurahan
bayar.kd_blok = self.invoice.kd_blok
bayar.no_urut = self.invoice.no_urut
bayar.kd_jns_op = self.invoice.kd_jns_op
bayar.thn_pajak_sppt = self.invoice.thn_pajak_sppt
bayar.pembayaran_sppt_ke = ke
bayar.tgl_rekam_byr_sppt = datetime.now()
bayar.tgl_pembayaran_sppt = tgl_bayar
bayar.jml_sppt_yg_dibayar = self.total
bayar.denda_sppt = denda
bayar.nip_rekam_byr_sppt = nip_pencatat
bayar.from_dict(bank_fields)
self.set_paid()
self.before_save(bayar)
self.DBSession.add(self.invoice)
self.DBSession.add(bayar)
self.DBSession.flush()
return bayar, ke
def before_save(self, bayar):
pass
# Override
def invoice2payment(self):
return Query.invoice2payment(self, self.invoice)
def get_id(self):
return get_id(self.invoice)
class AvailableInvoice:
def __init__(self, Sppt, Pembayaran, persen_denda=2, count=10):
self.count = count
self.Sppt = Sppt
self.Pembayaran = Pembayaran
self.persen_denda = persen_denda
def show(self):
Sppt = self.Sppt
offset = -1
no = 0
db_session = get_db_session()
awal = time()
while True:
durasi = time() - awal
if durasi > 10:
break
offset += 1
q = db_session.query(Sppt).filter_by(status_pembayaran_sppt='0')
q = q.order_by(Sppt.kd_propinsi, Sppt.kd_dati2, Sppt.kd_kecamatan,
Sppt.kd_kelurahan, Sppt.kd_blok, Sppt.no_urut,
Sppt.kd_jns_op, Sppt.thn_pajak_sppt)
q = q.offset(offset).limit(1)
row = q.first()
if not row:
continue
calc = CalculateInvoice(
self.Sppt, self.Pembayaran, 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.is_paid():
continue
invoice_id = calc.get_id()
no += 1
msg = '#{} {} Pokok Rp {} + Denda Rp {} = Rp {}'.format(
str(no).zfill(2), invoice_id, thousand(calc.tagihan),
thousand(calc.denda), thousand(calc.total))
print(msg)
if no == self.count:
break
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!