Commit 47a8792a by Owo Sugiana

Memahami BPHTB JSON

1 parent 37b1dab5
2.1 2022-09-01
--------------
- Memahami BPHTB JSON (Tangsel - PT POS)
2.0 2022-08-02
--------------
- Perbedaan utama dari versi 0.x adalah kini berangkat dari tabel aslinya dan
......
......@@ -41,6 +41,7 @@ from .common import (
init_db as base_init_db,
one_day,
InvalidSource,
BANK_NAMES,
)
......@@ -157,6 +158,9 @@ class App(BaseApp):
row = q.first()
if not row:
return
if row.iso_request[0] == '{':
channel = BANK_NAMES[str(row.bank_id)]
return '0000', channel, None, None
iso = get_iso(row.iso_request, Doc, self.option.debug)
info = get_channel_info_by_iso(iso)
return info.get('bit_018', '0000'), info['channel'], iso.get_stan(), \
......
import sys
from sqlalchemy import (
Column,
Integer,
DateTime,
String,
Date,
ForeignKey,
)
import transaction
import datetime
from opensipkd.waktu import (
dmyhms,
date_from_str,
)
from opensipkd.bphtb.models.default import (
Payment,
Invoice,
Perolehan,
Customer,
)
from iso8583_web.models.meta import Base as BaseConf
from opensipkd.iso8583.bjb.bphtb import Doc
from ..models import (
Base,
Bphtb,
)
from .common import (
BaseApp,
init_db as base_init_db,
BANK_NAMES,
)
def get_keys(iso):
return dict(
nomor_bayar=iso['no_tagihan'],
ntb=iso['transno'],
nama_bank=BANK_NAMES[iso['bankid']])
def get_filter(q):
return q.filter(IsoPayment.iso_request.like('{%'))
class IsoPayment(Base):
__tablename__ = 'bphtb_payment'
__table_args__ = dict(schema='bphtb')
id = Column(Integer, ForeignKey(Payment.id), primary_key=True)
tgl = Column(DateTime(timezone=True), nullable=False)
iso_request = Column(String(1024), nullable=False)
transmission = Column(DateTime(timezone=True), nullable=False)
settlement = Column(Date, nullable=False)
stan = Column(Integer, nullable=False)
invoice_id = Column(Integer, ForeignKey(Invoice.id), nullable=False)
invoice_no = Column(String(32), nullable=False)
ntb = Column(String(32), nullable=False)
ntp = Column(String(32), nullable=False, unique=True)
bank_id = Column(Integer)
channel_id = Column(Integer)
bank_ip = Column(String(15), nullable=False)
class IsoReversal(Base):
__tablename__ = 'bphtb_reversal'
__table_args__ = dict(schema='public')
id = Column(Integer, ForeignKey(IsoPayment.id), primary_key=True)
tgl = Column(DateTime(timezone=True), nullable=False)
iso_request = Column(String(1024), nullable=False)
class App(BaseApp):
iso_class = Doc
report_orm = Bphtb
iso_reversal_orm = IsoReversal
def __init__(self, argv):
super().__init__(argv)
if not self.pid:
return
self.base_q_inv = self.prod_session.query(
Invoice, Customer, Perolehan).filter(
Invoice.ppat_id == Customer.id,
Invoice.perolehan_id == Perolehan.id)
def update_last_id(self, last, value):
last.nilai = str(value)
with transaction.manager:
self.rpt_session.add(last)
def __warning_nol(self, s_tgl, d, row_pay):
msg = f'Tgl bayar {s_tgl}, Nomor bayar {d["nomor_bayar"]}, '\
f'NTB {d["ntb"]}, Channel {d["nama_bank"]}, '\
f'nilai Rp {row_pay.bayar} tidak disimpan'
self.log.warning(msg)
def __log_progress(self, s_tgl, d):
self.log.info(
f'Tgl bayar {s_tgl}, Nomor bayar {d["nomor_bayar"]}, '
f'NTB {d["ntb"]}, Channel {d["nama_bank"]}')
def __get_query_iso(self, last_id):
q_iso = self.prod_session.query(IsoPayment, Payment).filter(
IsoPayment.id == Payment.id,
IsoPayment.id > last_id)
q_iso = get_filter(q_iso)
return q_iso.order_by(IsoPayment.id)
def __create_data(self, row_iso, row_pay, iso, d):
q_inv = self.base_q_inv.filter(Invoice.id == row_pay.sspd_id)
inv, ppat, perolehan = q_inv.first()
return dict(
stan=row_iso.id, ntb=d['ntb'], tgl=row_iso.tgl,
jam=row_iso.tgl.time(), invoice_id=d['nomor_bayar'],
nop=row_pay.nop, wp_nama=row_pay.wp_nama,
wp_alamat=row_pay.wp_alamat, op_alamat=inv.op_alamat,
npop=row_pay.npop, bumi_luas=row_pay.bumi_luas,
bng_luas=row_pay.bng_luas, nilai_bphtb=row_pay.bayar,
jenis_perolehan=perolehan.nama, ppat=ppat.nama,
channel_id=int(iso['bankid']), channel_nama=d['nama_bank'])
def __run_payment(self):
last = self.get_last_id('bphtb json payment last id')
q_iso = self.__get_query_iso(last.as_int())
for row_iso, row_pay in q_iso:
iso = eval(row_iso.iso_request)
d = get_keys(iso)
if self.get_report(d['nomor_bayar'], d['ntb']):
continue
s_tgl = dmyhms(row_iso.tgl)
if not row_pay.bayar:
self.__warning_nol(s_tgl, d, row_pay)
self.update_last_id(last, str(row_iso.id))
continue
self.__log_progress(s_tgl, d)
data = self._create_data(row_iso, row_pay, iso, d)
rpt = Bphtb(**data)
last.nilai = str(row_iso.id)
with transaction.manager:
self.rpt_session.add(rpt)
self.rpt_session.add(last)
def __update_from_id(self):
q_iso = self.__get_query_iso(self.last_id)
found = False
for row_iso, row_pay in q_iso.limit(1000):
iso = eval(row_iso.iso_request)
d = get_keys(iso)
s_tgl = dmyhms(row_iso.tgl)
if not row_pay.bayar:
self.__warning_nol(s_tgl, d, row_pay)
continue
self.__log_progress(s_tgl, d)
data = self.__create_data(row_iso, row_pay, iso, d)
rpt = self.get_report(d['nomor_bayar'], d['ntb'])
if not rpt:
rpt = Bphtb()
rpt.from_dict(data)
with transaction.manager:
self.rpt_session.add(rpt)
found = True
self.last_id = row_iso.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 run_reversal(self): # Override
last = self.get_last_id('bphtb json reversal last date')
q = self.prod_session.query(self.iso_reversal_orm).filter(
self.iso_reversal_orm.iso_request.like('{%'),
self.iso_reversal_orm.tgl > last.as_datetime())
for row in q.order_by(self.iso_reversal_orm.tgl):
iso = eval(row.iso_request)
invoice_id = iso['bit_061']
ntb = iso['bit_037']
rpt = self.get_report(invoice_id, ntb)
if not rpt or rpt.tgl_batal:
continue
nama_bank = BANK_NAMES[iso['bit_032']]
rpt.tgl_batal = row.tgl
last.nilai = s_tgl = dmyhms(row.tgl)
self.log.info(
f'Tgl batal {s_tgl}, Nomor bayar {invoice_id}, '
f'NTB {ntb}, Channel {nama_bank}')
with transaction.manager:
self.rpt_session.add(rpt)
self.rpt_session.add(last)
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)
......@@ -7,10 +7,6 @@ from sqlalchemy import func
from sqlalchemy.exc import ProgrammingError
from opensipkd.string import FixLength
from opensipkd.waktu import dmyhms
from opensipkd.pad.models.default import (
Payment,
IsoPayment,
)
from iso8583_web.models.meta import Base as BaseConf
from opensipkd.iso8583.bjb.pad.structure import PAYMENT_CODE
from opensipkd.iso8583.bjb.pad.doc import Doc as BjbDoc
......@@ -76,6 +72,7 @@ class App(BaseApp):
return dmyhms(self.last_pay.sspdtgl)
def get_filter_query(self, q):
Payment = self.models.Payment
return q.filter(
Payment.sspdtgl >= self.tgl_awal,
Payment.sspdtgl < self.tgl_akhir + one_day)
......@@ -86,18 +83,18 @@ class App(BaseApp):
return q.scalar()
def get_payment_query(self): # Override
Payment = self.models.Payment
q = self.prod_session.query(Payment)
q = self.get_filter_query(q)
return q.order_by(Payment.sspdtgl)
def get_iso_v1(self, pay):
IsoPayment = self.models.IsoPayment
q = self.prod_session.query(IsoPayment).filter_by(id=pay.id)
row = q.first()
if not row:
return
if row.iso_request[0] == '{':
s = row.iso_request.replace('datetime.datetime', 'datetime')
d = eval(s)
channel = BANK_NAMES[str(row.bank_id)]
return '0000', channel, None, None, row.bank_id
Doc = BankHandlers[row.bank_id]
......
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!