Beispiel #1
0
ElementTree::ElementPtr stop_service(Session &session, ILogger &logger,
        const StringDict &params) {
    string transaction_eid = params.get("transaction_id", "");
    if (transaction_eid.size() < 4 || transaction_eid.size() > 64)
        throw ApiResult(mk_resp("bad_transaction"));
    Payment payment(EMPTY_DATAOBJ);
    try {
        payment = query<Payment>(session).for_update()
                .filter_by(Payment::c.trans_number == transaction_eid).one();
    }
    catch (const NoDataFound &) {
        throw ApiResult(mk_resp("bad_transaction"));
    }
    if (payment.payment_ts == Value() || payment.cancel_ts != Value())
        throw ApiResult(mk_resp("bad_transaction"));
    Order order = query<Order>(session).for_update()
            .filter_by(Order::c.id == payment.order->id).one();
    if (order.ticket_number != Value())
        throw ApiResult(mk_resp("bad_transaction"));
    int existing_cnt = order.receipts.size();
    ElementTree::ElementPtr resp = mk_resp("success");
    if (existing_cnt) {
        YB_ASSERT(existing_cnt == 1);
        resp->add_json("delta_amount", money2str(
                    order.receipts.begin()->amount));
        throw ApiResult(resp);
    }
    DateTime now_ts = now();
    if (now_ts >= order.paid_until_ts) {
        resp->add_json("delta_amount", money2str(Decimal(0)));
        throw ApiResult(resp);
    }
    int total_secs_left = (int)datetime_diff(now_ts, order.paid_until_ts) - 1;
    int duration_left = (total_secs_left / (15 * 60)) * 15; // rounded minutes
    Decimal price_per_minute = order.paid_amount / Decimal(datetime_diff(
                order.start_ts, order.paid_until_ts) / 60);
    Decimal delta_amount = (duration_left * price_per_minute).round(2);
    logger.debug("total_seconds_left=" + to_string(total_secs_left) +
            " duration_left=" + to_string(duration_left) +
            " price=" + money2str(price_per_minute) +
            " delta=" + money2str(delta_amount));
    create_account_receipt(session, order.user_eid, order, delta_amount);
    resp->add_json("delta_amount", money2str(delta_amount));
    return resp;
}
Beispiel #2
0
ElementTree::ElementPtr get_service_info(Session &session, ILogger &logger,
        const StringDict &params) {
    string service_descr_str = params["service_descr"];
    string user_eid = params.get("user_id", "");
    if (user_eid.empty())
        throw ApiResult(mk_resp("not_available", "invalid_user_id"));
    StringDict service_descr = json2dict(service_descr_str);
    logger.debug("service_descr: " + dict2str(service_descr));
    Product parking;
    try {
        string parking_name = service_descr["parking_id"];
        parking = query<Product>(session)
            .filter_by(Product::c.name == parking_name).one();
    }
    catch (const NoDataFound &) {
        throw ApiResult(mk_resp("not_available", "invalid_parking_id"));
    }
    Decimal price, hours;
    Order order(get_hours_and_price(session, logger,
                service_descr, parking, false, hours, price));
    ElementTree::ElementPtr resp = mk_resp("success");
    resp->add_json("price", money2str(price));
    ElementTree::ElementPtr info = resp->add_json_dict("info");
    info->add_json("available_places", parking.places_avail.value());
    if (!order.is_empty()) {
        info->add_json("start_ts",
                timestamp2str(datetime2timestamp(order.start_ts)));
        if (service_descr.has("user_ticket"))
            info->add_json("paid_duration",
                    Decimal(datetime_diff(order.start_ts,
                            order.paid_until_ts) / 60).round());
    }
    else {
        info->add_json("start_ts",
                timestamp2str(datetime2timestamp(now())));
    }
    info->add_json("duration", (hours * 60).round());
    info->add_json("balance", money2str(
            get_account_balance(session, user_eid)));
    throw ApiResult(resp);
}
Beispiel #3
0
ElementTree::ElementPtr create_reservation(Session &session, ILogger &logger,
        const StringDict &params) {
    string user_eid = params.get("user_id", "");
    if (user_eid.empty())
        throw ApiResult(mk_resp("not_available", "invalid_user_id"));
    StringDict service_descr = json2dict(params["service_descr"]);
    logger.debug("service_descr: " + dict2str(service_descr));
    Product parking(EMPTY_DATAOBJ);
    try {
        string parking_name = service_descr["parking_id"];
        parking = query<Product>(session).for_update()
            .filter_by(Product::c.name == parking_name).one();
    }
    catch (const NoDataFound &) {
        throw ApiResult(mk_resp("not_available", "invalid_parking_id"));
    }
    string plate_number = service_descr.get("registration_plate", "");
    if (plate_number.empty())
        throw ApiResult(mk_resp("not_available", "invalid_registration_plate"));
    Decimal price0 = Decimal(params["price"]);
    Decimal pay_from_balance = Decimal(params["pay_from_balance"]);
    if (pay_from_balance < Decimal(0) || pay_from_balance > price0)
        throw ApiResult(mk_resp("wrong_price"));
    string transaction_eid = params.get("transaction_id", "");
    if (transaction_eid.size() < 4 || transaction_eid.size() > 64)
        throw ApiResult(mk_resp("bad_transaction"));
    try {
        Payment payment = query<Payment>(session).for_update()
                .filter_by(Payment::c.trans_number == transaction_eid).one();
        if (payment.amount == price0 && *payment.order->product == parking)
            throw ApiResult(mk_resp("success"));
        throw ApiResult(mk_resp("wrong_price"));
    }
    catch (const NoDataFound &) {}
    Decimal price, hours;
    Order order(get_hours_and_price(
            session, logger, service_descr, parking, true, hours, price));
    if (price != price0)
        throw ApiResult(mk_resp("wrong_price"));
    if (parking.places_avail == 0)
        throw ApiResult(mk_resp("not_available"));
    if (order.is_empty()) {
        order = Order(session);
        order.product = Product::Holder(parking);
        order.user_eid = user_eid;
        order.plate_number = plate_number;
        order.start_ts = now();
        order.paid_until_ts = order.start_ts;
        order.price = parking.price;
    }
    Payment payment;
    payment.trans_number = transaction_eid;
    payment.hours = hours;
    payment.order = Order::Holder(order);
    payment.amount = price - pay_from_balance;
    payment.ts = order.start_ts;
    payment.save(session);
    if (pay_from_balance > 0) {
        create_account_consume(session, user_eid, payment,
                pay_from_balance, true);
    }
    ElementTree::ElementPtr resp = mk_resp("success");
    resp->add_json("price", money2str(price));
    ElementTree::ElementPtr info = resp->add_json_dict("info");
    info->add_json("start_ts",
            timestamp2str(datetime2timestamp(order.start_ts)));
    info->add_json("duration", (hours * 60).round());
    if (service_descr.has("user_ticket"))
        info->add_json("paid_duration", Decimal(0));
    return resp;
}