__init__.py 5.61 KB
from pyramid.response import Response
from pyramid.view import view_config
from deform import ValidationFailure
from sqlalchemy import create_engine
from sqlalchemy.orm import (
    sessionmaker,
    scoped_session,
    )
from zope.sqlalchemy import register
from iso8583_web.read_conf import web_path_conf
from iso8583_web.scripts.logger import (
    log_web_info,
    log_web_error,
    )
from opensipkd.iso8583.bjb.pbb.agratek.models import Rpc
from pyramid_linkaja.responses import (
    InquiryResponse,
    get_trx_date,
    get_method,
    is_inquiry,
    is_payment,
    )
from pyramid_linkaja.exceptions import (
    BaseError,
    NeedPostError,
    InternalError,
    BillRefNotFound,
    )
from pyramid_linkaja.structure import RENDERER
from pyramid_linkaja.form import get_form
from .. import (
    WebJob as BaseWebJob,
    View as BaseView,
    )


def get_web_conf(request):
    return web_path_conf.get(request.path)


def log_prefix(request):
    web_conf = get_web_conf(request)
    name = web_conf['name']
    return f'{request.client_addr} {name} {id(request)}'


def log_receive(self, msg, error=False):
    msg = '{} {} {}'.format(self.log_prefix(), 'Receive', msg)
    if error:
        log_web_error(msg)
    else:
        log_web_info(msg)


@view_config(context=BaseError)
def view_exception(exc, request):
    r = InquiryResponse()
    r['Response Code'] = exc.code
    r['Notification Message'] = exc.message
    prefix = log_prefix(request)
    msg = f'{prefix} Send {r}'
    log_web_error(msg)
    response = Response(str(r))
    response.status_int = 200
    return response


def pyramid_init(pyramid_config, h2h_conf, route_name):
    pyramid_config.add_renderer(RENDERER, 'pyramid_linkaja.renderer.Renderer')
    path = h2h_conf['route_path']
    pyramid_config.add_route(route_name, path)
    log_web_info(f'LinkAja route path {path}')
    pool_size = int(h2h_conf.get('db_pool_size', 50))
    max_overflow = int(h2h_conf.get('db_max_overflow', 100))
    engine = create_engine(
        h2h_conf['db_url'], pool_size=pool_size, max_overflow=max_overflow)
    session_factory = sessionmaker(bind=engine)
    h2h_conf['db_session'] = scoped_session(session_factory)
    register(h2h_conf['db_session'])


class WebJob(BaseWebJob):
    def timeout_error(self):  # override
        return TimeoutError()


class View(BaseView):
    def get_web_job_cls(self):  # Override
        return WebJob

    def not_found_error(self, hostname):  # Override
        return HostError(hostname)

    def not_running_error(self, hostname):  # Override
        msg = f'Host {hostname} belum terhubung'
        return InternalError(msg, 'Sedang offline')

    def get_web_conf(self):
        return get_web_conf(self.request)

    def get_inquiry(self, data):
        DBSession = self.get_db_session() 
        bill_ref = int(data['bill_ref'])
        q = DBSession.query(Rpc).filter_by(id=bill_ref)
        return q.first()

    def get_payment(self, data):
        DBSession = self.get_db_session()
        bill_ref = int(data['bill_ref'])
        q = DBSession.query(Rpc).filter_by(
                inquiry_id=bill_ref, trx_type='022')
        q = q.order_by(Rpc.id.desc())
        return q.first()

    def create_db_log(self, data, inq, pay):
        DBSession = self.get_db_session()
        web_conf = self.get_web_conf()
        row = Rpc(
            ip=self.request.client_addr,
            conf_name=web_conf['name'],
            merchant=data['merchant'],
            terminal=data['terminal'],
            trx_type=data['trx_type'],
            msisdn=data['msisdn'],
            acc_no=data['acc_no'])
        row.trx_date = get_trx_date(data),
        if data.get('msg'):
            row.msg = data['msg']
        if data.get('amount'):
            row.amount = int(data['amount'])
        if not is_inquiry(data):
            row.inquiry_id = inq and inq.id or pay.inquiry_id
            row.ntb = data['trx_id']
        return row

    def view(self):
        self.validate()
        if not self.request.POST:
            self.log_receive(f'GET {self.request.GET}')
            raise NeedPostError()
        items = self.request.POST.items()
        self.log_receive(f'POST {dict(items)}')
        items = self.request.POST.items()
        form = get_form()
        try:
            c = form.validate(items)
        except ValidationFailure as e:
            d = e.error.asdict()
            for field, err in d.items():
                msg = f'{field} {err}'
                break
            raise InternalError(msg)
        data = dict(c)
        return self.get_response(data)

    def get_db_session(self):  # Override, please
        pass

    def get_invoice_id(self, data):
        return data['acc_no']

    def get_invoice_id_from_inquiry(self, inq):
        return inq.acc_no

    def prepare_response(self, data):
        inq = pay = None
        if is_inquiry(data):
            invoice_id = self.get_invoice_id(data)
            p = dict(invoice_id=invoice_id)
        else:
            p = dict(amount=data['amount'], ntb=data['trx_id'])
            if is_payment(data):
                inq = self.get_inquiry(data)
                if not inq:
                    raise BillRefNotFound()
                p['invoice_id'] = self.get_invoice_id_from_inquiry(inq) 
            else:
                pay = self.get_payment(data)
                if not pay:
                    raise BillRefNotFound()
                inq = self.get_inquiry(data)
                p['invoice_id'] = self.get_invoice_id_from_inquiry(inq) 
                p['stan'] = pay.stan
        p['db_session'] = self.get_db_session()
        return p, inq, pay

    def get_response(self, data):  # Override, please
        pass