pbb_json.py 8.44 KB
import sys
from sqlalchemy import (
    Column,
    Integer,
    String,
    UniqueConstraint,
    )
import transaction
from opensipkd.string import (
    FixLength,
    DateTimeVar,
    )
from opensipkd.waktu import (
    dmyhms,
    create_datetime,
    date_from_str,
    )
from sismiop.services.base import get_id
from ..models import (
    Pbb as Report,
    Base,
    )
from .common import (
    BaseApp,
    get_channel_name_by_dict,
    get_module_object,
    )


ERR_NOT_FOUND = 'SPPT ID {invoice_id} pembayaran ke {ke} '\
        'tidak ada di pembayaran_sppt'


class Log(Base):
    __tablename__ = 'pbb_payment'
    id = Column(Integer, primary_key=True)
    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'))


def get_keys(d):
    r = dict()
    r['channel'] = get_channel_name_by_dict(d)
    r.update(dict(
        nomor_bayar=d['bit_061'],
        stan=d['bit_011'],
        ntb=d['bit_037']))
    return r


def get_nama_wp(d):
    return d['bit_062']['name']


def get_tgl_bayar(d, year):
    raw = d['bit_007']
    t = DateTimeVar()
    t.set_raw(raw)
    return create_datetime(
            year, int(t['month']), int(t['day']), int(t['hour']),
            int(t['minute']), int(t['second']))


def error(s):
    print(s)
    sys.exit()


class App(BaseApp):
    report_orm = Report

    def __init__(self, argv):
        super().__init__(argv)
        if not self.pid:
            return
        factory = self.get_factory('pbb_db_url')
        self.pbb_session = factory()
        self.base_q_log = self.prod_session.query(Log)
        self.models = get_module_object(self.conf['models'])
        self.PembayaranSppt = self.models.PembayaranSppt
        self.Sppt = self.models.Sppt
        self.base_q_psppt = self.pbb_session.query(self.PembayaranSppt)
        self.base_q_psppt = self.base_q_psppt.filter_by(
                kd_kanwil=self.conf['kd_kanwil'],
                kd_kantor=self.conf['kd_kantor'], kd_tp=self.conf['kd_tp'])
        self.base_q_sppt = self.pbb_session.query(self.Sppt)

    def get_report(self, d):  # Override
        return super().get_report(d['bit_011'], d['bit_037'])

    def get_psppt(self, pay):
        q = self.base_q_psppt.filter_by(
                kd_propinsi=pay.propinsi,
                kd_dati2=pay.kabupaten,
                kd_kecamatan=pay.kecamatan,
                kd_kelurahan=pay.kelurahan,
                kd_blok=pay.blok,
                no_urut=pay.urut,
                kd_jns_op=pay.jenis,
                thn_pajak_sppt=str(pay.tahun),
                pembayaran_sppt_ke=pay.ke)
        return q.first()

    def get_sppt(self, psppt):
        q = self.base_q_sppt.filter_by(
                kd_propinsi=psppt.kd_propinsi,
                kd_dati2=psppt.kd_dati2,
                kd_kecamatan=psppt.kd_kecamatan,
                kd_kelurahan=psppt.kd_kelurahan,
                kd_blok=psppt.kd_blok,
                no_urut=psppt.no_urut,
                kd_jns_op=psppt.kd_jns_op,
                thn_pajak_sppt=psppt.thn_pajak_sppt)
        return q.first()

    def __get_query_log(self, last_id):
        return self.base_q_log.filter(Log.id > last_id).order_by(Log.id)

    def __log_not_found(self, row, d):
        msg = ERR_NOT_FOUND.format(invoice_id=d['nomor_bayar'], ke=row.ke)
        self.log.error(msg)

    def __log_progress(self, s_tgl, d):
        self.log.info(f'Tgl bayar {s_tgl}, {d}')

    def __create_data(self, iso, d, tgl_bayar, psppt):
        sppt = self.get_sppt(psppt)
        nama_wp = get_nama_wp(iso)
        discount = hasattr(psppt, 'discount') and psppt.discount or None
        return dict(
            stan=d['stan'], ntb=d['ntb'],
            kd_propinsi=psppt.kd_propinsi, kd_dati2=psppt.kd_dati2,
            kd_kecamatan=psppt.kd_kecamatan, kd_kelurahan=psppt.kd_kelurahan,
            kd_blok=psppt.kd_blok, no_urut=psppt.no_urut,
            kd_jns_op=psppt.kd_jns_op, thn_pajak_sppt=psppt.thn_pajak_sppt,
            pembayaran_sppt_ke=psppt.pembayaran_sppt_ke,
            jml_sppt_yg_dibayar=iso['bit_004'],
            denda_sppt=psppt.denda_sppt, tgl_pembayaran_sppt=tgl_bayar.date(),
            tgl_rekam_byr_sppt=tgl_bayar, nm_wp_sppt=nama_wp,
            channel_kode=iso['bit_032'].strip(), channel_nama=d['channel'],
            pbb_yg_harus_dibayar_sppt=sppt.pbb_yg_harus_dibayar_sppt,
            discount=discount, bank_id=iso['bit_032'], tgl_inquiry=tgl_bayar)

    def __run_payment(self):
        last = self.get_last_id('pbb json payment last id')
        q_log = self.__get_query_log(last.as_int())
        found = False
        for row in q_log.limit(1000):
            iso = eval(row.iso_request)
            if self.get_report(iso):
                continue
            d = get_keys(iso)
            psppt = self.get_psppt(row)
            if not psppt:
                self.__log_not_found(row, d)
                continue
            tgl_bayar = get_tgl_bayar(iso, psppt.tgl_rekam_byr_sppt.year)
            s_tgl = dmyhms(tgl_bayar)
            self.__log_progress(s_tgl, d)
            d = self.__create_data(iso, d, tgl_bayar, psppt)
            rpt = Report(**d)
            last.nilai = str(row.id)
            with transaction.manager:
                self.rpt_session.add(rpt)
                self.rpt_session.add(last)
            found = True
        return found

    def __update_from_id(self):
        q_log = self.__get_query_log(self.last_id)
        found = False
        for row_pay in q_log.limit(1000):
            iso = eval(row_pay.iso_request)
            d = get_keys(iso)
            psppt = self.get_psppt(row_pay)
            if not psppt:
                self.__log_not_found(row_pay, d)
                continue
            tgl_bayar = get_tgl_bayar(iso, psppt.tgl_rekam_byr_sppt.year)
            s_tgl = dmyhms(tgl_bayar)
            self.__log_progress(s_tgl, d)
            d = self.__create_data(iso, d, tgl_bayar, psppt)
            rpt = self.get_report(iso)
            if not rpt:
                rpt = Pbb()
            rpt.from_dict(d)
            with transaction.manager:
                self.rpt_session.add(rpt)
            found = True
            self.last_id = row_pay.id
        return found

    def run_payment(self):  # Override
        if self.option.update_from_id:
            self.last_id = self.option.update_from_id
            func = self.__update_from_id
        elif self.option.update_from_date:
            tgl = date_from_str(self.option.update_from_date)
            Psppt = self.PembayaranSppt
            q = self.base_q_psppt.filter(Psppt.tgl_rekam_byr_sppt >= tgl)
            row_psppt = q.order_by(Psppt.tgl_rekam_byr_sppt).first()
            if not row_psppt:
                error('Kosong')
            invoice_id = get_id(row_psppt)
            print(f'DEBUG Invoice ID {invoice_id}')
            q = self.base_q_log.filter_by(
                    propinsi=row_psppt.kd_propinsi,
                    kabupaten=row_psppt.kd_dati2,
                    kecamatan=row_psppt.kd_kecamatan,
                    kelurahan=row_psppt.kd_kelurahan,
                    blok=row_psppt.kd_blok,
                    urut=row_psppt.no_urut,
                    jenis=row_psppt.kd_jns_op,
                    tahun=row_psppt.thn_pajak_sppt,
                    ke=row_psppt.pembayaran_sppt_ke)
            row_log = q.order_by(Log.id).first()
            self.last_id = row_log.id - 1
            func = self.__update_from_id
        else:
            func = self.__run_payment
        while True:
            found = func()
            if not found:
                break


def main(argv=sys.argv[1:]):
    app = App(argv)
    app.run()