vendor.py 12 KB
"""
Module proses:
Save
Invoice To Vendor
Invoice To Customer
"""

import re
from datetime import datetime
from importlib import import_module

import colander
import xmltodict
from deform import widget, Form, ValidationFailure
from opensipkd.base.tools.api import JsonRpcParameterNotFound
from opensipkd.pasar.models import PartnerLog
from pyramid.httpexceptions import HTTPFound
from pyramid.renderers import render_to_response
from pyramid.view import view_config
import json

from . import BaseView  # , save_file_upload
from ..models import (DBSession, flush_row, Partner, PartnerProduk)
from ..models import (Produk, ProdukCategory)
from ..tools import (btn_next, date_from_str, get_settings, btn_reset,
                     btn_inquiry, btn_advice, btn_payment, get_random_number)


def vendor():
    return DBSession.query(Partner.id, Partner.nama)\
        .filter(Partner.is_vendor == 1).all()

def customer():
    return DBSession.query(Partner.id, Partner.nama)\
        .filter(Partner.is_customer == 1).all()

def produk():
    return DBSession.query(Produk.id, Produk.nama)\
        .join(ProdukCategory, Produk.kategori_id==ProdukCategory.id)\
        .filter(ProdukCategory.kode.in_(['e-pulsa', 'e-voucher', 'e-payment'])).all()


def build_request(typ, values):
    produk_id = values['produk_id']
    vendor_id = values['vendor_id']
    vendor_product = PartnerProduk.query() \
        .join(Produk, PartnerProduk.produk_id==Produk.id)\
        .filter(PartnerProduk.partner_id == vendor_id,
                PartnerProduk.produk_id == produk_id).first()
    if not vendor_product:
        return dict(error='Data Tidak Ditemukan')

    modules = import_module('.'+vendor_product.modules, 'agratek.api.merchant.views')
    cls_module = modules.Vendor(PartnerProduk.kode, values['destination'],
                                values['trx_id'])
    if typ=='inquiry':
        return cls_module.inquiry()

    elif typ=='payment':
        return cls_module.payment()
    elif typ == 'advice':
        return hasattr(cls_module, typ) and cls_module.advice()
    elif typ == 'info':
        return hasattr(cls_module, typ) and cls_module.info()
    else:
        return dict(error='Function %s tidak ditemukan' % typ)


@colander.deferred
def deferred_vendor(node, kw):
    values = kw.get('vendor', [])
    return widget.SelectWidget(values=values)


@colander.deferred
def deferred_customer(node, kw):
    values = kw.get('customer', [])
    return widget.SelectWidget(values=values)


@colander.deferred
def deferred_produk(node, kw):
    values = kw.get('produk', [])
    return widget.SelectWidget(values=values)


class AddSchema(colander.Schema):
    produk_id = colander.SchemaNode(
        colander.Integer(), title='Produk',
        oid="produk_id", widget=deferred_produk)

    destination = colander.SchemaNode(
        colander.Integer(), title='No.Tujuan/ID Pelanggan',
        oid="destination", widget=widget.TextInputWidget())

    vendor_id = colander.SchemaNode(
        colander.Integer(), title='Vendor',
        oid="vendor_id", widget=deferred_vendor)
    trx_id = colander.SchemaNode(
        colander.Integer(), title='TRX ID',
        missing=colander.drop,
        oid="trx_id",
        # widget=widget.HiddenWidget()
    )

    result = colander.SchemaNode(
        colander.String(), title='Result',
        missing=colander.drop,
        oid="result",
        widget=widget.TextAreaWidget(rows=10)
    )

class EditSchema(AddSchema):

    id = colander.SchemaNode(
        colander.Integer(), title='ID',
        missing=colander.drop,
        oid="id", widget=widget.HiddenWidget())


def form_validator(form, value):
    pass


def get_form(request, class_form, buttons=None, row=None):
    schema = class_form(validator=form_validator)
    schema = schema.bind(vendor=vendor(),
                         produk=produk())
    schema.request = request
    if row:
        schema.deserialize(row)
    if not buttons:
        buttons = (btn_inquiry, btn_reset)
    return Form(schema, buttons=buttons)


def upload_form(request, values, form):
    docs = PartnerDocs.query() \
        .filter(PartnerDocs.partner_id == values['partner_id'])
    uploads = []
    preview_url = "{host}/simkel/api_download?partner_id={partner_id}&jdoc_id={jdoc_id}"
    for doc in docs:
        uploads.append(dict(jdoc_id=doc.jdoc_id,
                            upload=dict(filename=doc.doc_name,
                                        uid=doc.id, )))

    values['uploads'] = uploads
    form = form.render(values)
    return render_to_response('templates/form-upload.pt', dict(form=form),
                              request=request)


def route_list(request):
    return HTTPFound(location=request.route_url('simkel-permohonan'))


def save(values, row):
    if not row:
        row = Penduduk()
        kode = re.sub("\D", "", values["kode"])
        values['kode'] = kode
        values['is_vendor'] = 0
        values['is_customer'] = 1
        row.create_uid = values['uid']
        row.created = datetime.now()
    else:
        row.update_uid = values['uid']
        row.updated = datetime.now()

    row.from_dict(values)
    flush(row)
    return row


def save_permohonan(values, partner, row=None):
    if not row:
        row = Permohonan()
        row.partner_id = partner.id
        row.jenis_id = values['jenis_id']
        row.tgl_permohonan = datetime.now()
        row.create_uid = values['uid']
        row.created = datetime.now()
    else:
        row.update_uid = values['uid']
        row.updated = datetime.now()

    flush(row)
    return row


def save_request(request, values, row=None):
    values['tgl_lahir'] = date_from_str(values['tgl_lahir'])
    values['uid'] = request.user.id
    row = save(values, row)
    row_permohonan = Permohonan.query(). \
        filter(Permohonan.partner_id == row.id,
               Permohonan.status == 0,
               Permohonan.jenis_id == values['jenis_id']). \
        first()
    if not row_permohonan:
        row_permohonan = save_permohonan(values, row)

    request.session.flash('Data %s Berhasil disimpan' % values['nama'])
    return row_permohonan


form_params_edit = dict(scripts="""
$(document).ready(function(){
    $(".tanggal").datepicker({format:"dd-mm-yyyy"});
    $(".tanggal").attr("readonly", true);
    $("#trx_id").attr("readonly", true);
    $("#result").attr("readonly", true);
    

});
""")

form_params_view = dict(scripts="""
$(document).ready(function(){
    $("#nip_penerima, #nopel").attr("readonly", true);
    $("#trx_id").attr("readonly", true);
    $("#result").attr("readonly", true);
});
""")


def query_id(request):
    id = request.matchdict['id']
    return ApInvoice.query_id(id)


class ViewHome(BaseView):
    @view_config(route_name='api-vendor-doc',
                 permission="api-vendor-doc",
                 renderer='templates/vendor_doc.pt')
    def view_merchant_doc(self):
        return dict()

    @view_config(route_name='api-vendor-add',
                 permission="api-vendor-add",
                 renderer='templates/form.pt')
    def view_home(self):
        request = self.req
        session = self.ses
        form = get_form(request, AddSchema, (btn_inquiry, btn_payment, btn_advice, btn_next))
        # form_params = dict(scripts=None)
        settings = get_settings()
        if request.POST:
            if 'inquiry' in request.POST:
                controls = request.POST.items()
                try:
                    c = form.validate(controls)
                except ValidationFailure as e:
                    form.set_appstruct(e.cstruct)
                    return dict(form=form, params=form_params_edit)

                values = dict(c.items())
                if 'trx_id' not in values or not values['trx_id']:
                    values['trx_id'] = get_random_number(10)
                result = build_request('inquiry', values)
                if not result:
                    session.flash('Data Tidak Ditemukan', 'error')

                if result and 'error' in result:
                    session.flash(result['error'], 'error')
                if result:
                    values['result'] = json.dumps(result, indent=4)

                form.render(values)
                return dict(form=form, params=form_params_view)

        return dict(form=form, params=form_params_edit)

class VendorClass(object):
    def __init__(self, cid, vendor_id):
        """
        :param cid:
            merupakan customer id seperti MSN dan atu id pelanggaan
        """
        self.settings = get_settings()
        self.cid = cid
        self.vendor_id = vendor_id
        self.trx_id = None
        self.response = None
        self.request = None

    def save_log(self, typ):
        row = PartnerLog()
        row.partner_id = self.vendor_id
        row.trx_type = typ
        row.ref_id = self.trx_id
        row.log = dict(request=self.request,
                       response=self.response)
        flush_row(row)

    def get_product(self):
        pass

    def inquiry(self):
        pass

    def payment(self):
        pass

@view_config(route_name='api-vendor-notify', renderer='json')
def api_vendor_notify(request):
    """
    :param request:
    :return:

    ODEO will notify to affiliate if item has been successfully purchased or
    refunded.You can use any active url/IP you have to be registered, but ODEO
    suggests you to use a secure HTTPS. Please use "signature" parameter to
    validate any notification that come from ODEO. Compare the signature hash
    by generate the same hash by this following
    format:
    sha256({order_id} + {MID} + {SECRET_KEY} + {status}) [COMPLETED/REFUNDED]
    sha256({MID} + {SECRET_KEY} + {status}) [BROADCAST_NEW_PRICE]
    Also from "message" parameter, you can get data such as newest price of the
    product, and your current balance. Please refer to our apps to see all of
    message examples you can get from notify.Responded Status

    status	            reason
    COMPLETED	        item has successfully purchased
    REFUNDED	        purchase canceled, refunded to oCash balance
    BROADCAST_NEW_PRICE	there is new price for specific item
    """
    vendor_nm = request.matchdict['name']
    partner = Partner.query_kode(vendor_nm).first()
    if partner:
        row = PartnerLog()
        if vendor_nm=='odeoo':
            env = request.environ
            if not 'HTTP_SIGNATURE' in env:
                return JsonRpcParameterNotFound(message='SIGNATURE not found')

            row.log=env['HTTP_SIGNATURE']
        row.partner_id = partner.id
        flush_row(row)

# from pyramid_xmlrpc import XMLRPCView, xmlrpc_response


@view_config(route_name='api-vendor-test', renderer="string")
def vendor_test(request):
    params = request.params
    vendor = request.matchdict['vendor']
    result = dict(a=1)
    request.response.content_type = "text / xml"
    if vendor == 'vsi':
        cid=params['cid']
        dt=params['dt']
        hc=params['hc']
        modul=params['modul']
        command=params['command']
        trxid=params['trxid']
        resp=params['resp']

        if modul=="ISI":
            tujuan = params['tujuan']
            voucherid = params['voucherid']
            if command == "INQ":
                result = dict(root=dict(status="SUCCESS",
                         rc="0000",
                         rcm="0000",
                         text="[0] Cek Tagihan Sukses ke: 628523123789 ",
                         refnum="DB3DC0A2539419F8C50000000000000",
                         voucherid=voucherid,
                         destnum=tujuan,
                         nominal=5000
                    ))
            elif command == "PAY":
                result = dict(root=dict(
                    status="SUCCESS",
                    rc="0000",
                    rcm="0000",
                    text="[0] Cek Tagihan Sukses ke: 628523123789 ",
                    refnum="DB3DC0A2539419F8C50000000000000",
                    voucherid=voucherid,
                    destnum=tujuan,
                    nominal=5000
                ))
            elif command == "ADV":
                pass

    xml = xmltodict.unparse(result)
    return xml