pad_json.py 6.91 KB
import sys
import datetime
from datetime import timedelta
import transaction
from opensipkd.waktu import (
    dmyhms,
    date_from_str,
    )
from opensipkd.string import FixLength
from opensipkd.pad.models.default import (
    IsoPayment,
    IsoReversal,
    )
from opensipkd.pad.services.default import INVOICE_ID
from iso8583_web.models.meta import Base as BaseConf
from opensipkd.iso8583.bjb.pad.doc import Doc as BjbDoc
from opensipkd.iso8583.multi.doc import Doc as MultiDoc
from ..models import (
    Base,
    Pad,
    )
from .common import (
    BaseApp,
    init_db as base_init_db,
    BANK_NAMES,
    )


ERR_NOT_FOUND = 'Tgl {tgl_bayar} pad.pad_sspd.spt_id {invoice_id} tidak ada'


def get_filter(q):
    return q.filter(IsoPayment.iso_request.like('{%'))


class App(BaseApp):
    report_orm = Pad

    def __init__(self, argv):
        super().__init__(argv)
        if not self.pid:
            return
        Usaha = self.models.Usaha
        Pajak = self.models.Pajak
        Customer = self.models.Customer
        CustomerUsaha = self.models.CustomerUsaha
        Invoice = self.models.Invoice
        Payment = self.models.Payment
        self.base_q_pay = self.prod_session.query(Payment)
        self.base_q_inv = self.prod_session.query(
                Invoice, Pajak, Customer, Usaha)
        self.base_q_inv = self.base_q_inv.filter(
                Invoice.pajak_id == Pajak.id,
                Invoice.customer_usaha_id == CustomerUsaha.id,
                CustomerUsaha.customer_id == Customer.id,
                Usaha.id == Pajak.usaha_id,)
        self.base_q_iso = self.prod_session.query(IsoPayment)

    def get_pay(self, row):
        tgl_bayar = row.tgl.date()
        Payment = self.models.Payment
        q_pay = self.base_q_pay.filter_by(spt_id=row.invoice_id).filter(
                Payment.create_date >= tgl_bayar,
                Payment.create_date < tgl_bayar + timedelta(1))
        q_pay = q_pay.order_by(Payment.id.desc())
        return q_pay.first()

    def __get_query_iso(self, last_id):
        q_iso = self.base_q_iso.filter(IsoPayment.id > last_id)
        q_iso = get_filter(q_iso)
        return q_iso.order_by(IsoPayment.id)

    def __create_data(self, row, pay, iso, d, tgl_bayar):
        Invoice = self.models.Invoice
        q_inv = self.base_q_inv.filter(Invoice.id == pay.spt_id)
        inv, pajak, cust, usaha = q_inv.first()
        return dict(
            stan=d['stan'], ntb=d['ntb'], tgl=tgl_bayar,
            jam=row.tgl.time(), sspd_id=pay.id,
            nomor_bayar=d['nomor_bayar'],
            jenis_pajak=usaha.usahanm.strip(),
            masa_pajak=pajak.masapajak, npwpd=cust.npwpd,
            nama_wp=cust.customernm, pokok=pay.jml_bayar-pay.denda,
            denda=pay.denda, jml_bayar=pay.jml_bayar,
            channel_id=row.channel_id,
            channel_name=d['channel'], bank_id=row.bank_id)

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

    def get_keys(self, row):
        Invoice = self.models.Invoice
        q = self.prod_session.query(Invoice).filter_by(id=row.invoice_id)
        invoice = q.first()
        inv_id = FixLength(INVOICE_ID)
        inv_id['Tahun'] = str(invoice.tahun)
        inv_id['SptNo'] = str(invoice.sptno)
        stan = row.transmission.strftime('%H%M%S')
        return dict(
                stan=stan,
                nomor_bayar=inv_id.get_raw(),
                ntb=row.ntb,
                channel=BANK_NAMES[str(row.bank_id)])

    def __run_payment(self):
        last = self.get_last_id('pad json payment last id')
        q_iso = self.__get_query_iso(last.as_int())
        found = False
        for row in q_iso.order_by(IsoPayment.id).limit(1000):
            iso = eval(row.iso_request)
            d = self.get_keys(row)
            if self.get_report(d['stan'], d['ntb']):
                continue
            pay = self.get_pay(row)
            tgl_bayar = row.tgl.date()
            if not pay:
                msg = ERR_NOT_FOUND.format(
                        tgl_bayar=tgl_bayar, invoice_id=row.invoice_id)
                self.log.error(msg)
                continue
            s_tgl = dmyhms(row.tgl)
            data = self.__create_data(row, pay, iso, d, tgl_bayar)
            self.__log_progress(s_tgl, data)
            rpt = Pad(**data)
            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_iso = self.__get_query_iso(self.last_id)
        found = False
        for row in q_iso.order_by(IsoPayment.id).limit(1000):
            iso = eval(row.iso_request)
            d = self.get_keys(row)
            print(d)
            tgl_bayar = row.tgl.date()
            pay = self.get_pay(row)
            rpt = self.get_report(d['stan'], d['ntb'])
            if not rpt:
                if not pay:
                    msg = ERR_NOT_FOUND.format(
                            tgl_bayar=tgl_bayar, invoice_id=row.invoice_id)
                    self.log.error(msg)
                    continue
                rpt = Pad()
            s_tgl = dmyhms(row.tgl)
            data = self.__create_data(row, pay, iso, d, tgl_bayar)
            self.__log_progress(s_tgl, data)
            rpt.from_dict(data)
            with transaction.manager:
                self.rpt_session.add(rpt)
            found = True
            self.last_id = row.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(IsoPayment).filter(
                    IsoPayment.tgl >= tgl).order_by(
                    IsoPayment.id)
            q = get_filter(q)
            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 get_iso_reversal_orm(self):  # Override
        return IsoReversal

    def get_doc_for_reversal(self, row):  # Override
        q = self.prod_session.query(IsoPayment).filter_by(id=row.id)
        iso_pay = q.first()
        return BankHandlers[iso_pay.bank_id]

    def run_reversal(self):  # Override
        last = self.get_last_id('pad json reversal last date')
        q = self.prod_session.query(IsoReversal).filter(
                IsoReversal.iso_request.like('{%'),
                IsoReversal.tgl > last.as_datetime())
        for row in q.order_by(IsoReversal.tgl):
            print(f'DEBUG reversal {row.tgl}')


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)