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 2.0 2022-08-02
-------------- --------------
- Perbedaan utama dari versi 0.x adalah kini berangkat dari tabel aslinya dan - Perbedaan utama dari versi 0.x adalah kini berangkat dari tabel aslinya dan
......
...@@ -41,6 +41,7 @@ from .common import ( ...@@ -41,6 +41,7 @@ from .common import (
init_db as base_init_db, init_db as base_init_db,
one_day, one_day,
InvalidSource, InvalidSource,
BANK_NAMES,
) )
...@@ -157,6 +158,9 @@ class App(BaseApp): ...@@ -157,6 +158,9 @@ class App(BaseApp):
row = q.first() row = q.first()
if not row: if not row:
return 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) iso = get_iso(row.iso_request, Doc, self.option.debug)
info = get_channel_info_by_iso(iso) info = get_channel_info_by_iso(iso)
return info.get('bit_018', '0000'), info['channel'], iso.get_stan(), \ 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 ...@@ -7,10 +7,6 @@ from sqlalchemy import func
from sqlalchemy.exc import ProgrammingError from sqlalchemy.exc import ProgrammingError
from opensipkd.string import FixLength from opensipkd.string import FixLength
from opensipkd.waktu import dmyhms from opensipkd.waktu import dmyhms
from opensipkd.pad.models.default import (
Payment,
IsoPayment,
)
from iso8583_web.models.meta import Base as BaseConf from iso8583_web.models.meta import Base as BaseConf
from opensipkd.iso8583.bjb.pad.structure import PAYMENT_CODE from opensipkd.iso8583.bjb.pad.structure import PAYMENT_CODE
from opensipkd.iso8583.bjb.pad.doc import Doc as BjbDoc from opensipkd.iso8583.bjb.pad.doc import Doc as BjbDoc
...@@ -76,6 +72,7 @@ class App(BaseApp): ...@@ -76,6 +72,7 @@ class App(BaseApp):
return dmyhms(self.last_pay.sspdtgl) return dmyhms(self.last_pay.sspdtgl)
def get_filter_query(self, q): def get_filter_query(self, q):
Payment = self.models.Payment
return q.filter( return q.filter(
Payment.sspdtgl >= self.tgl_awal, Payment.sspdtgl >= self.tgl_awal,
Payment.sspdtgl < self.tgl_akhir + one_day) Payment.sspdtgl < self.tgl_akhir + one_day)
...@@ -86,18 +83,18 @@ class App(BaseApp): ...@@ -86,18 +83,18 @@ class App(BaseApp):
return q.scalar() return q.scalar()
def get_payment_query(self): # Override def get_payment_query(self): # Override
Payment = self.models.Payment
q = self.prod_session.query(Payment) q = self.prod_session.query(Payment)
q = self.get_filter_query(q) q = self.get_filter_query(q)
return q.order_by(Payment.sspdtgl) return q.order_by(Payment.sspdtgl)
def get_iso_v1(self, pay): def get_iso_v1(self, pay):
IsoPayment = self.models.IsoPayment
q = self.prod_session.query(IsoPayment).filter_by(id=pay.id) q = self.prod_session.query(IsoPayment).filter_by(id=pay.id)
row = q.first() row = q.first()
if not row: if not row:
return return
if row.iso_request[0] == '{': if row.iso_request[0] == '{':
s = row.iso_request.replace('datetime.datetime', 'datetime')
d = eval(s)
channel = BANK_NAMES[str(row.bank_id)] channel = BANK_NAMES[str(row.bank_id)]
return '0000', channel, None, None, row.bank_id return '0000', channel, None, None, row.bank_id
Doc = BankHandlers[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!