Okay
  Public Ticket #3419467
Appointments in Packages are bookable without payment
Closed

Comments

  • Robert Ehni started the conversation

    When a customer buys a package with the default payment method he is able to immediately book all appointments within the package without paying at all. 

    Booking appointments of the package should be blocked until the payment status is set to "payed".

    If there is any option for it I am sorry as I haven't found it yet.

  •  2,572
    Aleksandar replied

    Hello Robert.

    When you're creating a package, you're defining its price. Based on the payment method you've configured in Settings/Payments, the customers will either need to pay online or on-site. If it's set to on-site, the package is automatically booked when the customer is done with the booking process.

    There's no way that you can allow them to book a service or a package without paying, and then block them from booking until they pay. It is not possible.

    The best option, in this case, is to enable online payments and prevent customers from booking before they pay automatically, online.

    Another option is to manually cancel all appointments and the package if they don't pay in time.

    Kind Regards, 

    Aleksandar Vuković
    [email protected]

    Rate my support

    wpDataTables: FAQ | Facebook | Twitter | InstagramFront-end and back-end demo | Docs

    Amelia: FAQ | Facebook | Twitter | InstagramAmelia demo sites | Docs | Discord Community

    You can try wpDataTables add-ons before purchasing on these sandbox sites:

    Powerful Filters | Gravity Forms Integration for wpDataTables | Formidable Forms Integration for wpDataTables | Master-Detail Tables

  • Robert Ehni replied

    ... this is quite dissappointing.

    > There's no way that you can allow them to book a service or a package without paying, and then block them from booking until they pay. It is not possible.

    Why is this possible with online payment options but not with the built in option?

    > The best option, in this case, is to enable online payments and prevent customers from booking before they pay automatically, online.

    I have a client which is not using only payments and only "old school" bank transfer (invoice). The German translation actually is "Rechnung" (=invoice) and not "Vor Ort" (=On site) like you state in your documentation.

    > Another option is to manually cancel all appointments and the package if they don't pay in time.

    This is not really an option if you are honest. Because if the appointment is cancelled the customer can just rebook a new one and spam the client with appointments. Would you consider this as an option yourself? :-(


    Can you please add a second option "invoice" which blocks appointments from being booked until the bill is marked as paid in the finances?

  •  2,572
    Aleksandar replied

    Hello again Robert.

    Amelia doesn't prevent anyone from booking appointments. If you add Amelia to your website, and you allow people to see that page, everyone can book an appointment.

    There's no "Invoice" option in Amelia but even if there was, there'd be no way to stop the booking unless a payment's been made. Not even WooCommerce (a leader in the online shops industry) has this limitation. Let's take WooCommerce as an example - if you configure "Cash on Delivery", which is similar to the "On-Site" payment option, it will still accept the order. The only way not to accept an order without paying is to configure online payments.

    Can you explain how this would work? From my point of view - if I, as a customer, want to book an appointment with you, and I go through the booking procedure only to see that I'm not allowed to pay online, but I can't complete my booking without paying via invoice/bank transfer/personal visit, I'd give up. I'm just sharing my point of view, so don't get me wrong. I'd like to understand the approach and the logic in your client's use case.

    If you were to use the aforementioned WooCommerce and configure "Bank Transfer" as a payment method, you could configure rules in Amelia's settings, so when a booking is made, the appointment is set to "Pending" until it's paid. However, even through WooCommerce, a bank transfer or "cash on delivery" transactions would all have to be manually changed from "Processing" or "On Hold" to "Paid", so you'd be back to manually doing stuff. It's just that you'd be doing it manually in WooCommerce instead of Amelia.

    Kind Regards, 

    Aleksandar Vuković
    [email protected]

    Rate my support

    wpDataTables: FAQ | Facebook | Twitter | InstagramFront-end and back-end demo | Docs

    Amelia: FAQ | Facebook | Twitter | InstagramAmelia demo sites | Docs | Discord Community

    You can try wpDataTables add-ons before purchasing on these sandbox sites:

    Powerful Filters | Gravity Forms Integration for wpDataTables | Formidable Forms Integration for wpDataTables | Master-Detail Tables

  • Robert Ehni replied

    Hi Aleksandar,

    thanks for the quick reply.

    > There's no "Invoice" option in Amelia [...]

    I think you need to check your German translation. As the default payment option in German is "Rechnung" (="invoice") and not "Zahlung vor Ort" (="on-site"). So in fact, even if not intended from your side, there is currently an invoice option displayed. Or did I configure this manually somewhere?

    > Can you explain how this would work? 

    Sure, here's the use case:

    My client offers trainings and he offers packages for these trainings (e.g. packages containing 5/10/15 training hours with discount).

    He wants the customers to be able to book a package and pay via bank transfer. 

    The customer books the package and receives the payment information upon completion of the package booking.

    He sees the package in his frontend customer panel but is not able to book appointments with this package as it's not paid yet.

    Once he transfers the money and my client sets the booking to "paid" the client is able to book appointments with the package.

    Although this might be an outdated process (manual changing of orders to paid) this is a valid use case and is currently not covered by your plugin sadly.

    > However, even through WooCommerce, a bank transfer or "cash on delivery" transactions would all have to be manually changed from "Processing" or "On Hold" to "Paid", so you'd be back to manually doing stuff. It's just that you'd be doing it manually in WooCommerce instead of Amelia.

    Yes. I am aware of this manual process and it is indeed my clients requirement.


    Can you understand the use case I am trying to implement here? How can this be achieved with Amelia?

    From my point of view it looks like it should be possible to block an appointment booking within a package when the payment status is not set to "paid" (of course I have no insights into the Amelia software architecture but it looks like all information are available in the frontend like package, available appointments and in the backend the package is linked to the invoice so this information can be combined to achieve the use case).

  •  2,572
    Aleksandar replied

    Hey Robert.

    Whoever did the translation for German did it incorrectly. I suppose it was to adjust for their use case. We've modified it, so it will be "Zahlung vor Ort" in our next update.

    I can understand the use case now, thanks for explaining.

    The fact, currently, is that booking appointments within a package can't be blocked until it's set to "Paid". I will forward it as a suggestion to our developers in the hope they'll develop this functionality in the future, but there weren't similar requests in the past (that I know of), so I doubt it will be a priority.

    Using WooCommerce's "Bank Transfer" option and configuring rules for appointment and payment status in Amelia is currently the only similar option, so appointments come in as Pending, but I understand if that's not enough for your client.

    Unfortunately, I'm not able to promise anything regarding this even though it's much clearer now. I can only try and emphasize the need for this to our management and hope they'll develop this functionality in the future.

    Kind Regards, 

    Aleksandar Vuković
    [email protected]

    Rate my support

    wpDataTables: FAQ | Facebook | Twitter | InstagramFront-end and back-end demo | Docs

    Amelia: FAQ | Facebook | Twitter | InstagramAmelia demo sites | Docs | Discord Community

    You can try wpDataTables add-ons before purchasing on these sandbox sites:

    Powerful Filters | Gravity Forms Integration for wpDataTables | Formidable Forms Integration for wpDataTables | Master-Detail Tables

  • Robert Ehni replied

    Hi Aleksandar,

    > Whoever did the translation for German did it incorrectly. I suppose it was to adjust for their use case. We've modified it, so it will be "Zahlung vor Ort" in our next update.

    Thanks for updating the translation!

    > I can understand the use case now, thanks for explaining.

    Thanks for taking the time to understand my use case.

    > I will forward it as a suggestion to our developers in the hope they'll develop this functionality in the future, but there weren't similar requests in the past (that I know of), so I doubt it will be a priority.

    I saw that all information is already available at the frontend so maybe just an option in the backend which then enables a frontend code to check for the payment status could be a solution to my use case.

    - "wp-admin/admin-ajax.php?action=wpamelia_api&call=/entities&types=employees,categories,locations,custom_fields,packages,lessonSpace_spaces,resources" 

    → fetches all existing entities (including packages)

    - "/wp-admin/admin-ajax.php?action=wpamelia_api&call=/appointments&activePackages=0&source=cabinet-customer&timeZone=%2B02:00" 

    → fetches all packages for the user including their payment information ("pending", "paid")

    However when I looked into the Amelia frontend code to check if I can provide a temporary workaround or implementation by myself I saw that all the frontend code is obfuscated and minified.

    I'd be very happy to see this small feature implemented soon as it is blocking a client currently and it seems like all pieces of information are available and "only" the logic to block bookings is missing.

    Best

    Robert

  • Robert Ehni replied

    I actually implemented a very quick & dirty solution (which will break on the slightest API/HTML changes but for now it works).

    // javascript snippet which is loaded on the page which contains the frontend customer panel

    let pendingPackages = [];
    let entities = null;

    function findSpanByText(text) {
        const spans = document.querySelectorAll("span");
        for (const span of spans) {
            if (span.textContent.trim() === text) {
                return span;
            }
        }
        return null;
    }

    function getPendingPackages(data) {
        const availablePackageBookings = data.data.availablePackageBookings;
        for (const packageBooking of availablePackageBookings) {
            const packages = packageBooking.packages;
            for (const pkg of packages) {
                const services = pkg.services;
                for (const service of services) {
                    const bookings = service.bookings;
                    for (const booking of bookings) {
                        const payments = booking.payments;
                        for (const payment of payments) {
                            if (payment.status === "pending") {
                                pkg.package = getPackageById(pkg.packageId);
                                pendingPackages.push(pkg);
                                updatePendingPackageElement(pkg);
                                break;
                            }
                        }
                    }
                }
            }
        }

        return pendingPackages;
    }

    function updatePendingPackageElement(pkg) {
      const remainingBookings = pkg.services[0].bookings[0].count;
      const spanWithText = findSpanByText(
        remainingBookings + " verbleibende Termin-Slots für Buchung"
      );

      if (spanWithText) {
        spanWithText.title =
          "Buchungen für dieses Paket sind erst verfügbar sobald die Zahlung abgeschlossen wurde";
        spanWithText.innerHTML = "Dieses Paket ist noch nicht bezahlt.";
        const clonedElement = spanWithText.parentNode.cloneNode(true);
        spanWithText.parentNode.parentNode.replaceChild(clonedElement, spanWithText.parentNode);
      } else {
        console.log("Span not found!!");
      }
    }

    function getPackageById(packageId) {
        const packages = entities.data.packages;
        return packages.find((pkg) => pkg.id === packageId);
    }

    document.addEventListener("DOMContentLoaded", () => {
        var originalOpen = XMLHttpRequest.prototype.open;
        XMLHttpRequest.prototype.open = function (method, url) {
            this.addEventListener("load", () => {
                const packagesAjaxCall =
                    "wp-admin/admin-ajax.php?action=wpamelia_api&call=/appointments&activePackages=0";
                const entitiesAjaxCall =
                    "wp-admin/admin-ajax.php?action=wpamelia_api&call=/entities&types=employees,categories,locations,custom_fields,packages,lessonSpace_spaces,resources";

                const packagesCallMatches = url.includes(packagesAjaxCall);
                const entitiesCallMatches = url.includes(entitiesAjaxCall);

                const statusCodeIs200 = this.status === 200;

                if (packagesCallMatches && statusCodeIs200) {
                    const data = JSON.parse(this.response);
                    pendingPackages = getPendingPackages(data);
                }

                if (entitiesCallMatches && statusCodeIs200) {
                    entities = JSON.parse(this.response);
                }
            });
            originalOpen.apply(this, arguments);
        };
    });

  •  2,572
    Aleksandar replied

    Thank you for providing us with this JS, Robert.

    I forwarded the ticket to our developers, so they can review it, and see if there's a way to implement your suggestion in the future.

    I'll get back to you as soon as I hear from them.

    Kind Regards, 

    Aleksandar Vuković
    [email protected]

    Rate my support

    wpDataTables: FAQ | Facebook | Twitter | InstagramFront-end and back-end demo | Docs

    Amelia: FAQ | Facebook | Twitter | InstagramAmelia demo sites | Docs | Discord Community

    You can try wpDataTables add-ons before purchasing on these sandbox sites:

    Powerful Filters | Gravity Forms Integration for wpDataTables | Formidable Forms Integration for wpDataTables | Master-Detail Tables

  •  2,572
    Aleksandar replied

    Hi again Robert.

    Our developers confirmed they will not be changing the structure, so your JS should continue to work without issues in the future.

    We've also added a task for the future to block appointment bookings if the package is not paid, but there's no ETA at this time when it will be worked on.

    Kind Regards, 

    Aleksandar Vuković
    [email protected]

    Rate my support

    wpDataTables: FAQ | Facebook | Twitter | InstagramFront-end and back-end demo | Docs

    Amelia: FAQ | Facebook | Twitter | InstagramAmelia demo sites | Docs | Discord Community

    You can try wpDataTables add-ons before purchasing on these sandbox sites:

    Powerful Filters | Gravity Forms Integration for wpDataTables | Formidable Forms Integration for wpDataTables | Master-Detail Tables