log2iso_ciamis.py 3.86 KB
import sys
from argparse import ArgumentParser
from time import time
from ISO8583.ISOErrors import BitNotSet
from sqlalchemy import func
from zope.sqlalchemy import register
from opensipkd.waktu import create_datetime
from opensipkd.string import FixLength
from ..models import Common
from ..log_models import LogFile
from .common import (
    BaseApp,
    my_registry,
    append_csv,
    create_session,
    InvalidSource,
    )


def get_parser():
    pars = ArgumentParser()
    pars.add_argument('conf')
    pars.add_argument('--update-from-id', type=int)
    pars.add_argument('--debug-sql', action='store_true')
    return pars


def get_option(argv):
    pars = get_parser()
    return pars.parse_args(argv)


class App(BaseApp):
    def __init__(self, argv):
        super().__init__(argv)
        if not self.pid:
            return

        class Log(self.models.Log, Common):
            pass

        self.report_orm = Log
        if self.conf['models'].find('bphtb') > -1:
            self.conf_name = 'bphtb log file last id'
            self.pajak = 'bphtb'
        else:
            self.conf_name = 'pbb log file last id'
            self.pajak = 'pbb'
        register(self.prod_session)

    def get_option(self, argv):  # Override
        return get_option(argv)

    def get_session_for_save(self):  # Override
        return self.prod_session

    def get_filter_query(self, q):
        return q.filter(LogFile.id > self.last_id)

    def get_count(self):  # Override
        q = self.prod_session.query(func.count())
        q = self.get_filter_query(q)
        return q.scalar()

    def get_payment_query(self):  # Override
        q = self.prod_session.query(LogFile)
        q = self.get_filter_query(q)
        return q.order_by(LogFile.id)

    def get_prefix_log(self):  # Override
        return f'ID {self.log_id}'

    def create_data(self, log_file):  # Override
        self.log_id = log_file.id
        raw = log_file.line[15:]
        iso = self.service.Doc()
        try:
            iso.setIsoContent(raw.encode('utf-8'))
        except ValueError as e:
            raise InvalidSource(f'ID {log_file.id} tidak dipahami: {str(e)}')
        try:
            if iso.getBit(3) != self.service.PAYMENT_CODE:
                raise InvalidSource(f'ID {log_file.id} bukan payment')
        except BitNotSet:
            raise InvalidSource(f'ID {log_file.id} bit 3 tidak ada')
        waktu = iso.get_transaction_time()
        d = dict(
                id=log_file.id, mti=iso.getMTI(), created=waktu,
                bits=iso.get_values())
        if self.pajak == 'bphtb':
            try:
                profile = FixLength(self.service.INVOICE_PROFILE)
                profile.set_raw(iso.getBit(47))
                d['bit_047_data'] = profile.to_dict()
                profile = FixLength(self.service.INVOICE_PROFILE2)
                profile.set_raw(iso.getBit(48))
                d['bit_048_data'] = profile.to_dict()
            except BitNotSet:
                pass
        else:
            profile = FixLength(self.service.INVOICE_PROFILE)
            profile.set_raw(iso.getBit(62))
            d['bits_data'] = {62: profile.to_dict()}
        return d

    def get_last_time(self):  # Override
        return str(self.last_pay.id)

    def run_payment(self):  # Override
        self.last_pay = None
        self.offset = 0
        if self.option.update_from_id is None:
            self.last = self.get_last_id(self.conf_name)
            self.last_id = self.last.as_int()
        else:
            self.last = None
            self.last_id = self.option.update_from_id - 1
        self.count = self.get_count()
        self.start_time = time()
        while True:
            found = self.update_from_date()
            if not found:
                break
            if self.last_pay and self.last:
                self.update_last()


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