webr.py 4.47 KB
import sys
from datetime import datetime
from sqlalchemy.exc import ProgrammingError
import transaction
from opensipkd.waktu import dmyhms
from opensipkd.webr.models.default import (
    Payment,
    Invoice,
    )
from iso8583_web.models.meta import Base as BaseConf
from opensipkd.iso8583.bjb.webr.structure import PAYMENT_CODE
from opensipkd.iso8583.bjb.webr.models import (
    LogMixin,
    Log,
    )
from ..models import (
    Base,
    Webr,
    )
from .common import (
    BaseApp,
    init_db as base_init_db,
    BIT_18_NAMES,
    get_channel_name_by_row,
    )


class AlternativeLog(Base, LogMixin):
    __table_args__ = dict(schema='webr')


class App(BaseApp):
    def __init__(self, argv):
        super().__init__(argv)
        if not self.pid:
            return
        self.base_q_pay = self.prod_session.query(Payment, Invoice).filter(
                Payment.ar_invoice_id == Invoice.id)
        self.base_q_iso = self.prod_session.query(Log)
        try:
            self.base_q_iso.first()
            self.IsoLog = Log
        except ProgrammingError:
            self.prod_session.rollback()
            self.base_q_iso = self.prod_session.query(AlternativeLog)
            self.IsoLog = AlternativeLog
        self.base_q_iso = self.base_q_iso.filter_by(
                mti='0210', bit_003=PAYMENT_CODE, bit_039='00')

    def get_channel(self, pay, inv):
        if not pay.bank_id:
            return '0000', 'MANUAL', None
        nomor_bayar = inv.kode
        q = self.base_q_iso.filter(self.IsoLog.bit_061.like(f'{nomor_bayar}%'))
        iso = q.first()
        if not iso:
            name = BIT_18_NAMES[str(pay.channel_id)]
            return pay.channel_id, name, None
        name = get_channel_name_by_row(iso)
        return iso.bit_018, name, iso

    def update_last(self, pay):
        self.last_id = pay.id
        self.last.nilai = str(pay.id)
        with transaction.manager:
            self.rpt_session.add(self.last)

    def update_from_id(self):
        q_pay = self.base_q_pay.filter(Payment.id > self.last_id)
        no = 0
        for pay, inv in q_pay.order_by(Payment.id).limit(1000):
            no += 1
            channel_id, channel_name, iso = self.get_channel(pay, inv)
            nomor_bayar = inv.kode
            tgl_bayar = pay.created.date()
            s_tgl = dmyhms(pay.created)
            stan = iso and iso.bit_011 or None
            ntb = pay.ntb and pay.ntb.strip() or None
            msg = f'#{no} ID {pay.id}, Tgl bayar {s_tgl}, '\
                  f'Nomor bayar {nomor_bayar}, Channel {channel_name}'
            if iso:
                msg = f'{msg}, STAN {stan}, NTB {ntb}'
            if not pay.bayar:
                self.log.warning(f'{msg}, field bayar 0, abaikan')
                self.last and self.update_last(pay)
                continue
            self.log.info(msg)
            d = dict(
                    stan=stan, ntb=ntb, tgl=tgl_bayar, jam=pay.created.time(),
                    nomor_bayar=nomor_bayar, nama_wp=inv.subjek_nama,
                    pokok=inv.jumlah-inv.bunga, denda=pay.bunga,
                    jml_bayar=pay.bayar, channel_id=channel_id,
                    channel_name=channel_name)
            q = self.rpt_session.query(Webr).filter_by(id=pay.id)
            rpt = q.first()
            if rpt:
                rpt.from_dict(d)
            else:
                d['id'] = pay.id
                rpt = Webr(**d)
            self.last_id = pay.id
            with transaction.manager:
                self.rpt_session.add(rpt)
                if self.last:
                    self.last.nilai = str(pay.id)
                    self.rpt_session.add(last)
        return no

    def run_payment(self):  # Override
        self.last = None
        if self.option.update_from_id:
            self.last_id = self.option.update_from_id
        elif self.option.update_from_date:
            tgl = datetime.strptime(self.option.update_from_date, '%d-%m-%Y')
            q = self.prod_session.query(Payment).filter(
                    Payment.created >= tgl).order_by(Payment.id)
            row = q.first()
            self.last_id = row.id - 1
        else:
            self.last = self.get_last_id('webr payment last id')
            self.last_id = self.last.as_int()
        while True:
            found = self.update_from_id()
            if not found:
                break


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


def init_db(argv=sys.argv[1:]):
    base_init_db(Base.metadata, BaseConf.metadata, argv)