pbb.py 8.2 KB
import sys
from ISO8583.ISO8583 import BitNotSet
import transaction
from opensipkd.string import (
    FixLength,
    DateTimeVar,
    )
from opensipkd.waktu import (
    dmyhms,
    create_datetime,
    date_from_str,
    )
from sismiop.services.base import get_db_session
from opensipkd.iso8583.bjb.scripts.common import get_module_object
from opensipkd.iso8583.bjb.pbb import Doc
from opensipkd.iso8583.bjb.pbb.structure import INVOICE_PROFILE
from ..models import Pbb
from .common import (
    get_iso,
    get_keys,
    App as BaseApp,
    )


ERR_NOT_FOUND = 'Tgl {tgl_bayar} SPPT ID {invoice_id} '\
        'tidak ada di pembayaran_sppt'


def get_profile(iso):
    p = FixLength(INVOICE_PROFILE)
    try:
        p.set_raw(iso.get_invoice_profile())
    except BitNotSet:
        return
    return p


def get_nama_wp(iso, sppt):
    p = get_profile(iso)
    if p:
        return p['Nama']
    return sppt.nm_wp_sppt


def get_tgl_bayar(iso, year):
    raw = iso.get_value(7)
    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 get_user_id(iso):
    try:
        return iso.getBit(107)
    except BitNotSet:
        return


class App(BaseApp):
    iso_class = Doc
    report_orm = Pbb

    def __init__(self, argv):
        super().__init__(argv)
        if not self.pid:
            return
        d = self.module.Doc()
        self.iso_inquiry_orm = d.iso_inquiry_model
        self.iso_payment_orm = d.iso_payment_model
        self.iso_reversal_orm = d.iso_reversal_model
        self.base_q_iso = self.prod_session.query(
            self.iso_payment_orm, self.iso_inquiry_orm).filter(
            self.iso_payment_orm.inquiry_id == self.iso_inquiry_orm.id)
        self.models = get_module_object(self.conf['models'])
        self.PembayaranSppt = self.models.PembayaranSppt
        self.Sppt = self.models.Sppt
        self.base_q_psppt = self.prod_session.query(self.PembayaranSppt)
        self.base_q_sppt = self.prod_session.query(self.Sppt)

    def get_db_session(self):  # Override
        return get_db_session()

    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_iso(self, last_id):
        q_iso = self.base_q_iso.filter(self.iso_inquiry_orm.id > last_id)
        return q_iso.order_by(self.iso_inquiry_orm.id)

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

    def __log_progress(self, s_tgl, d):
        self.log.info(
            f'Tgl bayar {s_tgl}, Nomor bayar {d["nomor_bayar"]}, '
            f'STAN {d["stan"]}, NTB {d["ntb"]}, Channel {d["channel"]}')

    def __run_payment(self):
        last = self.get_last_id('pbb payment last id')
        q_iso = self.__get_query_iso(last.as_int())
        found = False
        for row_pay, row_inq in q_iso.limit(1000):
            iso = get_iso(row_pay.iso_request, Doc, self.option.debug)
            if self.get_report(iso):
                continue
            d = get_keys(iso)
            tgl_bayar = get_tgl_bayar(iso, row_inq.tgl.year)
            s_tgl = dmyhms(tgl_bayar)
            psppt = self.get_psppt(row_pay)
            if not psppt:
                self.__log_not_found(s_tgl, d)
                continue
            sppt = self.get_sppt(psppt)
            nama_wp = get_nama_wp(iso, sppt)
            user_id = get_user_id(iso)
            self.__log_progress(s_tgl, d)
            rpt = Pbb(
                    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.get_amount(),
                    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.get_channel().strip(),
                    channel_nama=d['channel'], user_id=user_id,
                    pbb_yg_harus_dibayar_sppt=sppt.pbb_yg_harus_dibayar_sppt,
                    tgl_inquiry=row_inq.tgl, discount=psppt.discount)
            last.nilai = str(row_inq.id)
            with transaction.manager:
                self.rpt_session.add(rpt)
                self.rpt_session.add(last)
            found = True
        return found

    def __update_from_id(self):
        q_iso = self.__get_query_iso(self.last_id)
        found = False
        for row_pay, row_inq in q_iso.limit(1000):
            iso = get_iso(row_pay.iso_request, Doc, self.option.debug)
            d = get_keys(iso)
            tgl_bayar = get_tgl_bayar(iso, row_inq.tgl.year)
            s_tgl = dmyhms(tgl_bayar)
            psppt = self.get_psppt(row_pay)
            if not psppt:
                self.__log_not_found(s_tgl, d)
                continue
            sppt = self.get_sppt(psppt)
            nama_wp = get_nama_wp(iso, sppt)
            user_id = get_user_id(iso)
            self.__log_progress(s_tgl, d)
            d = 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.get_amount(),
                    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.get_channel().strip(),
                    channel_nama=d['channel'], user_id=user_id,
                    pbb_yg_harus_dibayar_sppt=sppt.pbb_yg_harus_dibayar_sppt,
                    tgl_inquiry=row_inq.tgl, discount=psppt.discount)
            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_inq.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)
            q = self.prod_session.query(self.iso_inquiry_orm).filter(
                    self.iso_inquiry_orm.tgl >= tgl).order_by(
                    self.iso_inquiry_orm.id)
            row = q.first()
            self.last_id = row.id - 1
            func = self.__update_from_id
        else:
            func = self.__run_payment
        while True:
            found = func()
            if not found:
                break

    def run_reversal(self):  # Override
        super().run_reversal('pbb reversal last date')


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