v20 no more per-office holiday voice messages

Status
Not open for further replies.

stijngruwier-leiedal

Customer
Joined
Dec 28, 2023
Messages
1
Reaction score
7
after upgrading from v18 to v20 (update 0 build 1458) we noticied multiple holiday schemes can be set per department (which is great), but ont he other hand we are missing the function to link specific voice messages to holidays.

in v18 you could register/pre-record a different office holiday voice message for each holiday. something we only had to do once a year and could then forget about it.

in v20 you can only specify which days are holidays but you cannot not pre-record the individual messages for each holiday.
so now each time a holiday comes up we have to think about it to record the specific message , something that is easily forgotten ...

I hope the v18 handling of office hoidays can be brought back in v20 as it was much better than how it is now.
 
+1 for me as well. This is a realy important feature for some of my customers.
 
  • Like
Reactions: netts
We need this back, please. +1
 
  • Like
Reactions: Rogé
We need this back, please. +1
And also we would like to get the option back "global Holiday" on extensions "inbound rules"
 
  • Like
Reactions: netts and Rogé
Is just writing +1 in this topic "the way to go" for requesting a "new" feature by 3CX?

Our customers need a different message for each holiday. The suggestion of @akallistros is not an option for us as it requires manual actions before each holiday.

The "SIP trunk level scripting" what's suggested by @Nick Galea sounds like a more complicated way to achieve the same as the removed feature. Our customers currently maintain their own holiday messages as it was easy to maintain. I cannot expect that our customers understand how to change scripts. Its also sensitive to errors. I cannot migrate my customerrs from V18 to V20 as long as this feature is not re-implemented.

It would be great if 3CX would respond on this topic if the feature will be re-introduced or not.
 
  • Like
Reactions: petxi79
Hi Folks

Here, because sharing is caring:

C#:
#nullable disable
using CallFlow;
using System;
using System.Linq;
using System.Threading.Tasks;
using TCX.Configuration;
using TCX.PBXAPI;
using System.Collections.Generic;
using System.IO;

namespace dummy
{
    // KLM IT AG
    // Script Name: MultiHolidayPromptScript
    // Created by: Kilian Meister
    // Last Modified: 2024-05-18

    public class MultiHolidayPromptScript : ScriptBase<MultiHolidayPromptScript>
    {
        // Destination IVR extensions as variables for easy customization
        private string forwardingExtension = "404";
        private string fallbackExtension = "401"; // Fallback destination IVR extension
        private string ausserhalbExtension = "401"; // Ausserhalb IVR extension

        // Method to play the holiday prompt if applicable and then forward the call
        async Task PlayHolidayPromptAndForward()
        {
            var ps = MyCall.PS as PhoneSystem; // Access the PhoneSystem object
            var holidays = ps.GetAll<OfficeHoliday>().ToArray(); // Get all office holidays and convert to array
            var today = DateTime.Today; // Get today's date

            bool promptPlayed = false; // Flag to check if a prompt was played

            // First loop: Attempt to play the specific holiday prompt
            foreach (var holiday in holidays)
            {
                var holidayDate = new DateTime(today.Year, holiday.Month, holiday.Day); // Construct the holiday date for this year
                if (holidayDate == today) // Check if today is a holiday
                {
                    string holidayName = holiday.Name; // Get the holiday name
                    string promptFileName = $"{holidayName}.wav"; // Construct the filename for the prompt dynamically

                    // Check if a specific prompt file exists for the full holiday name
                    if (File.Exists(Path.Combine("/var/lib/3cxpbx/Instance1/Data/Ivr/Prompts/", promptFileName))) // Update the path as needed
                    {
                        // Play the specific holiday prompt
                        await MyCall.PlayPrompt(null, new[] { promptFileName }, PlayPromptOptions.Blocked);
                        promptPlayed = true;
                        break; // Exit the loop once the holiday prompt is played
                    }
                }
            }

            // Second loop: Attempt to play partial matches if no specific prompt was played
            if (!promptPlayed)
            {
                foreach (var holiday in holidays)
                {
                    var holidayDate = new DateTime(today.Year, holiday.Month, holiday.Day);
                    if (holidayDate == today)
                    {
                        string holidayName = holiday.Name;

                        // Check for partial matches
                        if (holidayName.Contains("Brückentag"))
                        {
                            await MyCall.PlayPrompt(null, new[] { "Brückentag.wav" }, PlayPromptOptions.Blocked);
                            promptPlayed = true;
                        }
                        else if (holidayName.Contains("Interner Firmenanlass"))
                        {
                            await MyCall.PlayPrompt(null, new[] { "Interner Firmenanlass.wav" }, PlayPromptOptions.Blocked);
                            promptPlayed = true;
                        }
                        else if (holidayName.Contains("bevorstehender Feiertag"))
                        {
                            await MyCall.PlayPrompt(null, new[] { "bevorstehender Feiertag.wav" }, PlayPromptOptions.Blocked);
                            promptPlayed = true;
                        }
                        else if (holidayName.Contains("Ausserhalb"))
                        {
                            //await MyCall.PlayPrompt(null, new[] { "IVR-Ausserhalb.wav" }, PlayPromptOptions.Blocked);
                            promptPlayed = true;
                            forwardingExtension = ausserhalbExtension; // Set to Ausserhalb IVR extension
                        }

                        if (promptPlayed)
                            break; // Exit the loop once the holiday prompt is played
                    }
                }
            }

            // Determine the forwarding destination
            string destinationExtension = promptPlayed ? forwardingExtension : fallbackExtension;

            // Forward the call to the determined IVR extension
            var destination = new DestinationStruct(DestinationType.Extension, ps.GetDNByNumber(destinationExtension), null);
            var routeResult = await MyCall.RouteToAsync(destination);

            if (routeResult.FinalStatus == CallControlResult.CallRequestStatus.Success)
            {
                MyCall.Debug($"Call successfully forwarded to IVR with extension {destinationExtension}."); // Log success
            }
            else
            {
                MyCall.Critical($"Failed to forward the call to IVR. Reason: {routeResult.ReasonText}"); // Log failure with reason
            }
        }

        // Main entry point for the script
        public override async void Start()
        {
            try
            {
                await Task.Run(async () =>
                {
                    try
                    {
                        MyCall.Debug($"Script start delay: {DateTime.UtcNow - MyCall.LastChangeStatus}"); // Log script start delay
                        MyCall.Debug($"Incoming connection {MyCall}"); // Log incoming connection details

                        // Play holiday prompt if applicable and forward the call
                        await PlayHolidayPromptAndForward();

                        MyCall.Info("MultiHolidayPromptScript Exit script"); // Log script exit
                        MyCall.Return(true); // Return success
                    }
                    catch
                    {
                        MyCall.Return(false); // Return failure in case of any exception
                    }
                });
            }
            catch
            {
                MyCall.Return(false); // Return failure in case of any exception
            }
        }
    }
}

I hope this helps.

Best regards

Kilian
 
We have a lot of customers here in Switzerland who were happy to be able to set all the holidays relatively easily and independently at the beginning of the year with a corresponding announcement, for example “company holidays,” “company events,” “school holidays,” and so on.
Schools in particular are now having a hard time because they want to announce to parents when the school or the office will be open again.
Now only being able to define the days, and setting a reminder each time, manually adjusting the announcement before and after - is a pretty big step backwards and is preventing people from switching to V20.
 
I also cannot move most clients to v20 until this feature returns, most are dependant on the ability to set these per holiday messages in advance
 
  • Like
Reactions: Rogé
We will be moving to another software if this feature is not restored.. Talk about going backwards.
 
  • Like
Reactions: Rogé
Hello everyone

It seems my post with a possible solution is taking a bit longer to be published. If anyone is interested in a potential solution using a Call Processing Script, please feel free to DM me.

Best regards

Kilian
 
  • Like
Reactions: Evolute IT
We need this back, please. +1
 
Hello everyone

It seems my post with a possible solution is taking a bit longer to be published. If anyone is interested in a potential solution using a Call Processing Script, please feel free to DM me.

Best regards

Kilian
Hello @kilianmeister ,

The problem using Call Processing Script is that it's a complicated way to explain to the autonomous customers.

The user @Rogé has explained it perfectly:
[...]

Our customers need a different message for each holiday. The suggestion of @akallistros is not an option for us as it requires manual actions before each holiday.

The "SIP trunk level scripting" what's suggested by @Nick Galea sounds like a more complicated way to achieve the same as the removed feature. Our customers currently maintain their own holiday messages as it was easy to maintain. I cannot expect that our customers understand how to change scripts. Its also sensitive to errors. I cannot migrate my customerrs from V18 to V20 as long as this feature is not re-implemented.

It would be great if 3CX would respond on this topic if the feature will be re-introduced or not.

Please vote in the ideas forum:
https://www.3cx.com/community/threads/bring-back-again-per-office-holiday-voice-messages.125146/

Best regards,
Jaume
 
Hello @kilianmeister ,

The problem using Call Processing Script is that it's a complicated way to explain to the autonomous customers.

The user @Rogé has explained it perfectly:


Please vote in the ideas forum:
https://www.3cx.com/community/threads/bring-back-again-per-office-holiday-voice-messages.125146/

Best regards,
Jaume
Hello @petxi79

I've had a similar thought regarding the CPS. However, I believe that the variant I designed increasingly automates this process. My version is based on the idea that there is a WAV file corresponding to the registered holiday name, which is then automatically selected. If a name is entered incorrectly, a fallback announcement is chosen. Subsequently, a call is forwarded to an extension. Of course, this can be further developed, but ultimately, I'm just offering my help here so that we can continue moving forward and not remain stuck on V18.

Best regards
Kilian
 
Hello @petxi79

I've had a similar thought regarding the CPS. However, I believe that the variant I designed increasingly automates this process. My version is based on the idea that there is a WAV file corresponding to the registered holiday name, which is then automatically selected. If a name is entered incorrectly, a fallback announcement is chosen. Subsequently, a call is forwarded to an extension. Of course, this can be further developed, but ultimately, I'm just offering my help here so that we can continue moving forward and not remain stuck on V18.

Best regards
Kilian
Hi @kilianmeister

I haven't doubt that your solution is a valid, helpful solution, and I suppose the rest of the forum users, appreciate your help. ;)

I'm going to send you a DM to get your solution.

Thanks,
Jaume
 
Last edited:
This is an important feature for all our clients.
A number of clients use this feature to change entire call flows for 'Sale" periods they run seasonally, tax time, valentines/Halloween/christmas/easter, etc. They are not closed but the companies shift roles and take HUGE numbers of calls including off shoring some calls to 3rd party concierges, its an entire new call flow that only holidays feature can overtake without changing the system design and moving it back again.
We set all this up with recordings and times early in the year so not a last minute consideration.
This really is a critical feature we require, prior to moving to v20 or another platform if need be.
I did just push 2 renewals today, 38% increase in price over last year and we have less functionality to date. Please have these features back in an update or extend out the expiration of v18 where possible, given the security concerns.
Thanks in advance!
 
Just lost one Client after the first day because we were not aware that this feature has gone. All other clients will not move to the 20 version. This feature is a killer. Pls bring it back.
 
  • Like
Reactions: petxi79
+1
Allot of our customers are using this feature.
Please bring it back, this will be a dealbreaker for some of them.
 
We use this feature all the time ourselves and have lots of clients that do as well, and even manage it on their own due to the ease of use. Will be very good to see this added back in.
 
Hi Folks

Here, because sharing is caring:

C#:
#nullable disable
using CallFlow;
using System;
using System.Linq;
using System.Threading.Tasks;
using TCX.Configuration;
using TCX.PBXAPI;
using System.Collections.Generic;
using System.IO;

namespace dummy
{
    // KLM IT AG
    // Script Name: MultiHolidayPromptScript
    // Created by: Kilian Meister
    // Last Modified: 2024-05-18

    public class MultiHolidayPromptScript : ScriptBase<MultiHolidayPromptScript>
    {
        // Destination IVR extensions as variables for easy customization
        private string forwardingExtension = "404";
        private string fallbackExtension = "401"; // Fallback destination IVR extension
        private string ausserhalbExtension = "401"; // Ausserhalb IVR extension

        // Method to play the holiday prompt if applicable and then forward the call
        async Task PlayHolidayPromptAndForward()
        {
            var ps = MyCall.PS as PhoneSystem; // Access the PhoneSystem object
            var holidays = ps.GetAll<OfficeHoliday>().ToArray(); // Get all office holidays and convert to array
            var today = DateTime.Today; // Get today's date

            bool promptPlayed = false; // Flag to check if a prompt was played

            // First loop: Attempt to play the specific holiday prompt
            foreach (var holiday in holidays)
            {
                var holidayDate = new DateTime(today.Year, holiday.Month, holiday.Day); // Construct the holiday date for this year
                if (holidayDate == today) // Check if today is a holiday
                {
                    string holidayName = holiday.Name; // Get the holiday name
                    string promptFileName = $"{holidayName}.wav"; // Construct the filename for the prompt dynamically

                    // Check if a specific prompt file exists for the full holiday name
                    if (File.Exists(Path.Combine("/var/lib/3cxpbx/Instance1/Data/Ivr/Prompts/", promptFileName))) // Update the path as needed
                    {
                        // Play the specific holiday prompt
                        await MyCall.PlayPrompt(null, new[] { promptFileName }, PlayPromptOptions.Blocked);
                        promptPlayed = true;
                        break; // Exit the loop once the holiday prompt is played
                    }
                }
            }

            // Second loop: Attempt to play partial matches if no specific prompt was played
            if (!promptPlayed)
            {
                foreach (var holiday in holidays)
                {
                    var holidayDate = new DateTime(today.Year, holiday.Month, holiday.Day);
                    if (holidayDate == today)
                    {
                        string holidayName = holiday.Name;

                        // Check for partial matches
                        if (holidayName.Contains("Brückentag"))
                        {
                            await MyCall.PlayPrompt(null, new[] { "Brückentag.wav" }, PlayPromptOptions.Blocked);
                            promptPlayed = true;
                        }
                        else if (holidayName.Contains("Interner Firmenanlass"))
                        {
                            await MyCall.PlayPrompt(null, new[] { "Interner Firmenanlass.wav" }, PlayPromptOptions.Blocked);
                            promptPlayed = true;
                        }
                        else if (holidayName.Contains("bevorstehender Feiertag"))
                        {
                            await MyCall.PlayPrompt(null, new[] { "bevorstehender Feiertag.wav" }, PlayPromptOptions.Blocked);
                            promptPlayed = true;
                        }
                        else if (holidayName.Contains("Ausserhalb"))
                        {
                            //await MyCall.PlayPrompt(null, new[] { "IVR-Ausserhalb.wav" }, PlayPromptOptions.Blocked);
                            promptPlayed = true;
                            forwardingExtension = ausserhalbExtension; // Set to Ausserhalb IVR extension
                        }

                        if (promptPlayed)
                            break; // Exit the loop once the holiday prompt is played
                    }
                }
            }

            // Determine the forwarding destination
            string destinationExtension = promptPlayed ? forwardingExtension : fallbackExtension;

            // Forward the call to the determined IVR extension
            var destination = new DestinationStruct(DestinationType.Extension, ps.GetDNByNumber(destinationExtension), null);
            var routeResult = await MyCall.RouteToAsync(destination);

            if (routeResult.FinalStatus == CallControlResult.CallRequestStatus.Success)
            {
                MyCall.Debug($"Call successfully forwarded to IVR with extension {destinationExtension}."); // Log success
            }
            else
            {
                MyCall.Critical($"Failed to forward the call to IVR. Reason: {routeResult.ReasonText}"); // Log failure with reason
            }
        }

        // Main entry point for the script
        public override async void Start()
        {
            try
            {
                await Task.Run(async () =>
                {
                    try
                    {
                        MyCall.Debug($"Script start delay: {DateTime.UtcNow - MyCall.LastChangeStatus}"); // Log script start delay
                        MyCall.Debug($"Incoming connection {MyCall}"); // Log incoming connection details

                        // Play holiday prompt if applicable and forward the call
                        await PlayHolidayPromptAndForward();

                        MyCall.Info("MultiHolidayPromptScript Exit script"); // Log script exit
                        MyCall.Return(true); // Return success
                    }
                    catch
                    {
                        MyCall.Return(false); // Return failure in case of any exception
                    }
                });
            }
            catch
            {
                MyCall.Return(false); // Return failure in case of any exception
            }
        }
    }
}

I hope this helps.

Best regards

Kilian
Hi Kilian
thanks for sharing. Is there a way this is loadable into CFD so it's visual?
I'm not so a programmer as you.

Thanks,
Rogier
 
I can only backup all previous comments. We need this feature back, or we will lose existing clients. At the moment we have a freeze on v18 and do not upgrade anyone to v20.
 
  • Like
Reactions: petxi79
Status
Not open for further replies.

Forum statistics

Threads
111,972
Messages
590,065
Members
164,887
Latest member
KrishnaMR