<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="fr">
	<id>https://indywiki.fr/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Anthony</id>
	<title>INDYWiki - Contributions [fr]</title>
	<link rel="self" type="application/atom+xml" href="https://indywiki.fr/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Anthony"/>
	<link rel="alternate" type="text/html" href="https://indywiki.fr/Sp%C3%A9cial:Contributions/Anthony"/>
	<updated>2026-06-02T20:59:16Z</updated>
	<subtitle>Contributions</subtitle>
	<generator>MediaWiki 1.44.2</generator>
	<entry>
		<id>https://indywiki.fr/index.php?title=Script_de_routage_des_appels&amp;diff=22288</id>
		<title>Script de routage des appels</title>
		<link rel="alternate" type="text/html" href="https://indywiki.fr/index.php?title=Script_de_routage_des_appels&amp;diff=22288"/>
		<updated>2026-06-01T14:30:18Z</updated>

		<summary type="html">&lt;p&gt;Anthony : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Permet en fonction du moment de la semaine de router les appels vers telle ou telle destination.&lt;br /&gt;
&#039;&#039;&#039;Nécessite d&#039;ouvrir le site H24 ( voir écran ci-dessous)&#039;&#039;&#039; sur le département / instance 3CX ( c&#039;est le script qui gère )&lt;br /&gt;
&lt;br /&gt;
[[Fichier:2026-06-01 16h28 48.png]]&lt;br /&gt;
&lt;br /&gt;
⚠️ les règles sont évaluées dans l&#039;ordre de leur apparition, il faut donc les déclarer de la plus spécifique à la plus générale ⚠️&lt;br /&gt;
&lt;br /&gt;
===Le script===&lt;br /&gt;
&lt;br /&gt;
Seules les lignes jaune requiert d&#039;être éditées. Si plus de règles sont à prévoir, dupliquer les sections &#039;&#039;&#039;new RoutingRule&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
* Ligne 16 : si aucune règle dans le script ne permet de déterminer un chemin, alors c&#039;est cette extension la cible&lt;br /&gt;
* Ligne 44 : Pour chaque règle, il faut définir les jours et horaires. sur cet exemple, le lundi de 14 à 17h, c&#039;est la règle 1 qui s&#039;applique.&lt;br /&gt;
* Ligne 50 : C&#039;est l&#039;extension qui va être visée par la règle, peut être un utilisateur, un SVI, un groupe , une file d&#039;attente.&lt;br /&gt;
* Ligne 51 : DID : ce filtre permet de tester le &#039;&#039;&#039;numéro appelé&#039;&#039;&#039; ( SDA  actif sur le système). En pratique on ne s&#039;en sert pas ici car le filtre se fait en amont de l&#039;[[Script_de_routage_des_appels#Mise_en_place_du_script|appel du script]]. Mais possible. La syntaxe &#039;&#039;&#039;*&#039;&#039;&#039; permet de tout laisser passer&lt;br /&gt;
* Ligne 52 : Callers, on peut filtrer sur le &#039;&#039;&#039;numéros de l&#039;appelant&#039;&#039;&#039;. La syntaxe &#039;&#039;&#039;*&#039;&#039;&#039; permet de tout laisser passer&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;csharp&amp;quot; line highlight=&amp;quot;16,44,50-52&amp;quot;&amp;gt;&lt;br /&gt;
#nullable disable&lt;br /&gt;
using CallFlow;&lt;br /&gt;
using System;&lt;br /&gt;
using System.Threading.Tasks;&lt;br /&gt;
using TCX.Configuration;&lt;br /&gt;
using TCX.PBXAPI;&lt;br /&gt;
using System.Collections.Generic;&lt;br /&gt;
using System.Linq;&lt;br /&gt;
using CallFlow.CFD;&lt;br /&gt;
&lt;br /&gt;
namespace interceptcall&lt;br /&gt;
{&lt;br /&gt;
    public class InterceptInboundCall : ScriptBase&amp;lt;InterceptInboundCall&amp;gt;&lt;br /&gt;
    {&lt;br /&gt;
        // Destination par Défaut, à priori jamais utilisé car ce numéro doit toujours être joignable&lt;br /&gt;
        const string DefaultDestinationDN = &amp;quot;812&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
        // Structure d&#039;une règle de routage&lt;br /&gt;
        class RoutingRule&lt;br /&gt;
        {&lt;br /&gt;
            public Schedule Schedule { get; set; }&lt;br /&gt;
            public string DestinationDN { get; set; }&lt;br /&gt;
            public string[] DIDs { get; set; }&lt;br /&gt;
            public string[] Callers { get; set; }&lt;br /&gt;
&lt;br /&gt;
            public RoutingRule(Schedule schedule, string destinationDN, string[] dids, string[] callers)&lt;br /&gt;
            {&lt;br /&gt;
                Schedule = schedule;&lt;br /&gt;
                DestinationDN = destinationDN;&lt;br /&gt;
                DIDs = dids;&lt;br /&gt;
                Callers = callers;&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
		// Règle(s) de routage &amp;quot;First Match&amp;quot; : La première règle satisfaite est éxécutée, les suivantes sont ignorées&lt;br /&gt;
&lt;br /&gt;
       static readonly List&amp;lt;RoutingRule&amp;gt; routingRules = new List&amp;lt;RoutingRule&amp;gt;&lt;br /&gt;
        {&lt;br /&gt;
            // Règle 1 - Mairie ouverte - routage vers le 801 qui route vers le 100 ( pas de changements&lt;br /&gt;
            new RoutingRule(&lt;br /&gt;
                new Schedule(RuleHoursType.SpecificHours)&lt;br /&gt;
                {&lt;br /&gt;
					{ DayOfWeek.Monday,    new Schedule.PeriodOfDay(new TimeSpan(14,00,0), new TimeSpan(17,00,0)) },&lt;br /&gt;
					{ DayOfWeek.Tuesday,    new Schedule.PeriodOfDay(new TimeSpan(14,00,0), new TimeSpan(17,00,0)) },&lt;br /&gt;
					{ DayOfWeek.Wednesday,    new Schedule.PeriodOfDay(new TimeSpan(09,00,0), new TimeSpan(12,00,0)) },&lt;br /&gt;
                    { DayOfWeek.Thursday,    new Schedule.PeriodOfDay(new TimeSpan(09,00,0), new TimeSpan(12,00,0)) },&lt;br /&gt;
					{ DayOfWeek.Friday,    new Schedule.PeriodOfDay(new TimeSpan(09,00,0), new TimeSpan(12,00,0)) }&lt;br /&gt;
                },&lt;br /&gt;
                &amp;quot;801&amp;quot;,&lt;br /&gt;
                new[] { &amp;quot;*&amp;quot; },   // Tous les DIDs&lt;br /&gt;
                new[] { &amp;quot;*&amp;quot; }    // Tous les callers&lt;br /&gt;
            ),&lt;br /&gt;
			&lt;br /&gt;
			 // Règle 2 — Mairie fermée en semaine ( routage vers le 800 )&lt;br /&gt;
            new RoutingRule(&lt;br /&gt;
                new Schedule(RuleHoursType.SpecificHours)&lt;br /&gt;
                {&lt;br /&gt;
					{ DayOfWeek.Monday,    new Schedule.PeriodOfDay(new TimeSpan(8,00,0), new TimeSpan(14,00,0)) },&lt;br /&gt;
     				{ DayOfWeek.Monday,    new Schedule.PeriodOfDay(new TimeSpan(17,00,0), new TimeSpan(24,00,0)) },&lt;br /&gt;
					{ DayOfWeek.Tuesday,    new Schedule.PeriodOfDay(new TimeSpan(0,00,0), new TimeSpan(14,00,0)) },&lt;br /&gt;
					{ DayOfWeek.Tuesday,    new Schedule.PeriodOfDay(new TimeSpan(17,00,0), new TimeSpan(24,00,0)) },&lt;br /&gt;
					{ DayOfWeek.Wednesday,    new Schedule.PeriodOfDay(new TimeSpan(0,00,0), new TimeSpan(09,00,0)) },&lt;br /&gt;
					{ DayOfWeek.Wednesday,    new Schedule.PeriodOfDay(new TimeSpan(12,00,0), new TimeSpan(24,00,0)) },&lt;br /&gt;
      				{ DayOfWeek.Thursday,    new Schedule.PeriodOfDay(new TimeSpan(0,00,0), new TimeSpan(09,00,0)) },&lt;br /&gt;
					{ DayOfWeek.Thursday,    new Schedule.PeriodOfDay(new TimeSpan(12,00,0), new TimeSpan(24,00,0)) },&lt;br /&gt;
      				{ DayOfWeek.Friday,    new Schedule.PeriodOfDay(new TimeSpan(0,00,0), new TimeSpan(09,00,0)) },&lt;br /&gt;
					{ DayOfWeek.Friday,    new Schedule.PeriodOfDay(new TimeSpan(12,00,0), new TimeSpan(24,00,0)) }&lt;br /&gt;
                },&lt;br /&gt;
                &amp;quot;800&amp;quot;,&lt;br /&gt;
                new[] { &amp;quot;*&amp;quot; },&lt;br /&gt;
                new[] { &amp;quot;*&amp;quot; }&lt;br /&gt;
            ),&lt;br /&gt;
			&lt;br /&gt;
			 // Règle 3 — Mairie fermée le week-end ( vendredi 16h30 au lundi ? )&lt;br /&gt;
            new RoutingRule(&lt;br /&gt;
                new Schedule(RuleHoursType.SpecificHours)&lt;br /&gt;
                {&lt;br /&gt;
					&lt;br /&gt;
					{ DayOfWeek.Friday,    new Schedule.PeriodOfDay(new TimeSpan(16,30,0), new TimeSpan(24,00,0)) },&lt;br /&gt;
					{ DayOfWeek.Saturday, new Schedule.PeriodOfDay(new TimeSpan(0,00,0), new TimeSpan(24,00,0)) },&lt;br /&gt;
					{ DayOfWeek.Sunday, new Schedule.PeriodOfDay(new TimeSpan(0,00,0), new TimeSpan(24,00,0)) }&lt;br /&gt;
      				{ DayOfWeek.Monday, new Schedule.PeriodOfDay(new TimeSpan(0,00,0), new TimeSpan(08,00,0)) }&lt;br /&gt;
                },&lt;br /&gt;
                &amp;quot;804&amp;quot;,&lt;br /&gt;
                new[] { &amp;quot;*&amp;quot; },&lt;br /&gt;
                new[] { &amp;quot;*&amp;quot; }&lt;br /&gt;
            ),&lt;br /&gt;
			&lt;br /&gt;
        };&lt;br /&gt;
&lt;br /&gt;
        // Appel de la fonction principale&lt;br /&gt;
&lt;br /&gt;
        public override async void Start()&lt;br /&gt;
        {&lt;br /&gt;
            try&lt;br /&gt;
            {&lt;br /&gt;
                await Task.Run(async () =&amp;gt;&lt;br /&gt;
                {&lt;br /&gt;
                    bool intercepted = false;&lt;br /&gt;
                    var ps = MyCall.PS as PhoneSystem;&lt;br /&gt;
&lt;br /&gt;
                    if (!(MyCall.Caller.DN is ExternalLine externalLine))&lt;br /&gt;
                    {&lt;br /&gt;
                        MyCall.Return(false);&lt;br /&gt;
                        return;&lt;br /&gt;
                    }&lt;br /&gt;
&lt;br /&gt;
                    var DIDNumber = MyCall.Caller[&amp;quot;inbound_did&amp;quot;] ?? &amp;quot;&amp;quot;;&lt;br /&gt;
                    var CallerID = MyCall.Caller.CallerID ?? &amp;quot;&amp;quot;;&lt;br /&gt;
                    var currentTime = externalLine.Now(out var utc, out var timezone, out var groupmode);&lt;br /&gt;
&lt;br /&gt;
                    MyCall.Info($&amp;quot;Incoming call | Caller: {CallerID} | DID: {DIDNumber} | Time: {currentTime}&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
                    foreach (var rule in routingRules)&lt;br /&gt;
                    {&lt;br /&gt;
                        if (!rule.Schedule.IsActiveTime(currentTime))&lt;br /&gt;
                            continue;&lt;br /&gt;
&lt;br /&gt;
                        bool didMatch = rule.DIDs.Contains(&amp;quot;*&amp;quot;) || rule.DIDs.Contains(DIDNumber);&lt;br /&gt;
                        bool callerMatch = rule.Callers.Contains(&amp;quot;*&amp;quot;) || rule.Callers.Contains(CallerID);&lt;br /&gt;
&lt;br /&gt;
                        if (!didMatch || !callerMatch)&lt;br /&gt;
                            continue;&lt;br /&gt;
&lt;br /&gt;
                        var destinationDN = ps.GetDNByNumber(rule.DestinationDN);&lt;br /&gt;
&lt;br /&gt;
                        if (destinationDN == null)&lt;br /&gt;
                        {&lt;br /&gt;
                            MyCall.Error($&amp;quot;Destination {rule.DestinationDN} not found.&amp;quot;);&lt;br /&gt;
                            continue;&lt;br /&gt;
                        }&lt;br /&gt;
&lt;br /&gt;
                        try&lt;br /&gt;
                        {&lt;br /&gt;
                            var result = await MyCall.RouteToAsync(new DestinationStruct(destinationDN));&lt;br /&gt;
                            MyCall.Info($&amp;quot;Routed to {rule.DestinationDN} | Result: {result}&amp;quot;);&lt;br /&gt;
                            intercepted = true;&lt;br /&gt;
                            break; // Stop at first matching rule&lt;br /&gt;
                        }&lt;br /&gt;
                        catch (Exception ex)&lt;br /&gt;
                        {&lt;br /&gt;
                            MyCall.Error($&amp;quot;Routing failed to {rule.DestinationDN}: {ex}&amp;quot;);&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
&lt;br /&gt;
                &lt;br /&gt;
                    // Utilisation de la route par défaut&lt;br /&gt;
                    &lt;br /&gt;
                    if (!intercepted)&lt;br /&gt;
                    {&lt;br /&gt;
                        var fallbackDN = ps.GetDNByNumber(DefaultDestinationDN);&lt;br /&gt;
                        if (fallbackDN != null)&lt;br /&gt;
                        {&lt;br /&gt;
                            try&lt;br /&gt;
                            {&lt;br /&gt;
                                var result = await MyCall.RouteToAsync(new DestinationStruct(fallbackDN));&lt;br /&gt;
                                MyCall.Info($&amp;quot;Fallback routing to {DefaultDestinationDN} | Result: {result}&amp;quot;);&lt;br /&gt;
                                intercepted = true;&lt;br /&gt;
                            }&lt;br /&gt;
                            catch (Exception ex)&lt;br /&gt;
                            {&lt;br /&gt;
                                MyCall.Error($&amp;quot;Fallback routing failed: {ex}&amp;quot;);&lt;br /&gt;
                            }&lt;br /&gt;
                        }&lt;br /&gt;
                        else&lt;br /&gt;
                        {&lt;br /&gt;
                            MyCall.Error($&amp;quot;Fallback DN {DefaultDestinationDN} not found.&amp;quot;);&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
&lt;br /&gt;
                    MyCall.Return(intercepted);&lt;br /&gt;
                });&lt;br /&gt;
            }&lt;br /&gt;
            catch (Exception ex)&lt;br /&gt;
            {&lt;br /&gt;
                MyCall.Error($&amp;quot;Script execution failed: {ex}&amp;quot;);&lt;br /&gt;
                MyCall.Return(false);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Mise en place du script===&lt;br /&gt;
&lt;br /&gt;
Connecté en admin dans 3CX :&lt;br /&gt;
 &lt;br /&gt;
 Admin / Intégrations / Scripts d&#039;appels / + Ajouter personnalisé&lt;br /&gt;
&lt;br /&gt;
[[Fichier:2026-05-27 15h34 23.png|cadre|right]]&lt;br /&gt;
# Nommer le script&lt;br /&gt;
#Choisir &#039;&#039;&#039;Quand cette SDA est composée&#039;&#039;&#039;&lt;br /&gt;
#Choisir la SDA appelée qui va déclencher le script&lt;br /&gt;
#Choisir le scope d&#039;action du script&lt;br /&gt;
#Cliquer sur OK&lt;br /&gt;
#Coller le script préparé dans la zone script&lt;br /&gt;
#Sauvegarder&lt;br /&gt;
&lt;br /&gt;
{{Valide|v20}}&lt;br /&gt;
[[Catégorie:3CX]]&lt;/div&gt;</summary>
		<author><name>Anthony</name></author>
	</entry>
	<entry>
		<id>https://indywiki.fr/index.php?title=Script_de_routage_des_appels&amp;diff=22287</id>
		<title>Script de routage des appels</title>
		<link rel="alternate" type="text/html" href="https://indywiki.fr/index.php?title=Script_de_routage_des_appels&amp;diff=22287"/>
		<updated>2026-06-01T14:29:24Z</updated>

		<summary type="html">&lt;p&gt;Anthony : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Permet en fonction du moment de la semaine de router les appels vers telle ou telle destination.&lt;br /&gt;
&#039;&#039;&#039;Nécessite de supprimer les horaires de fermeture&#039;&#039;&#039; sur le département / instance 3CX ( c&#039;est le script qui gère )&lt;br /&gt;
&lt;br /&gt;
[[Fichier:2026-06-01 16h28 48.png]]&lt;br /&gt;
&lt;br /&gt;
⚠️ les règles sont évaluées dans l&#039;ordre de leur apparition, il faut donc les déclarer de la plus spécifique à la plus générale ⚠️&lt;br /&gt;
&lt;br /&gt;
===Le script===&lt;br /&gt;
&lt;br /&gt;
Seules les lignes jaune requiert d&#039;être éditées. Si plus de règles sont à prévoir, dupliquer les sections &#039;&#039;&#039;new RoutingRule&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
* Ligne 16 : si aucune règle dans le script ne permet de déterminer un chemin, alors c&#039;est cette extension la cible&lt;br /&gt;
* Ligne 44 : Pour chaque règle, il faut définir les jours et horaires. sur cet exemple, le lundi de 14 à 17h, c&#039;est la règle 1 qui s&#039;applique.&lt;br /&gt;
* Ligne 50 : C&#039;est l&#039;extension qui va être visée par la règle, peut être un utilisateur, un SVI, un groupe , une file d&#039;attente.&lt;br /&gt;
* Ligne 51 : DID : ce filtre permet de tester le &#039;&#039;&#039;numéro appelé&#039;&#039;&#039; ( SDA  actif sur le système). En pratique on ne s&#039;en sert pas ici car le filtre se fait en amont de l&#039;[[Script_de_routage_des_appels#Mise_en_place_du_script|appel du script]]. Mais possible. La syntaxe &#039;&#039;&#039;*&#039;&#039;&#039; permet de tout laisser passer&lt;br /&gt;
* Ligne 52 : Callers, on peut filtrer sur le &#039;&#039;&#039;numéros de l&#039;appelant&#039;&#039;&#039;. La syntaxe &#039;&#039;&#039;*&#039;&#039;&#039; permet de tout laisser passer&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;csharp&amp;quot; line highlight=&amp;quot;16,44,50-52&amp;quot;&amp;gt;&lt;br /&gt;
#nullable disable&lt;br /&gt;
using CallFlow;&lt;br /&gt;
using System;&lt;br /&gt;
using System.Threading.Tasks;&lt;br /&gt;
using TCX.Configuration;&lt;br /&gt;
using TCX.PBXAPI;&lt;br /&gt;
using System.Collections.Generic;&lt;br /&gt;
using System.Linq;&lt;br /&gt;
using CallFlow.CFD;&lt;br /&gt;
&lt;br /&gt;
namespace interceptcall&lt;br /&gt;
{&lt;br /&gt;
    public class InterceptInboundCall : ScriptBase&amp;lt;InterceptInboundCall&amp;gt;&lt;br /&gt;
    {&lt;br /&gt;
        // Destination par Défaut, à priori jamais utilisé car ce numéro doit toujours être joignable&lt;br /&gt;
        const string DefaultDestinationDN = &amp;quot;812&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
        // Structure d&#039;une règle de routage&lt;br /&gt;
        class RoutingRule&lt;br /&gt;
        {&lt;br /&gt;
            public Schedule Schedule { get; set; }&lt;br /&gt;
            public string DestinationDN { get; set; }&lt;br /&gt;
            public string[] DIDs { get; set; }&lt;br /&gt;
            public string[] Callers { get; set; }&lt;br /&gt;
&lt;br /&gt;
            public RoutingRule(Schedule schedule, string destinationDN, string[] dids, string[] callers)&lt;br /&gt;
            {&lt;br /&gt;
                Schedule = schedule;&lt;br /&gt;
                DestinationDN = destinationDN;&lt;br /&gt;
                DIDs = dids;&lt;br /&gt;
                Callers = callers;&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
		// Règle(s) de routage &amp;quot;First Match&amp;quot; : La première règle satisfaite est éxécutée, les suivantes sont ignorées&lt;br /&gt;
&lt;br /&gt;
       static readonly List&amp;lt;RoutingRule&amp;gt; routingRules = new List&amp;lt;RoutingRule&amp;gt;&lt;br /&gt;
        {&lt;br /&gt;
            // Règle 1 - Mairie ouverte - routage vers le 801 qui route vers le 100 ( pas de changements&lt;br /&gt;
            new RoutingRule(&lt;br /&gt;
                new Schedule(RuleHoursType.SpecificHours)&lt;br /&gt;
                {&lt;br /&gt;
					{ DayOfWeek.Monday,    new Schedule.PeriodOfDay(new TimeSpan(14,00,0), new TimeSpan(17,00,0)) },&lt;br /&gt;
					{ DayOfWeek.Tuesday,    new Schedule.PeriodOfDay(new TimeSpan(14,00,0), new TimeSpan(17,00,0)) },&lt;br /&gt;
					{ DayOfWeek.Wednesday,    new Schedule.PeriodOfDay(new TimeSpan(09,00,0), new TimeSpan(12,00,0)) },&lt;br /&gt;
                    { DayOfWeek.Thursday,    new Schedule.PeriodOfDay(new TimeSpan(09,00,0), new TimeSpan(12,00,0)) },&lt;br /&gt;
					{ DayOfWeek.Friday,    new Schedule.PeriodOfDay(new TimeSpan(09,00,0), new TimeSpan(12,00,0)) }&lt;br /&gt;
                },&lt;br /&gt;
                &amp;quot;801&amp;quot;,&lt;br /&gt;
                new[] { &amp;quot;*&amp;quot; },   // Tous les DIDs&lt;br /&gt;
                new[] { &amp;quot;*&amp;quot; }    // Tous les callers&lt;br /&gt;
            ),&lt;br /&gt;
			&lt;br /&gt;
			 // Règle 2 — Mairie fermée en semaine ( routage vers le 800 )&lt;br /&gt;
            new RoutingRule(&lt;br /&gt;
                new Schedule(RuleHoursType.SpecificHours)&lt;br /&gt;
                {&lt;br /&gt;
					{ DayOfWeek.Monday,    new Schedule.PeriodOfDay(new TimeSpan(8,00,0), new TimeSpan(14,00,0)) },&lt;br /&gt;
     				{ DayOfWeek.Monday,    new Schedule.PeriodOfDay(new TimeSpan(17,00,0), new TimeSpan(24,00,0)) },&lt;br /&gt;
					{ DayOfWeek.Tuesday,    new Schedule.PeriodOfDay(new TimeSpan(0,00,0), new TimeSpan(14,00,0)) },&lt;br /&gt;
					{ DayOfWeek.Tuesday,    new Schedule.PeriodOfDay(new TimeSpan(17,00,0), new TimeSpan(24,00,0)) },&lt;br /&gt;
					{ DayOfWeek.Wednesday,    new Schedule.PeriodOfDay(new TimeSpan(0,00,0), new TimeSpan(09,00,0)) },&lt;br /&gt;
					{ DayOfWeek.Wednesday,    new Schedule.PeriodOfDay(new TimeSpan(12,00,0), new TimeSpan(24,00,0)) },&lt;br /&gt;
      				{ DayOfWeek.Thursday,    new Schedule.PeriodOfDay(new TimeSpan(0,00,0), new TimeSpan(09,00,0)) },&lt;br /&gt;
					{ DayOfWeek.Thursday,    new Schedule.PeriodOfDay(new TimeSpan(12,00,0), new TimeSpan(24,00,0)) },&lt;br /&gt;
      				{ DayOfWeek.Friday,    new Schedule.PeriodOfDay(new TimeSpan(0,00,0), new TimeSpan(09,00,0)) },&lt;br /&gt;
					{ DayOfWeek.Friday,    new Schedule.PeriodOfDay(new TimeSpan(12,00,0), new TimeSpan(24,00,0)) }&lt;br /&gt;
                },&lt;br /&gt;
                &amp;quot;800&amp;quot;,&lt;br /&gt;
                new[] { &amp;quot;*&amp;quot; },&lt;br /&gt;
                new[] { &amp;quot;*&amp;quot; }&lt;br /&gt;
            ),&lt;br /&gt;
			&lt;br /&gt;
			 // Règle 3 — Mairie fermée le week-end ( vendredi 16h30 au lundi ? )&lt;br /&gt;
            new RoutingRule(&lt;br /&gt;
                new Schedule(RuleHoursType.SpecificHours)&lt;br /&gt;
                {&lt;br /&gt;
					&lt;br /&gt;
					{ DayOfWeek.Friday,    new Schedule.PeriodOfDay(new TimeSpan(16,30,0), new TimeSpan(24,00,0)) },&lt;br /&gt;
					{ DayOfWeek.Saturday, new Schedule.PeriodOfDay(new TimeSpan(0,00,0), new TimeSpan(24,00,0)) },&lt;br /&gt;
					{ DayOfWeek.Sunday, new Schedule.PeriodOfDay(new TimeSpan(0,00,0), new TimeSpan(24,00,0)) }&lt;br /&gt;
      				{ DayOfWeek.Monday, new Schedule.PeriodOfDay(new TimeSpan(0,00,0), new TimeSpan(08,00,0)) }&lt;br /&gt;
                },&lt;br /&gt;
                &amp;quot;804&amp;quot;,&lt;br /&gt;
                new[] { &amp;quot;*&amp;quot; },&lt;br /&gt;
                new[] { &amp;quot;*&amp;quot; }&lt;br /&gt;
            ),&lt;br /&gt;
			&lt;br /&gt;
        };&lt;br /&gt;
&lt;br /&gt;
        // Appel de la fonction principale&lt;br /&gt;
&lt;br /&gt;
        public override async void Start()&lt;br /&gt;
        {&lt;br /&gt;
            try&lt;br /&gt;
            {&lt;br /&gt;
                await Task.Run(async () =&amp;gt;&lt;br /&gt;
                {&lt;br /&gt;
                    bool intercepted = false;&lt;br /&gt;
                    var ps = MyCall.PS as PhoneSystem;&lt;br /&gt;
&lt;br /&gt;
                    if (!(MyCall.Caller.DN is ExternalLine externalLine))&lt;br /&gt;
                    {&lt;br /&gt;
                        MyCall.Return(false);&lt;br /&gt;
                        return;&lt;br /&gt;
                    }&lt;br /&gt;
&lt;br /&gt;
                    var DIDNumber = MyCall.Caller[&amp;quot;inbound_did&amp;quot;] ?? &amp;quot;&amp;quot;;&lt;br /&gt;
                    var CallerID = MyCall.Caller.CallerID ?? &amp;quot;&amp;quot;;&lt;br /&gt;
                    var currentTime = externalLine.Now(out var utc, out var timezone, out var groupmode);&lt;br /&gt;
&lt;br /&gt;
                    MyCall.Info($&amp;quot;Incoming call | Caller: {CallerID} | DID: {DIDNumber} | Time: {currentTime}&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
                    foreach (var rule in routingRules)&lt;br /&gt;
                    {&lt;br /&gt;
                        if (!rule.Schedule.IsActiveTime(currentTime))&lt;br /&gt;
                            continue;&lt;br /&gt;
&lt;br /&gt;
                        bool didMatch = rule.DIDs.Contains(&amp;quot;*&amp;quot;) || rule.DIDs.Contains(DIDNumber);&lt;br /&gt;
                        bool callerMatch = rule.Callers.Contains(&amp;quot;*&amp;quot;) || rule.Callers.Contains(CallerID);&lt;br /&gt;
&lt;br /&gt;
                        if (!didMatch || !callerMatch)&lt;br /&gt;
                            continue;&lt;br /&gt;
&lt;br /&gt;
                        var destinationDN = ps.GetDNByNumber(rule.DestinationDN);&lt;br /&gt;
&lt;br /&gt;
                        if (destinationDN == null)&lt;br /&gt;
                        {&lt;br /&gt;
                            MyCall.Error($&amp;quot;Destination {rule.DestinationDN} not found.&amp;quot;);&lt;br /&gt;
                            continue;&lt;br /&gt;
                        }&lt;br /&gt;
&lt;br /&gt;
                        try&lt;br /&gt;
                        {&lt;br /&gt;
                            var result = await MyCall.RouteToAsync(new DestinationStruct(destinationDN));&lt;br /&gt;
                            MyCall.Info($&amp;quot;Routed to {rule.DestinationDN} | Result: {result}&amp;quot;);&lt;br /&gt;
                            intercepted = true;&lt;br /&gt;
                            break; // Stop at first matching rule&lt;br /&gt;
                        }&lt;br /&gt;
                        catch (Exception ex)&lt;br /&gt;
                        {&lt;br /&gt;
                            MyCall.Error($&amp;quot;Routing failed to {rule.DestinationDN}: {ex}&amp;quot;);&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
&lt;br /&gt;
                &lt;br /&gt;
                    // Utilisation de la route par défaut&lt;br /&gt;
                    &lt;br /&gt;
                    if (!intercepted)&lt;br /&gt;
                    {&lt;br /&gt;
                        var fallbackDN = ps.GetDNByNumber(DefaultDestinationDN);&lt;br /&gt;
                        if (fallbackDN != null)&lt;br /&gt;
                        {&lt;br /&gt;
                            try&lt;br /&gt;
                            {&lt;br /&gt;
                                var result = await MyCall.RouteToAsync(new DestinationStruct(fallbackDN));&lt;br /&gt;
                                MyCall.Info($&amp;quot;Fallback routing to {DefaultDestinationDN} | Result: {result}&amp;quot;);&lt;br /&gt;
                                intercepted = true;&lt;br /&gt;
                            }&lt;br /&gt;
                            catch (Exception ex)&lt;br /&gt;
                            {&lt;br /&gt;
                                MyCall.Error($&amp;quot;Fallback routing failed: {ex}&amp;quot;);&lt;br /&gt;
                            }&lt;br /&gt;
                        }&lt;br /&gt;
                        else&lt;br /&gt;
                        {&lt;br /&gt;
                            MyCall.Error($&amp;quot;Fallback DN {DefaultDestinationDN} not found.&amp;quot;);&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
&lt;br /&gt;
                    MyCall.Return(intercepted);&lt;br /&gt;
                });&lt;br /&gt;
            }&lt;br /&gt;
            catch (Exception ex)&lt;br /&gt;
            {&lt;br /&gt;
                MyCall.Error($&amp;quot;Script execution failed: {ex}&amp;quot;);&lt;br /&gt;
                MyCall.Return(false);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Mise en place du script===&lt;br /&gt;
&lt;br /&gt;
Connecté en admin dans 3CX :&lt;br /&gt;
 &lt;br /&gt;
 Admin / Intégrations / Scripts d&#039;appels / + Ajouter personnalisé&lt;br /&gt;
&lt;br /&gt;
[[Fichier:2026-05-27 15h34 23.png|cadre|right]]&lt;br /&gt;
# Nommer le script&lt;br /&gt;
#Choisir &#039;&#039;&#039;Quand cette SDA est composée&#039;&#039;&#039;&lt;br /&gt;
#Choisir la SDA appelée qui va déclencher le script&lt;br /&gt;
#Choisir le scope d&#039;action du script&lt;br /&gt;
#Cliquer sur OK&lt;br /&gt;
#Coller le script préparé dans la zone script&lt;br /&gt;
#Sauvegarder&lt;br /&gt;
&lt;br /&gt;
{{Valide|v20}}&lt;br /&gt;
[[Catégorie:3CX]]&lt;/div&gt;</summary>
		<author><name>Anthony</name></author>
	</entry>
	<entry>
		<id>https://indywiki.fr/index.php?title=Fichier:2026-06-01_16h28_48.png&amp;diff=22286</id>
		<title>Fichier:2026-06-01 16h28 48.png</title>
		<link rel="alternate" type="text/html" href="https://indywiki.fr/index.php?title=Fichier:2026-06-01_16h28_48.png&amp;diff=22286"/>
		<updated>2026-06-01T14:29:14Z</updated>

		<summary type="html">&lt;p&gt;Anthony : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;2026-06-01 16h28 48&lt;/div&gt;</summary>
		<author><name>Anthony</name></author>
	</entry>
	<entry>
		<id>https://indywiki.fr/index.php?title=Script_de_routage_des_appels&amp;diff=22285</id>
		<title>Script de routage des appels</title>
		<link rel="alternate" type="text/html" href="https://indywiki.fr/index.php?title=Script_de_routage_des_appels&amp;diff=22285"/>
		<updated>2026-05-27T13:57:19Z</updated>

		<summary type="html">&lt;p&gt;Anthony : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Permet en fonction du moment de la semaine de router les appels vers telle ou telle destination.&lt;br /&gt;
&#039;&#039;&#039;Nécessite de supprimer les horaires de fermeture&#039;&#039;&#039; sur le département / instance 3CX ( c&#039;est le script qui gère )&lt;br /&gt;
&lt;br /&gt;
⚠️ les règles sont évaluées dans l&#039;ordre de leur apparition, il faut donc les déclarer de la plus spécifique à la plus générale ⚠️&lt;br /&gt;
&lt;br /&gt;
===Le script===&lt;br /&gt;
&lt;br /&gt;
Seules les lignes jaune requiert d&#039;être éditées. Si plus de règles sont à prévoir, dupliquer les sections &#039;&#039;&#039;new RoutingRule&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
* Ligne 16 : si aucune règle dans le script ne permet de déterminer un chemin, alors c&#039;est cette extension la cible&lt;br /&gt;
* Ligne 44 : Pour chaque règle, il faut définir les jours et horaires. sur cet exemple, le lundi de 14 à 17h, c&#039;est la règle 1 qui s&#039;applique.&lt;br /&gt;
* Ligne 50 : C&#039;est l&#039;extension qui va être visée par la règle, peut être un utilisateur, un SVI, un groupe , une file d&#039;attente.&lt;br /&gt;
* Ligne 51 : DID : ce filtre permet de tester le &#039;&#039;&#039;numéro appelé&#039;&#039;&#039; ( SDA  actif sur le système). En pratique on ne s&#039;en sert pas ici car le filtre se fait en amont de l&#039;[[Script_de_routage_des_appels#Mise_en_place_du_script|appel du script]]. Mais possible. La syntaxe &#039;&#039;&#039;*&#039;&#039;&#039; permet de tout laisser passer&lt;br /&gt;
* Ligne 52 : Callers, on peut filtrer sur le &#039;&#039;&#039;numéros de l&#039;appelant&#039;&#039;&#039;. La syntaxe &#039;&#039;&#039;*&#039;&#039;&#039; permet de tout laisser passer&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;csharp&amp;quot; line highlight=&amp;quot;16,44,50-52&amp;quot;&amp;gt;&lt;br /&gt;
#nullable disable&lt;br /&gt;
using CallFlow;&lt;br /&gt;
using System;&lt;br /&gt;
using System.Threading.Tasks;&lt;br /&gt;
using TCX.Configuration;&lt;br /&gt;
using TCX.PBXAPI;&lt;br /&gt;
using System.Collections.Generic;&lt;br /&gt;
using System.Linq;&lt;br /&gt;
using CallFlow.CFD;&lt;br /&gt;
&lt;br /&gt;
namespace interceptcall&lt;br /&gt;
{&lt;br /&gt;
    public class InterceptInboundCall : ScriptBase&amp;lt;InterceptInboundCall&amp;gt;&lt;br /&gt;
    {&lt;br /&gt;
        // Destination par Défaut, à priori jamais utilisé car ce numéro doit toujours être joignable&lt;br /&gt;
        const string DefaultDestinationDN = &amp;quot;812&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
        // Structure d&#039;une règle de routage&lt;br /&gt;
        class RoutingRule&lt;br /&gt;
        {&lt;br /&gt;
            public Schedule Schedule { get; set; }&lt;br /&gt;
            public string DestinationDN { get; set; }&lt;br /&gt;
            public string[] DIDs { get; set; }&lt;br /&gt;
            public string[] Callers { get; set; }&lt;br /&gt;
&lt;br /&gt;
            public RoutingRule(Schedule schedule, string destinationDN, string[] dids, string[] callers)&lt;br /&gt;
            {&lt;br /&gt;
                Schedule = schedule;&lt;br /&gt;
                DestinationDN = destinationDN;&lt;br /&gt;
                DIDs = dids;&lt;br /&gt;
                Callers = callers;&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
		// Règle(s) de routage &amp;quot;First Match&amp;quot; : La première règle satisfaite est éxécutée, les suivantes sont ignorées&lt;br /&gt;
&lt;br /&gt;
       static readonly List&amp;lt;RoutingRule&amp;gt; routingRules = new List&amp;lt;RoutingRule&amp;gt;&lt;br /&gt;
        {&lt;br /&gt;
            // Règle 1 - Mairie ouverte - routage vers le 801 qui route vers le 100 ( pas de changements&lt;br /&gt;
            new RoutingRule(&lt;br /&gt;
                new Schedule(RuleHoursType.SpecificHours)&lt;br /&gt;
                {&lt;br /&gt;
					{ DayOfWeek.Monday,    new Schedule.PeriodOfDay(new TimeSpan(14,00,0), new TimeSpan(17,00,0)) },&lt;br /&gt;
					{ DayOfWeek.Tuesday,    new Schedule.PeriodOfDay(new TimeSpan(14,00,0), new TimeSpan(17,00,0)) },&lt;br /&gt;
					{ DayOfWeek.Wednesday,    new Schedule.PeriodOfDay(new TimeSpan(09,00,0), new TimeSpan(12,00,0)) },&lt;br /&gt;
                    { DayOfWeek.Thursday,    new Schedule.PeriodOfDay(new TimeSpan(09,00,0), new TimeSpan(12,00,0)) },&lt;br /&gt;
					{ DayOfWeek.Friday,    new Schedule.PeriodOfDay(new TimeSpan(09,00,0), new TimeSpan(12,00,0)) }&lt;br /&gt;
                },&lt;br /&gt;
                &amp;quot;801&amp;quot;,&lt;br /&gt;
                new[] { &amp;quot;*&amp;quot; },   // Tous les DIDs&lt;br /&gt;
                new[] { &amp;quot;*&amp;quot; }    // Tous les callers&lt;br /&gt;
            ),&lt;br /&gt;
			&lt;br /&gt;
			 // Règle 2 — Mairie fermée en semaine ( routage vers le 800 )&lt;br /&gt;
            new RoutingRule(&lt;br /&gt;
                new Schedule(RuleHoursType.SpecificHours)&lt;br /&gt;
                {&lt;br /&gt;
					{ DayOfWeek.Monday,    new Schedule.PeriodOfDay(new TimeSpan(8,00,0), new TimeSpan(14,00,0)) },&lt;br /&gt;
     				{ DayOfWeek.Monday,    new Schedule.PeriodOfDay(new TimeSpan(17,00,0), new TimeSpan(24,00,0)) },&lt;br /&gt;
					{ DayOfWeek.Tuesday,    new Schedule.PeriodOfDay(new TimeSpan(0,00,0), new TimeSpan(14,00,0)) },&lt;br /&gt;
					{ DayOfWeek.Tuesday,    new Schedule.PeriodOfDay(new TimeSpan(17,00,0), new TimeSpan(24,00,0)) },&lt;br /&gt;
					{ DayOfWeek.Wednesday,    new Schedule.PeriodOfDay(new TimeSpan(0,00,0), new TimeSpan(09,00,0)) },&lt;br /&gt;
					{ DayOfWeek.Wednesday,    new Schedule.PeriodOfDay(new TimeSpan(12,00,0), new TimeSpan(24,00,0)) },&lt;br /&gt;
      				{ DayOfWeek.Thursday,    new Schedule.PeriodOfDay(new TimeSpan(0,00,0), new TimeSpan(09,00,0)) },&lt;br /&gt;
					{ DayOfWeek.Thursday,    new Schedule.PeriodOfDay(new TimeSpan(12,00,0), new TimeSpan(24,00,0)) },&lt;br /&gt;
      				{ DayOfWeek.Friday,    new Schedule.PeriodOfDay(new TimeSpan(0,00,0), new TimeSpan(09,00,0)) },&lt;br /&gt;
					{ DayOfWeek.Friday,    new Schedule.PeriodOfDay(new TimeSpan(12,00,0), new TimeSpan(24,00,0)) }&lt;br /&gt;
                },&lt;br /&gt;
                &amp;quot;800&amp;quot;,&lt;br /&gt;
                new[] { &amp;quot;*&amp;quot; },&lt;br /&gt;
                new[] { &amp;quot;*&amp;quot; }&lt;br /&gt;
            ),&lt;br /&gt;
			&lt;br /&gt;
			 // Règle 3 — Mairie fermée le week-end ( vendredi 16h30 au lundi ? )&lt;br /&gt;
            new RoutingRule(&lt;br /&gt;
                new Schedule(RuleHoursType.SpecificHours)&lt;br /&gt;
                {&lt;br /&gt;
					&lt;br /&gt;
					{ DayOfWeek.Friday,    new Schedule.PeriodOfDay(new TimeSpan(16,30,0), new TimeSpan(24,00,0)) },&lt;br /&gt;
					{ DayOfWeek.Saturday, new Schedule.PeriodOfDay(new TimeSpan(0,00,0), new TimeSpan(24,00,0)) },&lt;br /&gt;
					{ DayOfWeek.Sunday, new Schedule.PeriodOfDay(new TimeSpan(0,00,0), new TimeSpan(24,00,0)) }&lt;br /&gt;
      				{ DayOfWeek.Monday, new Schedule.PeriodOfDay(new TimeSpan(0,00,0), new TimeSpan(08,00,0)) }&lt;br /&gt;
                },&lt;br /&gt;
                &amp;quot;804&amp;quot;,&lt;br /&gt;
                new[] { &amp;quot;*&amp;quot; },&lt;br /&gt;
                new[] { &amp;quot;*&amp;quot; }&lt;br /&gt;
            ),&lt;br /&gt;
			&lt;br /&gt;
        };&lt;br /&gt;
&lt;br /&gt;
        // Appel de la fonction principale&lt;br /&gt;
&lt;br /&gt;
        public override async void Start()&lt;br /&gt;
        {&lt;br /&gt;
            try&lt;br /&gt;
            {&lt;br /&gt;
                await Task.Run(async () =&amp;gt;&lt;br /&gt;
                {&lt;br /&gt;
                    bool intercepted = false;&lt;br /&gt;
                    var ps = MyCall.PS as PhoneSystem;&lt;br /&gt;
&lt;br /&gt;
                    if (!(MyCall.Caller.DN is ExternalLine externalLine))&lt;br /&gt;
                    {&lt;br /&gt;
                        MyCall.Return(false);&lt;br /&gt;
                        return;&lt;br /&gt;
                    }&lt;br /&gt;
&lt;br /&gt;
                    var DIDNumber = MyCall.Caller[&amp;quot;inbound_did&amp;quot;] ?? &amp;quot;&amp;quot;;&lt;br /&gt;
                    var CallerID = MyCall.Caller.CallerID ?? &amp;quot;&amp;quot;;&lt;br /&gt;
                    var currentTime = externalLine.Now(out var utc, out var timezone, out var groupmode);&lt;br /&gt;
&lt;br /&gt;
                    MyCall.Info($&amp;quot;Incoming call | Caller: {CallerID} | DID: {DIDNumber} | Time: {currentTime}&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
                    foreach (var rule in routingRules)&lt;br /&gt;
                    {&lt;br /&gt;
                        if (!rule.Schedule.IsActiveTime(currentTime))&lt;br /&gt;
                            continue;&lt;br /&gt;
&lt;br /&gt;
                        bool didMatch = rule.DIDs.Contains(&amp;quot;*&amp;quot;) || rule.DIDs.Contains(DIDNumber);&lt;br /&gt;
                        bool callerMatch = rule.Callers.Contains(&amp;quot;*&amp;quot;) || rule.Callers.Contains(CallerID);&lt;br /&gt;
&lt;br /&gt;
                        if (!didMatch || !callerMatch)&lt;br /&gt;
                            continue;&lt;br /&gt;
&lt;br /&gt;
                        var destinationDN = ps.GetDNByNumber(rule.DestinationDN);&lt;br /&gt;
&lt;br /&gt;
                        if (destinationDN == null)&lt;br /&gt;
                        {&lt;br /&gt;
                            MyCall.Error($&amp;quot;Destination {rule.DestinationDN} not found.&amp;quot;);&lt;br /&gt;
                            continue;&lt;br /&gt;
                        }&lt;br /&gt;
&lt;br /&gt;
                        try&lt;br /&gt;
                        {&lt;br /&gt;
                            var result = await MyCall.RouteToAsync(new DestinationStruct(destinationDN));&lt;br /&gt;
                            MyCall.Info($&amp;quot;Routed to {rule.DestinationDN} | Result: {result}&amp;quot;);&lt;br /&gt;
                            intercepted = true;&lt;br /&gt;
                            break; // Stop at first matching rule&lt;br /&gt;
                        }&lt;br /&gt;
                        catch (Exception ex)&lt;br /&gt;
                        {&lt;br /&gt;
                            MyCall.Error($&amp;quot;Routing failed to {rule.DestinationDN}: {ex}&amp;quot;);&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
&lt;br /&gt;
                &lt;br /&gt;
                    // Utilisation de la route par défaut&lt;br /&gt;
                    &lt;br /&gt;
                    if (!intercepted)&lt;br /&gt;
                    {&lt;br /&gt;
                        var fallbackDN = ps.GetDNByNumber(DefaultDestinationDN);&lt;br /&gt;
                        if (fallbackDN != null)&lt;br /&gt;
                        {&lt;br /&gt;
                            try&lt;br /&gt;
                            {&lt;br /&gt;
                                var result = await MyCall.RouteToAsync(new DestinationStruct(fallbackDN));&lt;br /&gt;
                                MyCall.Info($&amp;quot;Fallback routing to {DefaultDestinationDN} | Result: {result}&amp;quot;);&lt;br /&gt;
                                intercepted = true;&lt;br /&gt;
                            }&lt;br /&gt;
                            catch (Exception ex)&lt;br /&gt;
                            {&lt;br /&gt;
                                MyCall.Error($&amp;quot;Fallback routing failed: {ex}&amp;quot;);&lt;br /&gt;
                            }&lt;br /&gt;
                        }&lt;br /&gt;
                        else&lt;br /&gt;
                        {&lt;br /&gt;
                            MyCall.Error($&amp;quot;Fallback DN {DefaultDestinationDN} not found.&amp;quot;);&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
&lt;br /&gt;
                    MyCall.Return(intercepted);&lt;br /&gt;
                });&lt;br /&gt;
            }&lt;br /&gt;
            catch (Exception ex)&lt;br /&gt;
            {&lt;br /&gt;
                MyCall.Error($&amp;quot;Script execution failed: {ex}&amp;quot;);&lt;br /&gt;
                MyCall.Return(false);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Mise en place du script===&lt;br /&gt;
&lt;br /&gt;
Connecté en admin dans 3CX :&lt;br /&gt;
 &lt;br /&gt;
 Admin / Intégrations / Scripts d&#039;appels / + Ajouter personnalisé&lt;br /&gt;
&lt;br /&gt;
[[Fichier:2026-05-27 15h34 23.png|cadre|right]]&lt;br /&gt;
# Nommer le script&lt;br /&gt;
#Choisir &#039;&#039;&#039;Quand cette SDA est composée&#039;&#039;&#039;&lt;br /&gt;
#Choisir la SDA appelée qui va déclencher le script&lt;br /&gt;
#Choisir le scope d&#039;action du script&lt;br /&gt;
#Cliquer sur OK&lt;br /&gt;
#Coller le script préparé dans la zone script&lt;br /&gt;
#Sauvegarder&lt;br /&gt;
&lt;br /&gt;
{{Valide|v20}}&lt;br /&gt;
[[Catégorie:3CX]]&lt;/div&gt;</summary>
		<author><name>Anthony</name></author>
	</entry>
	<entry>
		<id>https://indywiki.fr/index.php?title=Astreinte&amp;diff=22284</id>
		<title>Astreinte</title>
		<link rel="alternate" type="text/html" href="https://indywiki.fr/index.php?title=Astreinte&amp;diff=22284"/>
		<updated>2026-05-27T13:56:53Z</updated>

		<summary type="html">&lt;p&gt;Anthony : /* Configuration concrète */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;===Principe===&lt;br /&gt;
On paramètre le statut choisi pour l&#039;astreinte en renvoi vers &#039;&#039;&#039;mon mobile&#039;&#039;&#039;. Un script viendra modifier le statut de l&#039;extension cible ainsi que son numéro de contact mobile, prénom et nom. Ce script déclenchable par l&#039;appel à un code court, paramétrable si on le souhaite sur une BLF. &lt;br /&gt;
&lt;br /&gt;
===Déclaration du script===&lt;br /&gt;
[[Fichier:2026-04-02 17h11 35.png|vignette]]&lt;br /&gt;
&lt;br /&gt;
Rendez-vous dans :&lt;br /&gt;
&lt;br /&gt;
 Admin / Intégrations / Scripts d&#039;appels / + Ajouter personnalisé&lt;br /&gt;
&lt;br /&gt;
#Donner un nom au traitement de l&#039;appel. Exemple : &#039;&#039;&#039;astreinte_weekend&#039;&#039;&#039;&lt;br /&gt;
#Créer un code de raccourci, ce qui permettra d&#039;exécuter le script simplement en appelant ce code, et in fine par une BLF. Exemple : &#039;&#039;&#039;*99&#039;&#039;&#039;&lt;br /&gt;
#OK&lt;br /&gt;
#Coller dans le champ script le script paramétré ( voir section suivante )&lt;br /&gt;
#Sauvegarder&lt;br /&gt;
#Un message doit indiquer &#039;&#039;&#039;Compilation réussie !&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Le script d&#039;astreinte===&lt;br /&gt;
&lt;br /&gt;
L&#039;éxécution du script va modifier l&#039;extension &#039;&#039;&#039;targetExtNum &#039;&#039;&#039;, il va le basculer sur le statut &#039;&#039;&#039;profileName &#039;&#039;&#039;, modifier son mobile de contact &#039;&#039;&#039;mobileElu &#039;&#039;&#039;, son nom et prénom.&lt;br /&gt;
&lt;br /&gt;
Il faut donc seulement modifier les lignes surlignés dans le code ci-dessous :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;csharp&amp;quot; line highlight=&amp;quot;14-17&amp;quot;&amp;gt;&lt;br /&gt;
using System;&lt;br /&gt;
using System.Threading.Tasks;&lt;br /&gt;
using TCX.Configuration;&lt;br /&gt;
using CallFlow;&lt;br /&gt;
using System.Linq;&lt;br /&gt;
&lt;br /&gt;
namespace dummy&lt;br /&gt;
{&lt;br /&gt;
    public class SetDynamicAstreinte : ScriptBase&amp;lt;SetDynamicAstreinte&amp;gt;&lt;br /&gt;
    {&lt;br /&gt;
        // ============================================================&lt;br /&gt;
        // CONFIGURATION — modifier uniquement ces lignes par script&lt;br /&gt;
        // ============================================================&lt;br /&gt;
        private const string TARGET_EXT   = &amp;quot;111&amp;quot;;&lt;br /&gt;
        private const string MOBILE_EXT   = &amp;quot;0612345678&amp;quot;;&lt;br /&gt;
        private const string PRENOM_EXT   = &amp;quot;Claude&amp;quot;;&lt;br /&gt;
        private const string NOM_EXT      = &amp;quot;IA&amp;quot;;&lt;br /&gt;
		 // ============================================================&lt;br /&gt;
        &lt;br /&gt;
		private const string PROFILE_NAME = &amp;quot;Away&amp;quot;;&lt;br /&gt;
       &lt;br /&gt;
        public override Task&amp;lt;bool&amp;gt; StartAsync()&lt;br /&gt;
        {&lt;br /&gt;
            try&lt;br /&gt;
            {&lt;br /&gt;
                IPhoneSystem ps = PhoneSystem.Root;&lt;br /&gt;
                Extension ext = ps.GetDNByNumber(TARGET_EXT) as Extension;&lt;br /&gt;
                if (ext == null)&lt;br /&gt;
                    return Task.FromResult(false);&lt;br /&gt;
&lt;br /&gt;
                // 1. Nom / Prénom&lt;br /&gt;
                ext.FirstName = PRENOM_EXT;&lt;br /&gt;
                ext.LastName  = NOM_EXT;&lt;br /&gt;
&lt;br /&gt;
                // 2. Numéro mobile&lt;br /&gt;
                ext.SetProperty(&amp;quot;MOBILENUMBER&amp;quot;, MOBILE_EXT);&lt;br /&gt;
&lt;br /&gt;
                // 3. Trouver le profil Away&lt;br /&gt;
                FwdProfile targetProfile = ext.FwdProfiles&lt;br /&gt;
                    .FirstOrDefault(p =&amp;gt; p.Name.Equals(&lt;br /&gt;
                        PROFILE_NAME, StringComparison.OrdinalIgnoreCase));&lt;br /&gt;
&lt;br /&gt;
                if (targetProfile != null)&lt;br /&gt;
                {&lt;br /&gt;
                    // AwayRoute, Internal, External sont read-only&lt;br /&gt;
                    // mais ce sont des références : on peut modifier&lt;br /&gt;
                    // leurs membres si ceux-ci sont accessibles en écriture&lt;br /&gt;
                    AwayRouting route = targetProfile.AwayRoute;&lt;br /&gt;
&lt;br /&gt;
                    // Capturer les HoursDestination comme variables locales&lt;br /&gt;
                    // (objets référence — la propriété est read-only,&lt;br /&gt;
                    //  mais l&#039;objet pointé est modifiable)&lt;br /&gt;
                    HoursDestination internalHours = route.Internal;&lt;br /&gt;
                    HoursDestination externalHours = route.External;&lt;br /&gt;
&lt;br /&gt;
                    // Capturer AllHours (struct) → modifier → réassigner&lt;br /&gt;
                    DestinationStruct destInternal = internalHours.AllHours;&lt;br /&gt;
                    destInternal.To               = DestinationType.Boomerang;&lt;br /&gt;
                    destInternal.External         = MOBILE_EXT;&lt;br /&gt;
                    internalHours.AllHours        = destInternal;&lt;br /&gt;
&lt;br /&gt;
                    DestinationStruct destExternal = externalHours.AllHours;&lt;br /&gt;
                    destExternal.To               = DestinationType.Boomerang;&lt;br /&gt;
                    destExternal.External         = MOBILE_EXT;&lt;br /&gt;
                    externalHours.AllHours        = destExternal;&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                // 4. Sauvegarder&lt;br /&gt;
                ext.Save();&lt;br /&gt;
&lt;br /&gt;
                // 5. Recharger et basculer le profil&lt;br /&gt;
                ext = ps.GetDNByNumber(TARGET_EXT) as Extension;&lt;br /&gt;
                if (ext == null)&lt;br /&gt;
                    return Task.FromResult(false);&lt;br /&gt;
&lt;br /&gt;
                FwdProfile profile = ext.FwdProfiles&lt;br /&gt;
                    .FirstOrDefault(p =&amp;gt; p.Name.Equals(&lt;br /&gt;
                        PROFILE_NAME, StringComparison.OrdinalIgnoreCase));&lt;br /&gt;
&lt;br /&gt;
                if (profile != null)&lt;br /&gt;
                {&lt;br /&gt;
                    ext.CurrentProfile = profile;&lt;br /&gt;
                    ext.Save();&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                return Task.FromResult(true);&lt;br /&gt;
            }&lt;br /&gt;
            catch (Exception)&lt;br /&gt;
            {&lt;br /&gt;
                return Task.FromResult(false);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Le script de retour à la normale===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;csharp&amp;quot; line highlight=&amp;quot;14-16&amp;quot;&amp;gt;&lt;br /&gt;
using System;&lt;br /&gt;
using System.Threading.Tasks;&lt;br /&gt;
using TCX.Configuration;&lt;br /&gt;
using CallFlow;&lt;br /&gt;
using System.Linq;&lt;br /&gt;
&lt;br /&gt;
namespace dummy&lt;br /&gt;
{&lt;br /&gt;
    public class ResetAstreinte : ScriptBase&amp;lt;ResetAstreinte&amp;gt;&lt;br /&gt;
    {&lt;br /&gt;
        // ============================================================&lt;br /&gt;
        // CONFIGURATION — modifier uniquement ces lignes par script&lt;br /&gt;
        // ============================================================&lt;br /&gt;
        private const string TARGET_EXT   = &amp;quot;111&amp;quot;;&lt;br /&gt;
        private const string PRENOM_EXT   = &amp;quot;Accueil&amp;quot;;&lt;br /&gt;
        private const string NOM_EXT      = &amp;quot;Mairie&amp;quot;;&lt;br /&gt;
        // ============================================================&lt;br /&gt;
&lt;br /&gt;
        public override Task&amp;lt;bool&amp;gt; StartAsync()&lt;br /&gt;
        {&lt;br /&gt;
            try&lt;br /&gt;
            {&lt;br /&gt;
                IPhoneSystem ps = PhoneSystem.Root;&lt;br /&gt;
                Extension ext = ps.GetDNByNumber(TARGET_EXT) as Extension;&lt;br /&gt;
                if (ext == null)&lt;br /&gt;
                    return Task.FromResult(false);&lt;br /&gt;
&lt;br /&gt;
                // 1. Remettre le nom générique&lt;br /&gt;
                ext.FirstName = PRENOM_EXT;&lt;br /&gt;
                ext.LastName  = NOM_EXT;&lt;br /&gt;
&lt;br /&gt;
                // 2. Vider le numéro mobile&lt;br /&gt;
                ext.SetProperty(&amp;quot;MOBILENUMBER&amp;quot;, &amp;quot;&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
                // 3. Résoudre le DN pour la messagerie vocale&lt;br /&gt;
                DN targetDN = ps.GetDNByNumber(TARGET_EXT);&lt;br /&gt;
&lt;br /&gt;
                // 4. Remettre AwayRoute → messagerie vocale&lt;br /&gt;
                FwdProfile awayProfile = ext.FwdProfiles&lt;br /&gt;
                    .FirstOrDefault(p =&amp;gt; p.Name.Equals(&lt;br /&gt;
                        &amp;quot;Away&amp;quot;, StringComparison.OrdinalIgnoreCase));&lt;br /&gt;
&lt;br /&gt;
                if (awayProfile != null)&lt;br /&gt;
                {&lt;br /&gt;
                    AwayRouting route = awayProfile.AwayRoute;&lt;br /&gt;
&lt;br /&gt;
                    HoursDestination internalHours = route.Internal;&lt;br /&gt;
                    HoursDestination externalHours = route.External;&lt;br /&gt;
&lt;br /&gt;
                    DestinationStruct destInternal = internalHours.AllHours;&lt;br /&gt;
                    destInternal.To               = DestinationType.VoiceMail;&lt;br /&gt;
                    destInternal.Internal         = targetDN;&lt;br /&gt;
                    destInternal.External         = &amp;quot;&amp;quot;;&lt;br /&gt;
                    internalHours.AllHours        = destInternal;&lt;br /&gt;
&lt;br /&gt;
                    DestinationStruct destExternal = externalHours.AllHours;&lt;br /&gt;
                    destExternal.To               = DestinationType.VoiceMail;&lt;br /&gt;
                    destExternal.Internal         = targetDN;&lt;br /&gt;
                    destExternal.External         = &amp;quot;&amp;quot;;&lt;br /&gt;
                    externalHours.AllHours        = destExternal;&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                // 5. Sauvegarder&lt;br /&gt;
                ext.Save();&lt;br /&gt;
&lt;br /&gt;
                // 6. Recharger et basculer vers Available&lt;br /&gt;
                ext = ps.GetDNByNumber(TARGET_EXT) as Extension;&lt;br /&gt;
                if (ext == null)&lt;br /&gt;
                    return Task.FromResult(false);&lt;br /&gt;
&lt;br /&gt;
                FwdProfile profile = ext.FwdProfiles&lt;br /&gt;
                    .FirstOrDefault(p =&amp;gt; p.Name.Equals(&lt;br /&gt;
                        &amp;quot;Available&amp;quot;, StringComparison.OrdinalIgnoreCase));&lt;br /&gt;
&lt;br /&gt;
                if (profile != null)&lt;br /&gt;
                {&lt;br /&gt;
                    ext.CurrentProfile = profile;&lt;br /&gt;
                    ext.Save();&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                return Task.FromResult(true);&lt;br /&gt;
            }&lt;br /&gt;
            catch (Exception)&lt;br /&gt;
            {&lt;br /&gt;
                return Task.FromResult(false);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Configuration concrète===&lt;br /&gt;
&lt;br /&gt;
On a besoin de gérer deux astreintes. Le poste Accueil reçoit les appels en temps normal&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Extraits de chaque script&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;Marcel Patulacci&#039;&#039;&#039; || &#039;&#039;&#039;Jean-Michel Apeuprè&#039;&#039;&#039;|| &#039;&#039;&#039;Poste accueil &#039;&#039;&#039; hors période d&#039;astreinte&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;syntaxhighlight lang=&amp;quot;csharp&amp;quot; line highlight=&amp;quot;4-7&amp;quot;&amp;gt;&lt;br /&gt;
public class SetDynamicAstreinte : ScriptBase&amp;lt;SetDynamicAstreinte&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
 // modifier uniquement ces lignes :&lt;br /&gt;
private const string TARGET_EXT   = &amp;quot;111&amp;quot;;&lt;br /&gt;
private const string MOBILE_EXT   = &amp;quot;0612345678&amp;quot;;&lt;br /&gt;
private const string PRENOM_EXT   = &amp;quot;Marcel&amp;quot;;&lt;br /&gt;
private const string NOM_EXT      = &amp;quot;Patulacci&amp;quot;;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt; || &amp;lt;syntaxhighlight lang=&amp;quot;csharp&amp;quot; line highlight=&amp;quot;4-7&amp;quot;&amp;gt;&lt;br /&gt;
public class SetDynamicAstreinte : ScriptBase&amp;lt;SetDynamicAstreinte&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
// Modifier uniquement ces lignes&lt;br /&gt;
private const string TARGET_EXT   = &amp;quot;111&amp;quot;;&lt;br /&gt;
private const string MOBILE_EXT   = &amp;quot;0699999999&amp;quot;;&lt;br /&gt;
private const string PRENOM_EXT   = &amp;quot;Jean-Michel&amp;quot;;&lt;br /&gt;
private const string NOM_EXT      = &amp;quot;Apeuprè&amp;quot;; &lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;|| &amp;lt;syntaxhighlight lang=&amp;quot;csharp&amp;quot; line highlight=&amp;quot;4-6&amp;quot;&amp;gt;&lt;br /&gt;
public class ResetAstreinte : ScriptBase&amp;lt;ResetAstreinte&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
// Modifier uniquement ces lignes :&lt;br /&gt;
private const string TARGET_EXT   = &amp;quot;111&amp;quot;;&lt;br /&gt;
private const string PRENOM_EXT   = &amp;quot;Accueil&amp;quot;;&lt;br /&gt;
private const string NOM_EXT      = &amp;quot;Mairie&amp;quot;; &lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Une fois les 3 scripts produits, passer à l&#039;étape [[Astreinte#Déclaration_du_script|Déclaration du script]] qui va permettre d&#039;affecter un code court à chaque script.&lt;br /&gt;
Exemple : &lt;br /&gt;
* *90 pour hors période d&#039;astreinte&lt;br /&gt;
* *91 pour Jean-Michel&lt;br /&gt;
* *92 pour Marcel&lt;br /&gt;
&lt;br /&gt;
On peut communiquer les codes aux personnes habilitées à gérer le système d&#039;astreinte et aller jusqu&#039;à paramétrer des BLF pour faciliter la vie d&#039;une secrétaire par exemple.&lt;br /&gt;
&lt;br /&gt;
{{Valide|v20}}&lt;br /&gt;
[[Catégorie:3CX]]&lt;/div&gt;</summary>
		<author><name>Anthony</name></author>
	</entry>
	<entry>
		<id>https://indywiki.fr/index.php?title=Astreinte&amp;diff=22283</id>
		<title>Astreinte</title>
		<link rel="alternate" type="text/html" href="https://indywiki.fr/index.php?title=Astreinte&amp;diff=22283"/>
		<updated>2026-05-27T13:55:51Z</updated>

		<summary type="html">&lt;p&gt;Anthony : /* Configuration concrète */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;===Principe===&lt;br /&gt;
On paramètre le statut choisi pour l&#039;astreinte en renvoi vers &#039;&#039;&#039;mon mobile&#039;&#039;&#039;. Un script viendra modifier le statut de l&#039;extension cible ainsi que son numéro de contact mobile, prénom et nom. Ce script déclenchable par l&#039;appel à un code court, paramétrable si on le souhaite sur une BLF. &lt;br /&gt;
&lt;br /&gt;
===Déclaration du script===&lt;br /&gt;
[[Fichier:2026-04-02 17h11 35.png|vignette]]&lt;br /&gt;
&lt;br /&gt;
Rendez-vous dans :&lt;br /&gt;
&lt;br /&gt;
 Admin / Intégrations / Scripts d&#039;appels / + Ajouter personnalisé&lt;br /&gt;
&lt;br /&gt;
#Donner un nom au traitement de l&#039;appel. Exemple : &#039;&#039;&#039;astreinte_weekend&#039;&#039;&#039;&lt;br /&gt;
#Créer un code de raccourci, ce qui permettra d&#039;exécuter le script simplement en appelant ce code, et in fine par une BLF. Exemple : &#039;&#039;&#039;*99&#039;&#039;&#039;&lt;br /&gt;
#OK&lt;br /&gt;
#Coller dans le champ script le script paramétré ( voir section suivante )&lt;br /&gt;
#Sauvegarder&lt;br /&gt;
#Un message doit indiquer &#039;&#039;&#039;Compilation réussie !&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Le script d&#039;astreinte===&lt;br /&gt;
&lt;br /&gt;
L&#039;éxécution du script va modifier l&#039;extension &#039;&#039;&#039;targetExtNum &#039;&#039;&#039;, il va le basculer sur le statut &#039;&#039;&#039;profileName &#039;&#039;&#039;, modifier son mobile de contact &#039;&#039;&#039;mobileElu &#039;&#039;&#039;, son nom et prénom.&lt;br /&gt;
&lt;br /&gt;
Il faut donc seulement modifier les lignes surlignés dans le code ci-dessous :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;csharp&amp;quot; line highlight=&amp;quot;14-17&amp;quot;&amp;gt;&lt;br /&gt;
using System;&lt;br /&gt;
using System.Threading.Tasks;&lt;br /&gt;
using TCX.Configuration;&lt;br /&gt;
using CallFlow;&lt;br /&gt;
using System.Linq;&lt;br /&gt;
&lt;br /&gt;
namespace dummy&lt;br /&gt;
{&lt;br /&gt;
    public class SetDynamicAstreinte : ScriptBase&amp;lt;SetDynamicAstreinte&amp;gt;&lt;br /&gt;
    {&lt;br /&gt;
        // ============================================================&lt;br /&gt;
        // CONFIGURATION — modifier uniquement ces lignes par script&lt;br /&gt;
        // ============================================================&lt;br /&gt;
        private const string TARGET_EXT   = &amp;quot;111&amp;quot;;&lt;br /&gt;
        private const string MOBILE_EXT   = &amp;quot;0612345678&amp;quot;;&lt;br /&gt;
        private const string PRENOM_EXT   = &amp;quot;Claude&amp;quot;;&lt;br /&gt;
        private const string NOM_EXT      = &amp;quot;IA&amp;quot;;&lt;br /&gt;
		 // ============================================================&lt;br /&gt;
        &lt;br /&gt;
		private const string PROFILE_NAME = &amp;quot;Away&amp;quot;;&lt;br /&gt;
       &lt;br /&gt;
        public override Task&amp;lt;bool&amp;gt; StartAsync()&lt;br /&gt;
        {&lt;br /&gt;
            try&lt;br /&gt;
            {&lt;br /&gt;
                IPhoneSystem ps = PhoneSystem.Root;&lt;br /&gt;
                Extension ext = ps.GetDNByNumber(TARGET_EXT) as Extension;&lt;br /&gt;
                if (ext == null)&lt;br /&gt;
                    return Task.FromResult(false);&lt;br /&gt;
&lt;br /&gt;
                // 1. Nom / Prénom&lt;br /&gt;
                ext.FirstName = PRENOM_EXT;&lt;br /&gt;
                ext.LastName  = NOM_EXT;&lt;br /&gt;
&lt;br /&gt;
                // 2. Numéro mobile&lt;br /&gt;
                ext.SetProperty(&amp;quot;MOBILENUMBER&amp;quot;, MOBILE_EXT);&lt;br /&gt;
&lt;br /&gt;
                // 3. Trouver le profil Away&lt;br /&gt;
                FwdProfile targetProfile = ext.FwdProfiles&lt;br /&gt;
                    .FirstOrDefault(p =&amp;gt; p.Name.Equals(&lt;br /&gt;
                        PROFILE_NAME, StringComparison.OrdinalIgnoreCase));&lt;br /&gt;
&lt;br /&gt;
                if (targetProfile != null)&lt;br /&gt;
                {&lt;br /&gt;
                    // AwayRoute, Internal, External sont read-only&lt;br /&gt;
                    // mais ce sont des références : on peut modifier&lt;br /&gt;
                    // leurs membres si ceux-ci sont accessibles en écriture&lt;br /&gt;
                    AwayRouting route = targetProfile.AwayRoute;&lt;br /&gt;
&lt;br /&gt;
                    // Capturer les HoursDestination comme variables locales&lt;br /&gt;
                    // (objets référence — la propriété est read-only,&lt;br /&gt;
                    //  mais l&#039;objet pointé est modifiable)&lt;br /&gt;
                    HoursDestination internalHours = route.Internal;&lt;br /&gt;
                    HoursDestination externalHours = route.External;&lt;br /&gt;
&lt;br /&gt;
                    // Capturer AllHours (struct) → modifier → réassigner&lt;br /&gt;
                    DestinationStruct destInternal = internalHours.AllHours;&lt;br /&gt;
                    destInternal.To               = DestinationType.Boomerang;&lt;br /&gt;
                    destInternal.External         = MOBILE_EXT;&lt;br /&gt;
                    internalHours.AllHours        = destInternal;&lt;br /&gt;
&lt;br /&gt;
                    DestinationStruct destExternal = externalHours.AllHours;&lt;br /&gt;
                    destExternal.To               = DestinationType.Boomerang;&lt;br /&gt;
                    destExternal.External         = MOBILE_EXT;&lt;br /&gt;
                    externalHours.AllHours        = destExternal;&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                // 4. Sauvegarder&lt;br /&gt;
                ext.Save();&lt;br /&gt;
&lt;br /&gt;
                // 5. Recharger et basculer le profil&lt;br /&gt;
                ext = ps.GetDNByNumber(TARGET_EXT) as Extension;&lt;br /&gt;
                if (ext == null)&lt;br /&gt;
                    return Task.FromResult(false);&lt;br /&gt;
&lt;br /&gt;
                FwdProfile profile = ext.FwdProfiles&lt;br /&gt;
                    .FirstOrDefault(p =&amp;gt; p.Name.Equals(&lt;br /&gt;
                        PROFILE_NAME, StringComparison.OrdinalIgnoreCase));&lt;br /&gt;
&lt;br /&gt;
                if (profile != null)&lt;br /&gt;
                {&lt;br /&gt;
                    ext.CurrentProfile = profile;&lt;br /&gt;
                    ext.Save();&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                return Task.FromResult(true);&lt;br /&gt;
            }&lt;br /&gt;
            catch (Exception)&lt;br /&gt;
            {&lt;br /&gt;
                return Task.FromResult(false);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Le script de retour à la normale===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;csharp&amp;quot; line highlight=&amp;quot;14-16&amp;quot;&amp;gt;&lt;br /&gt;
using System;&lt;br /&gt;
using System.Threading.Tasks;&lt;br /&gt;
using TCX.Configuration;&lt;br /&gt;
using CallFlow;&lt;br /&gt;
using System.Linq;&lt;br /&gt;
&lt;br /&gt;
namespace dummy&lt;br /&gt;
{&lt;br /&gt;
    public class ResetAstreinte : ScriptBase&amp;lt;ResetAstreinte&amp;gt;&lt;br /&gt;
    {&lt;br /&gt;
        // ============================================================&lt;br /&gt;
        // CONFIGURATION — modifier uniquement ces lignes par script&lt;br /&gt;
        // ============================================================&lt;br /&gt;
        private const string TARGET_EXT   = &amp;quot;111&amp;quot;;&lt;br /&gt;
        private const string PRENOM_EXT   = &amp;quot;Accueil&amp;quot;;&lt;br /&gt;
        private const string NOM_EXT      = &amp;quot;Mairie&amp;quot;;&lt;br /&gt;
        // ============================================================&lt;br /&gt;
&lt;br /&gt;
        public override Task&amp;lt;bool&amp;gt; StartAsync()&lt;br /&gt;
        {&lt;br /&gt;
            try&lt;br /&gt;
            {&lt;br /&gt;
                IPhoneSystem ps = PhoneSystem.Root;&lt;br /&gt;
                Extension ext = ps.GetDNByNumber(TARGET_EXT) as Extension;&lt;br /&gt;
                if (ext == null)&lt;br /&gt;
                    return Task.FromResult(false);&lt;br /&gt;
&lt;br /&gt;
                // 1. Remettre le nom générique&lt;br /&gt;
                ext.FirstName = PRENOM_EXT;&lt;br /&gt;
                ext.LastName  = NOM_EXT;&lt;br /&gt;
&lt;br /&gt;
                // 2. Vider le numéro mobile&lt;br /&gt;
                ext.SetProperty(&amp;quot;MOBILENUMBER&amp;quot;, &amp;quot;&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
                // 3. Résoudre le DN pour la messagerie vocale&lt;br /&gt;
                DN targetDN = ps.GetDNByNumber(TARGET_EXT);&lt;br /&gt;
&lt;br /&gt;
                // 4. Remettre AwayRoute → messagerie vocale&lt;br /&gt;
                FwdProfile awayProfile = ext.FwdProfiles&lt;br /&gt;
                    .FirstOrDefault(p =&amp;gt; p.Name.Equals(&lt;br /&gt;
                        &amp;quot;Away&amp;quot;, StringComparison.OrdinalIgnoreCase));&lt;br /&gt;
&lt;br /&gt;
                if (awayProfile != null)&lt;br /&gt;
                {&lt;br /&gt;
                    AwayRouting route = awayProfile.AwayRoute;&lt;br /&gt;
&lt;br /&gt;
                    HoursDestination internalHours = route.Internal;&lt;br /&gt;
                    HoursDestination externalHours = route.External;&lt;br /&gt;
&lt;br /&gt;
                    DestinationStruct destInternal = internalHours.AllHours;&lt;br /&gt;
                    destInternal.To               = DestinationType.VoiceMail;&lt;br /&gt;
                    destInternal.Internal         = targetDN;&lt;br /&gt;
                    destInternal.External         = &amp;quot;&amp;quot;;&lt;br /&gt;
                    internalHours.AllHours        = destInternal;&lt;br /&gt;
&lt;br /&gt;
                    DestinationStruct destExternal = externalHours.AllHours;&lt;br /&gt;
                    destExternal.To               = DestinationType.VoiceMail;&lt;br /&gt;
                    destExternal.Internal         = targetDN;&lt;br /&gt;
                    destExternal.External         = &amp;quot;&amp;quot;;&lt;br /&gt;
                    externalHours.AllHours        = destExternal;&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                // 5. Sauvegarder&lt;br /&gt;
                ext.Save();&lt;br /&gt;
&lt;br /&gt;
                // 6. Recharger et basculer vers Available&lt;br /&gt;
                ext = ps.GetDNByNumber(TARGET_EXT) as Extension;&lt;br /&gt;
                if (ext == null)&lt;br /&gt;
                    return Task.FromResult(false);&lt;br /&gt;
&lt;br /&gt;
                FwdProfile profile = ext.FwdProfiles&lt;br /&gt;
                    .FirstOrDefault(p =&amp;gt; p.Name.Equals(&lt;br /&gt;
                        &amp;quot;Available&amp;quot;, StringComparison.OrdinalIgnoreCase));&lt;br /&gt;
&lt;br /&gt;
                if (profile != null)&lt;br /&gt;
                {&lt;br /&gt;
                    ext.CurrentProfile = profile;&lt;br /&gt;
                    ext.Save();&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                return Task.FromResult(true);&lt;br /&gt;
            }&lt;br /&gt;
            catch (Exception)&lt;br /&gt;
            {&lt;br /&gt;
                return Task.FromResult(false);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Configuration concrète===&lt;br /&gt;
&lt;br /&gt;
On a besoin de gérer deux astreintes. Le poste Accueil reçoit les appels en temps normal&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Texte de la légende&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;Marcel Patulacci&#039;&#039;&#039; || &#039;&#039;&#039;Jean-Michel Apeuprè&#039;&#039;&#039;|| &#039;&#039;&#039;Poste accueil &#039;&#039;&#039; hors période d&#039;astreinte&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;syntaxhighlight lang=&amp;quot;csharp&amp;quot; line highlight=&amp;quot;4-7&amp;quot;&amp;gt;&lt;br /&gt;
public class SetDynamicAstreinte : ScriptBase&amp;lt;SetDynamicAstreinte&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
 // modifier uniquement ces lignes :&lt;br /&gt;
private const string TARGET_EXT   = &amp;quot;111&amp;quot;;&lt;br /&gt;
private const string MOBILE_EXT   = &amp;quot;0612345678&amp;quot;;&lt;br /&gt;
private const string PRENOM_EXT   = &amp;quot;Marcel&amp;quot;;&lt;br /&gt;
private const string NOM_EXT      = &amp;quot;Patulacci&amp;quot;;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt; || &amp;lt;syntaxhighlight lang=&amp;quot;csharp&amp;quot; line highlight=&amp;quot;4-7&amp;quot;&amp;gt;&lt;br /&gt;
public class SetDynamicAstreinte : ScriptBase&amp;lt;SetDynamicAstreinte&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
// Modifier uniquement ces lignes&lt;br /&gt;
private const string TARGET_EXT   = &amp;quot;111&amp;quot;;&lt;br /&gt;
private const string MOBILE_EXT   = &amp;quot;0699999999&amp;quot;;&lt;br /&gt;
private const string PRENOM_EXT   = &amp;quot;Jean-Michel&amp;quot;;&lt;br /&gt;
private const string NOM_EXT      = &amp;quot;Apeuprè&amp;quot;; &lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;|| &amp;lt;syntaxhighlight lang=&amp;quot;csharp&amp;quot; line highlight=&amp;quot;4-6&amp;quot;&amp;gt;&lt;br /&gt;
public class ResetAstreinte : ScriptBase&amp;lt;ResetAstreinte&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
// Modifier uniquement ces lignes :&lt;br /&gt;
private const string TARGET_EXT   = &amp;quot;111&amp;quot;;&lt;br /&gt;
private const string PRENOM_EXT   = &amp;quot;Accueil&amp;quot;;&lt;br /&gt;
private const string NOM_EXT      = &amp;quot;Mairie&amp;quot;; &lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Une fois les 3 scripts produits, passer à l&#039;étape [[Astreinte#Déclaration_du_script|Déclaration du script]] qui va permettre d&#039;affecter un code court à chaque script.&lt;br /&gt;
Exemple : &lt;br /&gt;
* *90 pour hors période d&#039;astreinte&lt;br /&gt;
* *91 pour Jean-Michel&lt;br /&gt;
* *92 pour Marcel&lt;br /&gt;
&lt;br /&gt;
On peut communiquer les codes aux personnes habilitées à gérer le système d&#039;astreinte et aller jusqu&#039;à paramétrer des BLF pour faciliter la vie d&#039;une secrétaire par exemple.&lt;br /&gt;
&lt;br /&gt;
{{Valide|v20}}&lt;br /&gt;
[[Catégorie:3CX]]&lt;/div&gt;</summary>
		<author><name>Anthony</name></author>
	</entry>
	<entry>
		<id>https://indywiki.fr/index.php?title=Astreinte&amp;diff=22282</id>
		<title>Astreinte</title>
		<link rel="alternate" type="text/html" href="https://indywiki.fr/index.php?title=Astreinte&amp;diff=22282"/>
		<updated>2026-05-27T13:52:37Z</updated>

		<summary type="html">&lt;p&gt;Anthony : /* Configuration concrète */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;===Principe===&lt;br /&gt;
On paramètre le statut choisi pour l&#039;astreinte en renvoi vers &#039;&#039;&#039;mon mobile&#039;&#039;&#039;. Un script viendra modifier le statut de l&#039;extension cible ainsi que son numéro de contact mobile, prénom et nom. Ce script déclenchable par l&#039;appel à un code court, paramétrable si on le souhaite sur une BLF. &lt;br /&gt;
&lt;br /&gt;
===Déclaration du script===&lt;br /&gt;
[[Fichier:2026-04-02 17h11 35.png|vignette]]&lt;br /&gt;
&lt;br /&gt;
Rendez-vous dans :&lt;br /&gt;
&lt;br /&gt;
 Admin / Intégrations / Scripts d&#039;appels / + Ajouter personnalisé&lt;br /&gt;
&lt;br /&gt;
#Donner un nom au traitement de l&#039;appel. Exemple : &#039;&#039;&#039;astreinte_weekend&#039;&#039;&#039;&lt;br /&gt;
#Créer un code de raccourci, ce qui permettra d&#039;exécuter le script simplement en appelant ce code, et in fine par une BLF. Exemple : &#039;&#039;&#039;*99&#039;&#039;&#039;&lt;br /&gt;
#OK&lt;br /&gt;
#Coller dans le champ script le script paramétré ( voir section suivante )&lt;br /&gt;
#Sauvegarder&lt;br /&gt;
#Un message doit indiquer &#039;&#039;&#039;Compilation réussie !&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Le script d&#039;astreinte===&lt;br /&gt;
&lt;br /&gt;
L&#039;éxécution du script va modifier l&#039;extension &#039;&#039;&#039;targetExtNum &#039;&#039;&#039;, il va le basculer sur le statut &#039;&#039;&#039;profileName &#039;&#039;&#039;, modifier son mobile de contact &#039;&#039;&#039;mobileElu &#039;&#039;&#039;, son nom et prénom.&lt;br /&gt;
&lt;br /&gt;
Il faut donc seulement modifier les lignes surlignés dans le code ci-dessous :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;csharp&amp;quot; line highlight=&amp;quot;14-17&amp;quot;&amp;gt;&lt;br /&gt;
using System;&lt;br /&gt;
using System.Threading.Tasks;&lt;br /&gt;
using TCX.Configuration;&lt;br /&gt;
using CallFlow;&lt;br /&gt;
using System.Linq;&lt;br /&gt;
&lt;br /&gt;
namespace dummy&lt;br /&gt;
{&lt;br /&gt;
    public class SetDynamicAstreinte : ScriptBase&amp;lt;SetDynamicAstreinte&amp;gt;&lt;br /&gt;
    {&lt;br /&gt;
        // ============================================================&lt;br /&gt;
        // CONFIGURATION — modifier uniquement ces lignes par script&lt;br /&gt;
        // ============================================================&lt;br /&gt;
        private const string TARGET_EXT   = &amp;quot;111&amp;quot;;&lt;br /&gt;
        private const string MOBILE_EXT   = &amp;quot;0612345678&amp;quot;;&lt;br /&gt;
        private const string PRENOM_EXT   = &amp;quot;Claude&amp;quot;;&lt;br /&gt;
        private const string NOM_EXT      = &amp;quot;IA&amp;quot;;&lt;br /&gt;
		 // ============================================================&lt;br /&gt;
        &lt;br /&gt;
		private const string PROFILE_NAME = &amp;quot;Away&amp;quot;;&lt;br /&gt;
       &lt;br /&gt;
        public override Task&amp;lt;bool&amp;gt; StartAsync()&lt;br /&gt;
        {&lt;br /&gt;
            try&lt;br /&gt;
            {&lt;br /&gt;
                IPhoneSystem ps = PhoneSystem.Root;&lt;br /&gt;
                Extension ext = ps.GetDNByNumber(TARGET_EXT) as Extension;&lt;br /&gt;
                if (ext == null)&lt;br /&gt;
                    return Task.FromResult(false);&lt;br /&gt;
&lt;br /&gt;
                // 1. Nom / Prénom&lt;br /&gt;
                ext.FirstName = PRENOM_EXT;&lt;br /&gt;
                ext.LastName  = NOM_EXT;&lt;br /&gt;
&lt;br /&gt;
                // 2. Numéro mobile&lt;br /&gt;
                ext.SetProperty(&amp;quot;MOBILENUMBER&amp;quot;, MOBILE_EXT);&lt;br /&gt;
&lt;br /&gt;
                // 3. Trouver le profil Away&lt;br /&gt;
                FwdProfile targetProfile = ext.FwdProfiles&lt;br /&gt;
                    .FirstOrDefault(p =&amp;gt; p.Name.Equals(&lt;br /&gt;
                        PROFILE_NAME, StringComparison.OrdinalIgnoreCase));&lt;br /&gt;
&lt;br /&gt;
                if (targetProfile != null)&lt;br /&gt;
                {&lt;br /&gt;
                    // AwayRoute, Internal, External sont read-only&lt;br /&gt;
                    // mais ce sont des références : on peut modifier&lt;br /&gt;
                    // leurs membres si ceux-ci sont accessibles en écriture&lt;br /&gt;
                    AwayRouting route = targetProfile.AwayRoute;&lt;br /&gt;
&lt;br /&gt;
                    // Capturer les HoursDestination comme variables locales&lt;br /&gt;
                    // (objets référence — la propriété est read-only,&lt;br /&gt;
                    //  mais l&#039;objet pointé est modifiable)&lt;br /&gt;
                    HoursDestination internalHours = route.Internal;&lt;br /&gt;
                    HoursDestination externalHours = route.External;&lt;br /&gt;
&lt;br /&gt;
                    // Capturer AllHours (struct) → modifier → réassigner&lt;br /&gt;
                    DestinationStruct destInternal = internalHours.AllHours;&lt;br /&gt;
                    destInternal.To               = DestinationType.Boomerang;&lt;br /&gt;
                    destInternal.External         = MOBILE_EXT;&lt;br /&gt;
                    internalHours.AllHours        = destInternal;&lt;br /&gt;
&lt;br /&gt;
                    DestinationStruct destExternal = externalHours.AllHours;&lt;br /&gt;
                    destExternal.To               = DestinationType.Boomerang;&lt;br /&gt;
                    destExternal.External         = MOBILE_EXT;&lt;br /&gt;
                    externalHours.AllHours        = destExternal;&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                // 4. Sauvegarder&lt;br /&gt;
                ext.Save();&lt;br /&gt;
&lt;br /&gt;
                // 5. Recharger et basculer le profil&lt;br /&gt;
                ext = ps.GetDNByNumber(TARGET_EXT) as Extension;&lt;br /&gt;
                if (ext == null)&lt;br /&gt;
                    return Task.FromResult(false);&lt;br /&gt;
&lt;br /&gt;
                FwdProfile profile = ext.FwdProfiles&lt;br /&gt;
                    .FirstOrDefault(p =&amp;gt; p.Name.Equals(&lt;br /&gt;
                        PROFILE_NAME, StringComparison.OrdinalIgnoreCase));&lt;br /&gt;
&lt;br /&gt;
                if (profile != null)&lt;br /&gt;
                {&lt;br /&gt;
                    ext.CurrentProfile = profile;&lt;br /&gt;
                    ext.Save();&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                return Task.FromResult(true);&lt;br /&gt;
            }&lt;br /&gt;
            catch (Exception)&lt;br /&gt;
            {&lt;br /&gt;
                return Task.FromResult(false);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Le script de retour à la normale===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;csharp&amp;quot; line highlight=&amp;quot;14-16&amp;quot;&amp;gt;&lt;br /&gt;
using System;&lt;br /&gt;
using System.Threading.Tasks;&lt;br /&gt;
using TCX.Configuration;&lt;br /&gt;
using CallFlow;&lt;br /&gt;
using System.Linq;&lt;br /&gt;
&lt;br /&gt;
namespace dummy&lt;br /&gt;
{&lt;br /&gt;
    public class ResetAstreinte : ScriptBase&amp;lt;ResetAstreinte&amp;gt;&lt;br /&gt;
    {&lt;br /&gt;
        // ============================================================&lt;br /&gt;
        // CONFIGURATION — modifier uniquement ces lignes par script&lt;br /&gt;
        // ============================================================&lt;br /&gt;
        private const string TARGET_EXT   = &amp;quot;111&amp;quot;;&lt;br /&gt;
        private const string PRENOM_EXT   = &amp;quot;Accueil&amp;quot;;&lt;br /&gt;
        private const string NOM_EXT      = &amp;quot;Mairie&amp;quot;;&lt;br /&gt;
        // ============================================================&lt;br /&gt;
&lt;br /&gt;
        public override Task&amp;lt;bool&amp;gt; StartAsync()&lt;br /&gt;
        {&lt;br /&gt;
            try&lt;br /&gt;
            {&lt;br /&gt;
                IPhoneSystem ps = PhoneSystem.Root;&lt;br /&gt;
                Extension ext = ps.GetDNByNumber(TARGET_EXT) as Extension;&lt;br /&gt;
                if (ext == null)&lt;br /&gt;
                    return Task.FromResult(false);&lt;br /&gt;
&lt;br /&gt;
                // 1. Remettre le nom générique&lt;br /&gt;
                ext.FirstName = PRENOM_EXT;&lt;br /&gt;
                ext.LastName  = NOM_EXT;&lt;br /&gt;
&lt;br /&gt;
                // 2. Vider le numéro mobile&lt;br /&gt;
                ext.SetProperty(&amp;quot;MOBILENUMBER&amp;quot;, &amp;quot;&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
                // 3. Résoudre le DN pour la messagerie vocale&lt;br /&gt;
                DN targetDN = ps.GetDNByNumber(TARGET_EXT);&lt;br /&gt;
&lt;br /&gt;
                // 4. Remettre AwayRoute → messagerie vocale&lt;br /&gt;
                FwdProfile awayProfile = ext.FwdProfiles&lt;br /&gt;
                    .FirstOrDefault(p =&amp;gt; p.Name.Equals(&lt;br /&gt;
                        &amp;quot;Away&amp;quot;, StringComparison.OrdinalIgnoreCase));&lt;br /&gt;
&lt;br /&gt;
                if (awayProfile != null)&lt;br /&gt;
                {&lt;br /&gt;
                    AwayRouting route = awayProfile.AwayRoute;&lt;br /&gt;
&lt;br /&gt;
                    HoursDestination internalHours = route.Internal;&lt;br /&gt;
                    HoursDestination externalHours = route.External;&lt;br /&gt;
&lt;br /&gt;
                    DestinationStruct destInternal = internalHours.AllHours;&lt;br /&gt;
                    destInternal.To               = DestinationType.VoiceMail;&lt;br /&gt;
                    destInternal.Internal         = targetDN;&lt;br /&gt;
                    destInternal.External         = &amp;quot;&amp;quot;;&lt;br /&gt;
                    internalHours.AllHours        = destInternal;&lt;br /&gt;
&lt;br /&gt;
                    DestinationStruct destExternal = externalHours.AllHours;&lt;br /&gt;
                    destExternal.To               = DestinationType.VoiceMail;&lt;br /&gt;
                    destExternal.Internal         = targetDN;&lt;br /&gt;
                    destExternal.External         = &amp;quot;&amp;quot;;&lt;br /&gt;
                    externalHours.AllHours        = destExternal;&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                // 5. Sauvegarder&lt;br /&gt;
                ext.Save();&lt;br /&gt;
&lt;br /&gt;
                // 6. Recharger et basculer vers Available&lt;br /&gt;
                ext = ps.GetDNByNumber(TARGET_EXT) as Extension;&lt;br /&gt;
                if (ext == null)&lt;br /&gt;
                    return Task.FromResult(false);&lt;br /&gt;
&lt;br /&gt;
                FwdProfile profile = ext.FwdProfiles&lt;br /&gt;
                    .FirstOrDefault(p =&amp;gt; p.Name.Equals(&lt;br /&gt;
                        &amp;quot;Available&amp;quot;, StringComparison.OrdinalIgnoreCase));&lt;br /&gt;
&lt;br /&gt;
                if (profile != null)&lt;br /&gt;
                {&lt;br /&gt;
                    ext.CurrentProfile = profile;&lt;br /&gt;
                    ext.Save();&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                return Task.FromResult(true);&lt;br /&gt;
            }&lt;br /&gt;
            catch (Exception)&lt;br /&gt;
            {&lt;br /&gt;
                return Task.FromResult(false);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Configuration concrète===&lt;br /&gt;
&lt;br /&gt;
On a besoin de gérer deux astreintes. Le poste Accueil reçoit les appels en temps normal&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Texte de la légende&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;Marcel Patulacci&#039;&#039;&#039; || &#039;&#039;&#039;Jean-Michel Apeuprè&#039;&#039;&#039;|| &#039;&#039;&#039;Poste accueil &#039;&#039;&#039; hors période d&#039;astreinte&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;syntaxhighlight lang=&amp;quot;csharp&amp;quot; line highlight=&amp;quot;4-7&amp;quot;&amp;gt;&lt;br /&gt;
public class SetDynamicAstreinte : ScriptBase&amp;lt;SetDynamicAstreinte&amp;gt;&lt;br /&gt;
{&lt;br /&gt;
 // CONFIGURATION — modifier uniquement ces lignes&lt;br /&gt;
private const string TARGET_EXT   = &amp;quot;111&amp;quot;;&lt;br /&gt;
private const string MOBILE_EXT   = &amp;quot;0612345678&amp;quot;;&lt;br /&gt;
private const string PRENOM_EXT   = &amp;quot;Marcel&amp;quot;;&lt;br /&gt;
private const string NOM_EXT      = &amp;quot;Patulacci&amp;quot;;&lt;br /&gt;
//&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt; || &amp;lt;syntaxhighlight lang=&amp;quot;csharp&amp;quot; line highlight=&amp;quot;4-7&amp;quot;&amp;gt;&lt;br /&gt;
    public class SetDynamicAstreinte : ScriptBase&amp;lt;SetDynamicAstreinte&amp;gt;&lt;br /&gt;
    {&lt;br /&gt;
        // CONFIGURATION — modifier uniquement ces lignes par script&lt;br /&gt;
        private const string TARGET_EXT   = &amp;quot;111&amp;quot;;&lt;br /&gt;
        private const string MOBILE_EXT   = &amp;quot;0699999999&amp;quot;;&lt;br /&gt;
        private const string PRENOM_EXT   = &amp;quot;Jean-Michel&amp;quot;;&lt;br /&gt;
        private const string NOM_EXT      = &amp;quot;Apeuprè&amp;quot;;&lt;br /&gt;
		 // &lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;|| &amp;lt;syntaxhighlight lang=&amp;quot;csharp&amp;quot; line highlight=&amp;quot;4-6&amp;quot;&amp;gt;&lt;br /&gt;
    public class ResetAstreinte : ScriptBase&amp;lt;ResetAstreinte&amp;gt;&lt;br /&gt;
    {&lt;br /&gt;
        // CONFIGURATION — modifier uniquement ces lignes par script&lt;br /&gt;
        private const string TARGET_EXT   = &amp;quot;111&amp;quot;;&lt;br /&gt;
        private const string PRENOM_EXT   = &amp;quot;Accueil&amp;quot;;&lt;br /&gt;
        private const string NOM_EXT      = &amp;quot;Mairie&amp;quot;;&lt;br /&gt;
        // &lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Une fois les 3 scripts produits, passer à l&#039;étape [[Astreinte#Déclaration_du_script|Déclaration du script]] qui va permettre d&#039;affecter un code court à chaque script.&lt;br /&gt;
Exemple : &lt;br /&gt;
* *90 pour hors période d&#039;astreinte&lt;br /&gt;
* *91 pour Jean-Michel&lt;br /&gt;
* *92 pour Marcel&lt;br /&gt;
&lt;br /&gt;
On peut communiquer les codes aux personnes habilitées à gérer le système d&#039;astreinte et aller jusqu&#039;à paramétrer des BLF pour faciliter la vie d&#039;une secrétaire par exemple.&lt;br /&gt;
&lt;br /&gt;
{{Valide|v20}}&lt;br /&gt;
[[Catégorie:3CX]]&lt;/div&gt;</summary>
		<author><name>Anthony</name></author>
	</entry>
	<entry>
		<id>https://indywiki.fr/index.php?title=Script_de_routage_des_appels&amp;diff=22281</id>
		<title>Script de routage des appels</title>
		<link rel="alternate" type="text/html" href="https://indywiki.fr/index.php?title=Script_de_routage_des_appels&amp;diff=22281"/>
		<updated>2026-05-27T13:47:37Z</updated>

		<summary type="html">&lt;p&gt;Anthony : /* Le script */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Permet en fonction du moment de la semaine de router les appels vers telle ou telle destination.&lt;br /&gt;
&#039;&#039;&#039;Nécessite de supprimer les horaires de fermeture&#039;&#039;&#039; sur le département / instance 3CX ( c&#039;est le script qui gère )&lt;br /&gt;
&lt;br /&gt;
⚠️ les règles sont évaluées dans l&#039;ordre de leur apparition, il faut donc les déclarer de la plus spécifique à la plus générale ⚠️&lt;br /&gt;
&lt;br /&gt;
===Le script===&lt;br /&gt;
&lt;br /&gt;
Seules les lignes jaune requiert d&#039;être éditées. Si plus de règles sont à prévoir, dupliquer les sections &#039;&#039;&#039;new RoutingRule&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
* Ligne 16 : si aucune règle dans le script ne permet de déterminer un chemin, alors c&#039;est cette extension la cible&lt;br /&gt;
* Ligne 44 : Pour chaque règle, il faut définir les jours et horaires. sur cet exemple, le lundi de 14 à 17h, c&#039;est la règle 1 qui s&#039;applique.&lt;br /&gt;
* Ligne 50 : C&#039;est l&#039;extension qui va être visée par la règle, peut être un utilisateur, un SVI, un groupe , une file d&#039;attente.&lt;br /&gt;
* Ligne 51 : DID : ce filtre permet de tester le &#039;&#039;&#039;numéro appelé&#039;&#039;&#039; ( SDA  actif sur le système). En pratique on ne s&#039;en sert pas ici car le filtre se fait en amont de l&#039;[[Script_de_routage_des_appels#Mise_en_place_du_script|appel du script]]. Mais possible. La syntaxe &#039;&#039;&#039;*&#039;&#039;&#039; permet de tout laisser passer&lt;br /&gt;
* Ligne 52 : Callers, on peut filtrer sur le &#039;&#039;&#039;numéros de l&#039;appelant&#039;&#039;&#039;. La syntaxe &#039;&#039;&#039;*&#039;&#039;&#039; permet de tout laisser passer&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;csharp&amp;quot; line highlight=&amp;quot;16,44,50-52&amp;quot;&amp;gt;&lt;br /&gt;
#nullable disable&lt;br /&gt;
using CallFlow;&lt;br /&gt;
using System;&lt;br /&gt;
using System.Threading.Tasks;&lt;br /&gt;
using TCX.Configuration;&lt;br /&gt;
using TCX.PBXAPI;&lt;br /&gt;
using System.Collections.Generic;&lt;br /&gt;
using System.Linq;&lt;br /&gt;
using CallFlow.CFD;&lt;br /&gt;
&lt;br /&gt;
namespace interceptcall&lt;br /&gt;
{&lt;br /&gt;
    public class InterceptInboundCall : ScriptBase&amp;lt;InterceptInboundCall&amp;gt;&lt;br /&gt;
    {&lt;br /&gt;
        // Destination par Défaut, à priori jamais utilisé car ce numéro doit toujours être joignable&lt;br /&gt;
        const string DefaultDestinationDN = &amp;quot;812&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
        // Structure d&#039;une règle de routage&lt;br /&gt;
        class RoutingRule&lt;br /&gt;
        {&lt;br /&gt;
            public Schedule Schedule { get; set; }&lt;br /&gt;
            public string DestinationDN { get; set; }&lt;br /&gt;
            public string[] DIDs { get; set; }&lt;br /&gt;
            public string[] Callers { get; set; }&lt;br /&gt;
&lt;br /&gt;
            public RoutingRule(Schedule schedule, string destinationDN, string[] dids, string[] callers)&lt;br /&gt;
            {&lt;br /&gt;
                Schedule = schedule;&lt;br /&gt;
                DestinationDN = destinationDN;&lt;br /&gt;
                DIDs = dids;&lt;br /&gt;
                Callers = callers;&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
		// Règle(s) de routage &amp;quot;First Match&amp;quot; : La première règle satisfaite est éxécutée, les suivantes sont ignorées&lt;br /&gt;
&lt;br /&gt;
       static readonly List&amp;lt;RoutingRule&amp;gt; routingRules = new List&amp;lt;RoutingRule&amp;gt;&lt;br /&gt;
        {&lt;br /&gt;
            // Règle 1 - Mairie ouverte - routage vers le 801 qui route vers le 100 ( pas de changements&lt;br /&gt;
            new RoutingRule(&lt;br /&gt;
                new Schedule(RuleHoursType.SpecificHours)&lt;br /&gt;
                {&lt;br /&gt;
					{ DayOfWeek.Monday,    new Schedule.PeriodOfDay(new TimeSpan(14,00,0), new TimeSpan(17,00,0)) },&lt;br /&gt;
					{ DayOfWeek.Tuesday,    new Schedule.PeriodOfDay(new TimeSpan(14,00,0), new TimeSpan(17,00,0)) },&lt;br /&gt;
					{ DayOfWeek.Wednesday,    new Schedule.PeriodOfDay(new TimeSpan(09,00,0), new TimeSpan(12,00,0)) },&lt;br /&gt;
                    { DayOfWeek.Thursday,    new Schedule.PeriodOfDay(new TimeSpan(09,00,0), new TimeSpan(12,00,0)) },&lt;br /&gt;
					{ DayOfWeek.Friday,    new Schedule.PeriodOfDay(new TimeSpan(09,00,0), new TimeSpan(12,00,0)) }&lt;br /&gt;
                },&lt;br /&gt;
                &amp;quot;801&amp;quot;,&lt;br /&gt;
                new[] { &amp;quot;*&amp;quot; },   // Tous les DIDs&lt;br /&gt;
                new[] { &amp;quot;*&amp;quot; }    // Tous les callers&lt;br /&gt;
            ),&lt;br /&gt;
			&lt;br /&gt;
			 // Règle 2 — Mairie fermée en semaine ( routage vers le 800 )&lt;br /&gt;
            new RoutingRule(&lt;br /&gt;
                new Schedule(RuleHoursType.SpecificHours)&lt;br /&gt;
                {&lt;br /&gt;
					{ DayOfWeek.Monday,    new Schedule.PeriodOfDay(new TimeSpan(8,00,0), new TimeSpan(14,00,0)) },&lt;br /&gt;
     				{ DayOfWeek.Monday,    new Schedule.PeriodOfDay(new TimeSpan(17,00,0), new TimeSpan(24,00,0)) },&lt;br /&gt;
					{ DayOfWeek.Tuesday,    new Schedule.PeriodOfDay(new TimeSpan(0,00,0), new TimeSpan(14,00,0)) },&lt;br /&gt;
					{ DayOfWeek.Tuesday,    new Schedule.PeriodOfDay(new TimeSpan(17,00,0), new TimeSpan(24,00,0)) },&lt;br /&gt;
					{ DayOfWeek.Wednesday,    new Schedule.PeriodOfDay(new TimeSpan(0,00,0), new TimeSpan(09,00,0)) },&lt;br /&gt;
					{ DayOfWeek.Wednesday,    new Schedule.PeriodOfDay(new TimeSpan(12,00,0), new TimeSpan(24,00,0)) },&lt;br /&gt;
      				{ DayOfWeek.Thursday,    new Schedule.PeriodOfDay(new TimeSpan(0,00,0), new TimeSpan(09,00,0)) },&lt;br /&gt;
					{ DayOfWeek.Thursday,    new Schedule.PeriodOfDay(new TimeSpan(12,00,0), new TimeSpan(24,00,0)) },&lt;br /&gt;
      				{ DayOfWeek.Friday,    new Schedule.PeriodOfDay(new TimeSpan(0,00,0), new TimeSpan(09,00,0)) },&lt;br /&gt;
					{ DayOfWeek.Friday,    new Schedule.PeriodOfDay(new TimeSpan(12,00,0), new TimeSpan(24,00,0)) }&lt;br /&gt;
                },&lt;br /&gt;
                &amp;quot;800&amp;quot;,&lt;br /&gt;
                new[] { &amp;quot;*&amp;quot; },&lt;br /&gt;
                new[] { &amp;quot;*&amp;quot; }&lt;br /&gt;
            ),&lt;br /&gt;
			&lt;br /&gt;
			 // Règle 3 — Mairie fermée le week-end ( vendredi 16h30 au lundi ? )&lt;br /&gt;
            new RoutingRule(&lt;br /&gt;
                new Schedule(RuleHoursType.SpecificHours)&lt;br /&gt;
                {&lt;br /&gt;
					&lt;br /&gt;
					{ DayOfWeek.Friday,    new Schedule.PeriodOfDay(new TimeSpan(16,30,0), new TimeSpan(24,00,0)) },&lt;br /&gt;
					{ DayOfWeek.Saturday, new Schedule.PeriodOfDay(new TimeSpan(0,00,0), new TimeSpan(24,00,0)) },&lt;br /&gt;
					{ DayOfWeek.Sunday, new Schedule.PeriodOfDay(new TimeSpan(0,00,0), new TimeSpan(24,00,0)) }&lt;br /&gt;
      				{ DayOfWeek.Monday, new Schedule.PeriodOfDay(new TimeSpan(0,00,0), new TimeSpan(08,00,0)) }&lt;br /&gt;
                },&lt;br /&gt;
                &amp;quot;804&amp;quot;,&lt;br /&gt;
                new[] { &amp;quot;*&amp;quot; },&lt;br /&gt;
                new[] { &amp;quot;*&amp;quot; }&lt;br /&gt;
            ),&lt;br /&gt;
			&lt;br /&gt;
        };&lt;br /&gt;
&lt;br /&gt;
        // Appel de la fonction principale&lt;br /&gt;
&lt;br /&gt;
        public override async void Start()&lt;br /&gt;
        {&lt;br /&gt;
            try&lt;br /&gt;
            {&lt;br /&gt;
                await Task.Run(async () =&amp;gt;&lt;br /&gt;
                {&lt;br /&gt;
                    bool intercepted = false;&lt;br /&gt;
                    var ps = MyCall.PS as PhoneSystem;&lt;br /&gt;
&lt;br /&gt;
                    if (!(MyCall.Caller.DN is ExternalLine externalLine))&lt;br /&gt;
                    {&lt;br /&gt;
                        MyCall.Return(false);&lt;br /&gt;
                        return;&lt;br /&gt;
                    }&lt;br /&gt;
&lt;br /&gt;
                    var DIDNumber = MyCall.Caller[&amp;quot;inbound_did&amp;quot;] ?? &amp;quot;&amp;quot;;&lt;br /&gt;
                    var CallerID = MyCall.Caller.CallerID ?? &amp;quot;&amp;quot;;&lt;br /&gt;
                    var currentTime = externalLine.Now(out var utc, out var timezone, out var groupmode);&lt;br /&gt;
&lt;br /&gt;
                    MyCall.Info($&amp;quot;Incoming call | Caller: {CallerID} | DID: {DIDNumber} | Time: {currentTime}&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
                    foreach (var rule in routingRules)&lt;br /&gt;
                    {&lt;br /&gt;
                        if (!rule.Schedule.IsActiveTime(currentTime))&lt;br /&gt;
                            continue;&lt;br /&gt;
&lt;br /&gt;
                        bool didMatch = rule.DIDs.Contains(&amp;quot;*&amp;quot;) || rule.DIDs.Contains(DIDNumber);&lt;br /&gt;
                        bool callerMatch = rule.Callers.Contains(&amp;quot;*&amp;quot;) || rule.Callers.Contains(CallerID);&lt;br /&gt;
&lt;br /&gt;
                        if (!didMatch || !callerMatch)&lt;br /&gt;
                            continue;&lt;br /&gt;
&lt;br /&gt;
                        var destinationDN = ps.GetDNByNumber(rule.DestinationDN);&lt;br /&gt;
&lt;br /&gt;
                        if (destinationDN == null)&lt;br /&gt;
                        {&lt;br /&gt;
                            MyCall.Error($&amp;quot;Destination {rule.DestinationDN} not found.&amp;quot;);&lt;br /&gt;
                            continue;&lt;br /&gt;
                        }&lt;br /&gt;
&lt;br /&gt;
                        try&lt;br /&gt;
                        {&lt;br /&gt;
                            var result = await MyCall.RouteToAsync(new DestinationStruct(destinationDN));&lt;br /&gt;
                            MyCall.Info($&amp;quot;Routed to {rule.DestinationDN} | Result: {result}&amp;quot;);&lt;br /&gt;
                            intercepted = true;&lt;br /&gt;
                            break; // Stop at first matching rule&lt;br /&gt;
                        }&lt;br /&gt;
                        catch (Exception ex)&lt;br /&gt;
                        {&lt;br /&gt;
                            MyCall.Error($&amp;quot;Routing failed to {rule.DestinationDN}: {ex}&amp;quot;);&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
&lt;br /&gt;
                &lt;br /&gt;
                    // Utilisation de la route par défaut&lt;br /&gt;
                    &lt;br /&gt;
                    if (!intercepted)&lt;br /&gt;
                    {&lt;br /&gt;
                        var fallbackDN = ps.GetDNByNumber(DefaultDestinationDN);&lt;br /&gt;
                        if (fallbackDN != null)&lt;br /&gt;
                        {&lt;br /&gt;
                            try&lt;br /&gt;
                            {&lt;br /&gt;
                                var result = await MyCall.RouteToAsync(new DestinationStruct(fallbackDN));&lt;br /&gt;
                                MyCall.Info($&amp;quot;Fallback routing to {DefaultDestinationDN} | Result: {result}&amp;quot;);&lt;br /&gt;
                                intercepted = true;&lt;br /&gt;
                            }&lt;br /&gt;
                            catch (Exception ex)&lt;br /&gt;
                            {&lt;br /&gt;
                                MyCall.Error($&amp;quot;Fallback routing failed: {ex}&amp;quot;);&lt;br /&gt;
                            }&lt;br /&gt;
                        }&lt;br /&gt;
                        else&lt;br /&gt;
                        {&lt;br /&gt;
                            MyCall.Error($&amp;quot;Fallback DN {DefaultDestinationDN} not found.&amp;quot;);&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
&lt;br /&gt;
                    MyCall.Return(intercepted);&lt;br /&gt;
                });&lt;br /&gt;
            }&lt;br /&gt;
            catch (Exception ex)&lt;br /&gt;
            {&lt;br /&gt;
                MyCall.Error($&amp;quot;Script execution failed: {ex}&amp;quot;);&lt;br /&gt;
                MyCall.Return(false);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Mise en place du script===&lt;br /&gt;
&lt;br /&gt;
Connecté en admin dans 3CX :&lt;br /&gt;
 &lt;br /&gt;
 Admin / Intégrations / Scripts d&#039;appels / + Ajouter personnalisé&lt;br /&gt;
&lt;br /&gt;
[[Fichier:2026-05-27 15h34 23.png|cadre|right]]&lt;br /&gt;
# Nommer le script&lt;br /&gt;
#Choisir &#039;&#039;&#039;Quand cette SDA est composée&#039;&#039;&#039;&lt;br /&gt;
#Choisir la SDA appelée qui va déclencher le script&lt;br /&gt;
#Choisir le scope d&#039;action du script&lt;br /&gt;
#Cliquer sur OK&lt;br /&gt;
#Coller le script préparé dans la zone script&lt;br /&gt;
#Sauvegarder&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Catégorie:3CX]]&lt;/div&gt;</summary>
		<author><name>Anthony</name></author>
	</entry>
	<entry>
		<id>https://indywiki.fr/index.php?title=Script_de_routage_des_appels&amp;diff=22280</id>
		<title>Script de routage des appels</title>
		<link rel="alternate" type="text/html" href="https://indywiki.fr/index.php?title=Script_de_routage_des_appels&amp;diff=22280"/>
		<updated>2026-05-27T13:44:40Z</updated>

		<summary type="html">&lt;p&gt;Anthony : /* Mise en place du script */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Permet en fonction du moment de la semaine de router les appels vers telle ou telle destination.&lt;br /&gt;
&#039;&#039;&#039;Nécessite de supprimer les horaires de fermeture&#039;&#039;&#039; sur le département / instance 3CX ( c&#039;est le script qui gère )&lt;br /&gt;
&lt;br /&gt;
⚠️ les règles sont évaluées dans l&#039;ordre de leur apparition, il faut donc les déclarer de la plus spécifique à la plus générale ⚠️&lt;br /&gt;
&lt;br /&gt;
===Le script===&lt;br /&gt;
&lt;br /&gt;
Seules les lignes jaune requiert d&#039;être éditées. Si plus de règles sont à prévoir, dupliquer les sections &#039;&#039;&#039;new RoutingRule&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
* Ligne 16 : si aucune règle dans le script ne permet de déterminer un chemin, alors c&#039;est cette extension la cible&lt;br /&gt;
* Ligne 44 : Pour chaque règle, il faut définir les jours et horaires. sur cet exemple, le lundi de 14 à 17h, c&#039;est la règle 1 qui s&#039;applique.&lt;br /&gt;
* Ligne 50 : C&#039;est l&#039;extension qui va être visée par la règle, peut être un utilisateur, un SVI, un groupe , une file d&#039;attente.&lt;br /&gt;
* Ligne 51 : DID : ce filtre permet de tester le &#039;&#039;&#039;numéro appelé&#039;&#039;&#039; ( SDA  actif sur le système). En pratique on ne s&#039;en sert pas ici car le filtre se fait en amont de l&#039;appel du script. Mais possible. La syntaxe &#039;&#039;&#039;*&#039;&#039;&#039; permet de tout laisser passer&lt;br /&gt;
* Ligne 52 : Callers, on peut filtrer sur le &#039;&#039;&#039;numéros de l&#039;appelant&#039;&#039;&#039;. La syntaxe &#039;&#039;&#039;*&#039;&#039;&#039; permet de tout laisser passer&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;csharp&amp;quot; line highlight=&amp;quot;16,44,50-52&amp;quot;&amp;gt;&lt;br /&gt;
#nullable disable&lt;br /&gt;
using CallFlow;&lt;br /&gt;
using System;&lt;br /&gt;
using System.Threading.Tasks;&lt;br /&gt;
using TCX.Configuration;&lt;br /&gt;
using TCX.PBXAPI;&lt;br /&gt;
using System.Collections.Generic;&lt;br /&gt;
using System.Linq;&lt;br /&gt;
using CallFlow.CFD;&lt;br /&gt;
&lt;br /&gt;
namespace interceptcall&lt;br /&gt;
{&lt;br /&gt;
    public class InterceptInboundCall : ScriptBase&amp;lt;InterceptInboundCall&amp;gt;&lt;br /&gt;
    {&lt;br /&gt;
        // Destination par Défaut, à priori jamais utilisé car ce numéro doit toujours être joignable&lt;br /&gt;
        const string DefaultDestinationDN = &amp;quot;812&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
        // Structure d&#039;une règle de routage&lt;br /&gt;
        class RoutingRule&lt;br /&gt;
        {&lt;br /&gt;
            public Schedule Schedule { get; set; }&lt;br /&gt;
            public string DestinationDN { get; set; }&lt;br /&gt;
            public string[] DIDs { get; set; }&lt;br /&gt;
            public string[] Callers { get; set; }&lt;br /&gt;
&lt;br /&gt;
            public RoutingRule(Schedule schedule, string destinationDN, string[] dids, string[] callers)&lt;br /&gt;
            {&lt;br /&gt;
                Schedule = schedule;&lt;br /&gt;
                DestinationDN = destinationDN;&lt;br /&gt;
                DIDs = dids;&lt;br /&gt;
                Callers = callers;&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
		// Règle(s) de routage &amp;quot;First Match&amp;quot; : La première règle satisfaite est éxécutée, les suivantes sont ignorées&lt;br /&gt;
&lt;br /&gt;
       static readonly List&amp;lt;RoutingRule&amp;gt; routingRules = new List&amp;lt;RoutingRule&amp;gt;&lt;br /&gt;
        {&lt;br /&gt;
            // Règle 1 - Mairie ouverte - routage vers le 801 qui route vers le 100 ( pas de changements&lt;br /&gt;
            new RoutingRule(&lt;br /&gt;
                new Schedule(RuleHoursType.SpecificHours)&lt;br /&gt;
                {&lt;br /&gt;
					{ DayOfWeek.Monday,    new Schedule.PeriodOfDay(new TimeSpan(14,00,0), new TimeSpan(17,00,0)) },&lt;br /&gt;
					{ DayOfWeek.Tuesday,    new Schedule.PeriodOfDay(new TimeSpan(14,00,0), new TimeSpan(17,00,0)) },&lt;br /&gt;
					{ DayOfWeek.Wednesday,    new Schedule.PeriodOfDay(new TimeSpan(09,00,0), new TimeSpan(12,00,0)) },&lt;br /&gt;
                    { DayOfWeek.Thursday,    new Schedule.PeriodOfDay(new TimeSpan(09,00,0), new TimeSpan(12,00,0)) },&lt;br /&gt;
					{ DayOfWeek.Friday,    new Schedule.PeriodOfDay(new TimeSpan(09,00,0), new TimeSpan(12,00,0)) }&lt;br /&gt;
                },&lt;br /&gt;
                &amp;quot;801&amp;quot;,&lt;br /&gt;
                new[] { &amp;quot;*&amp;quot; },   // Tous les DIDs&lt;br /&gt;
                new[] { &amp;quot;*&amp;quot; }    // Tous les callers&lt;br /&gt;
            ),&lt;br /&gt;
			&lt;br /&gt;
			 // Règle 2 — Mairie fermée en semaine ( routage vers le 800 )&lt;br /&gt;
            new RoutingRule(&lt;br /&gt;
                new Schedule(RuleHoursType.SpecificHours)&lt;br /&gt;
                {&lt;br /&gt;
					{ DayOfWeek.Monday,    new Schedule.PeriodOfDay(new TimeSpan(8,00,0), new TimeSpan(14,00,0)) },&lt;br /&gt;
     				{ DayOfWeek.Monday,    new Schedule.PeriodOfDay(new TimeSpan(17,00,0), new TimeSpan(24,00,0)) },&lt;br /&gt;
					{ DayOfWeek.Tuesday,    new Schedule.PeriodOfDay(new TimeSpan(0,00,0), new TimeSpan(14,00,0)) },&lt;br /&gt;
					{ DayOfWeek.Tuesday,    new Schedule.PeriodOfDay(new TimeSpan(17,00,0), new TimeSpan(24,00,0)) },&lt;br /&gt;
					{ DayOfWeek.Wednesday,    new Schedule.PeriodOfDay(new TimeSpan(0,00,0), new TimeSpan(09,00,0)) },&lt;br /&gt;
					{ DayOfWeek.Wednesday,    new Schedule.PeriodOfDay(new TimeSpan(12,00,0), new TimeSpan(24,00,0)) },&lt;br /&gt;
      				{ DayOfWeek.Thursday,    new Schedule.PeriodOfDay(new TimeSpan(0,00,0), new TimeSpan(09,00,0)) },&lt;br /&gt;
					{ DayOfWeek.Thursday,    new Schedule.PeriodOfDay(new TimeSpan(12,00,0), new TimeSpan(24,00,0)) },&lt;br /&gt;
      				{ DayOfWeek.Friday,    new Schedule.PeriodOfDay(new TimeSpan(0,00,0), new TimeSpan(09,00,0)) },&lt;br /&gt;
					{ DayOfWeek.Friday,    new Schedule.PeriodOfDay(new TimeSpan(12,00,0), new TimeSpan(24,00,0)) }&lt;br /&gt;
                },&lt;br /&gt;
                &amp;quot;800&amp;quot;,&lt;br /&gt;
                new[] { &amp;quot;*&amp;quot; },&lt;br /&gt;
                new[] { &amp;quot;*&amp;quot; }&lt;br /&gt;
            ),&lt;br /&gt;
			&lt;br /&gt;
			 // Règle 3 — Mairie fermée le week-end ( vendredi 16h30 au lundi ? )&lt;br /&gt;
            new RoutingRule(&lt;br /&gt;
                new Schedule(RuleHoursType.SpecificHours)&lt;br /&gt;
                {&lt;br /&gt;
					&lt;br /&gt;
					{ DayOfWeek.Friday,    new Schedule.PeriodOfDay(new TimeSpan(16,30,0), new TimeSpan(24,00,0)) },&lt;br /&gt;
					{ DayOfWeek.Saturday, new Schedule.PeriodOfDay(new TimeSpan(0,00,0), new TimeSpan(24,00,0)) },&lt;br /&gt;
					{ DayOfWeek.Sunday, new Schedule.PeriodOfDay(new TimeSpan(0,00,0), new TimeSpan(24,00,0)) }&lt;br /&gt;
      				{ DayOfWeek.Monday, new Schedule.PeriodOfDay(new TimeSpan(0,00,0), new TimeSpan(08,00,0)) }&lt;br /&gt;
                },&lt;br /&gt;
                &amp;quot;804&amp;quot;,&lt;br /&gt;
                new[] { &amp;quot;*&amp;quot; },&lt;br /&gt;
                new[] { &amp;quot;*&amp;quot; }&lt;br /&gt;
            ),&lt;br /&gt;
			&lt;br /&gt;
        };&lt;br /&gt;
&lt;br /&gt;
        // Appel de la fonction principale&lt;br /&gt;
&lt;br /&gt;
        public override async void Start()&lt;br /&gt;
        {&lt;br /&gt;
            try&lt;br /&gt;
            {&lt;br /&gt;
                await Task.Run(async () =&amp;gt;&lt;br /&gt;
                {&lt;br /&gt;
                    bool intercepted = false;&lt;br /&gt;
                    var ps = MyCall.PS as PhoneSystem;&lt;br /&gt;
&lt;br /&gt;
                    if (!(MyCall.Caller.DN is ExternalLine externalLine))&lt;br /&gt;
                    {&lt;br /&gt;
                        MyCall.Return(false);&lt;br /&gt;
                        return;&lt;br /&gt;
                    }&lt;br /&gt;
&lt;br /&gt;
                    var DIDNumber = MyCall.Caller[&amp;quot;inbound_did&amp;quot;] ?? &amp;quot;&amp;quot;;&lt;br /&gt;
                    var CallerID = MyCall.Caller.CallerID ?? &amp;quot;&amp;quot;;&lt;br /&gt;
                    var currentTime = externalLine.Now(out var utc, out var timezone, out var groupmode);&lt;br /&gt;
&lt;br /&gt;
                    MyCall.Info($&amp;quot;Incoming call | Caller: {CallerID} | DID: {DIDNumber} | Time: {currentTime}&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
                    foreach (var rule in routingRules)&lt;br /&gt;
                    {&lt;br /&gt;
                        if (!rule.Schedule.IsActiveTime(currentTime))&lt;br /&gt;
                            continue;&lt;br /&gt;
&lt;br /&gt;
                        bool didMatch = rule.DIDs.Contains(&amp;quot;*&amp;quot;) || rule.DIDs.Contains(DIDNumber);&lt;br /&gt;
                        bool callerMatch = rule.Callers.Contains(&amp;quot;*&amp;quot;) || rule.Callers.Contains(CallerID);&lt;br /&gt;
&lt;br /&gt;
                        if (!didMatch || !callerMatch)&lt;br /&gt;
                            continue;&lt;br /&gt;
&lt;br /&gt;
                        var destinationDN = ps.GetDNByNumber(rule.DestinationDN);&lt;br /&gt;
&lt;br /&gt;
                        if (destinationDN == null)&lt;br /&gt;
                        {&lt;br /&gt;
                            MyCall.Error($&amp;quot;Destination {rule.DestinationDN} not found.&amp;quot;);&lt;br /&gt;
                            continue;&lt;br /&gt;
                        }&lt;br /&gt;
&lt;br /&gt;
                        try&lt;br /&gt;
                        {&lt;br /&gt;
                            var result = await MyCall.RouteToAsync(new DestinationStruct(destinationDN));&lt;br /&gt;
                            MyCall.Info($&amp;quot;Routed to {rule.DestinationDN} | Result: {result}&amp;quot;);&lt;br /&gt;
                            intercepted = true;&lt;br /&gt;
                            break; // Stop at first matching rule&lt;br /&gt;
                        }&lt;br /&gt;
                        catch (Exception ex)&lt;br /&gt;
                        {&lt;br /&gt;
                            MyCall.Error($&amp;quot;Routing failed to {rule.DestinationDN}: {ex}&amp;quot;);&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
&lt;br /&gt;
                &lt;br /&gt;
                    // Utilisation de la route par défaut&lt;br /&gt;
                    &lt;br /&gt;
                    if (!intercepted)&lt;br /&gt;
                    {&lt;br /&gt;
                        var fallbackDN = ps.GetDNByNumber(DefaultDestinationDN);&lt;br /&gt;
                        if (fallbackDN != null)&lt;br /&gt;
                        {&lt;br /&gt;
                            try&lt;br /&gt;
                            {&lt;br /&gt;
                                var result = await MyCall.RouteToAsync(new DestinationStruct(fallbackDN));&lt;br /&gt;
                                MyCall.Info($&amp;quot;Fallback routing to {DefaultDestinationDN} | Result: {result}&amp;quot;);&lt;br /&gt;
                                intercepted = true;&lt;br /&gt;
                            }&lt;br /&gt;
                            catch (Exception ex)&lt;br /&gt;
                            {&lt;br /&gt;
                                MyCall.Error($&amp;quot;Fallback routing failed: {ex}&amp;quot;);&lt;br /&gt;
                            }&lt;br /&gt;
                        }&lt;br /&gt;
                        else&lt;br /&gt;
                        {&lt;br /&gt;
                            MyCall.Error($&amp;quot;Fallback DN {DefaultDestinationDN} not found.&amp;quot;);&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
&lt;br /&gt;
                    MyCall.Return(intercepted);&lt;br /&gt;
                });&lt;br /&gt;
            }&lt;br /&gt;
            catch (Exception ex)&lt;br /&gt;
            {&lt;br /&gt;
                MyCall.Error($&amp;quot;Script execution failed: {ex}&amp;quot;);&lt;br /&gt;
                MyCall.Return(false);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Mise en place du script===&lt;br /&gt;
&lt;br /&gt;
Connecté en admin dans 3CX :&lt;br /&gt;
 &lt;br /&gt;
 Admin / Intégrations / Scripts d&#039;appels / + Ajouter personnalisé&lt;br /&gt;
&lt;br /&gt;
[[Fichier:2026-05-27 15h34 23.png|cadre|right]]&lt;br /&gt;
# Nommer le script&lt;br /&gt;
#Choisir &#039;&#039;&#039;Quand cette SDA est composée&#039;&#039;&#039;&lt;br /&gt;
#Choisir la SDA appelée qui va déclencher le script&lt;br /&gt;
#Choisir le scope d&#039;action du script&lt;br /&gt;
#Cliquer sur OK&lt;br /&gt;
#Coller le script préparé dans la zone script&lt;br /&gt;
#Sauvegarder&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Catégorie:3CX]]&lt;/div&gt;</summary>
		<author><name>Anthony</name></author>
	</entry>
	<entry>
		<id>https://indywiki.fr/index.php?title=Script_de_routage_des_appels&amp;diff=22279</id>
		<title>Script de routage des appels</title>
		<link rel="alternate" type="text/html" href="https://indywiki.fr/index.php?title=Script_de_routage_des_appels&amp;diff=22279"/>
		<updated>2026-05-27T13:44:12Z</updated>

		<summary type="html">&lt;p&gt;Anthony : /* Mise en place du script */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Permet en fonction du moment de la semaine de router les appels vers telle ou telle destination.&lt;br /&gt;
&#039;&#039;&#039;Nécessite de supprimer les horaires de fermeture&#039;&#039;&#039; sur le département / instance 3CX ( c&#039;est le script qui gère )&lt;br /&gt;
&lt;br /&gt;
⚠️ les règles sont évaluées dans l&#039;ordre de leur apparition, il faut donc les déclarer de la plus spécifique à la plus générale ⚠️&lt;br /&gt;
&lt;br /&gt;
===Le script===&lt;br /&gt;
&lt;br /&gt;
Seules les lignes jaune requiert d&#039;être éditées. Si plus de règles sont à prévoir, dupliquer les sections &#039;&#039;&#039;new RoutingRule&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
* Ligne 16 : si aucune règle dans le script ne permet de déterminer un chemin, alors c&#039;est cette extension la cible&lt;br /&gt;
* Ligne 44 : Pour chaque règle, il faut définir les jours et horaires. sur cet exemple, le lundi de 14 à 17h, c&#039;est la règle 1 qui s&#039;applique.&lt;br /&gt;
* Ligne 50 : C&#039;est l&#039;extension qui va être visée par la règle, peut être un utilisateur, un SVI, un groupe , une file d&#039;attente.&lt;br /&gt;
* Ligne 51 : DID : ce filtre permet de tester le &#039;&#039;&#039;numéro appelé&#039;&#039;&#039; ( SDA  actif sur le système). En pratique on ne s&#039;en sert pas ici car le filtre se fait en amont de l&#039;appel du script. Mais possible. La syntaxe &#039;&#039;&#039;*&#039;&#039;&#039; permet de tout laisser passer&lt;br /&gt;
* Ligne 52 : Callers, on peut filtrer sur le &#039;&#039;&#039;numéros de l&#039;appelant&#039;&#039;&#039;. La syntaxe &#039;&#039;&#039;*&#039;&#039;&#039; permet de tout laisser passer&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;csharp&amp;quot; line highlight=&amp;quot;16,44,50-52&amp;quot;&amp;gt;&lt;br /&gt;
#nullable disable&lt;br /&gt;
using CallFlow;&lt;br /&gt;
using System;&lt;br /&gt;
using System.Threading.Tasks;&lt;br /&gt;
using TCX.Configuration;&lt;br /&gt;
using TCX.PBXAPI;&lt;br /&gt;
using System.Collections.Generic;&lt;br /&gt;
using System.Linq;&lt;br /&gt;
using CallFlow.CFD;&lt;br /&gt;
&lt;br /&gt;
namespace interceptcall&lt;br /&gt;
{&lt;br /&gt;
    public class InterceptInboundCall : ScriptBase&amp;lt;InterceptInboundCall&amp;gt;&lt;br /&gt;
    {&lt;br /&gt;
        // Destination par Défaut, à priori jamais utilisé car ce numéro doit toujours être joignable&lt;br /&gt;
        const string DefaultDestinationDN = &amp;quot;812&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
        // Structure d&#039;une règle de routage&lt;br /&gt;
        class RoutingRule&lt;br /&gt;
        {&lt;br /&gt;
            public Schedule Schedule { get; set; }&lt;br /&gt;
            public string DestinationDN { get; set; }&lt;br /&gt;
            public string[] DIDs { get; set; }&lt;br /&gt;
            public string[] Callers { get; set; }&lt;br /&gt;
&lt;br /&gt;
            public RoutingRule(Schedule schedule, string destinationDN, string[] dids, string[] callers)&lt;br /&gt;
            {&lt;br /&gt;
                Schedule = schedule;&lt;br /&gt;
                DestinationDN = destinationDN;&lt;br /&gt;
                DIDs = dids;&lt;br /&gt;
                Callers = callers;&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
		// Règle(s) de routage &amp;quot;First Match&amp;quot; : La première règle satisfaite est éxécutée, les suivantes sont ignorées&lt;br /&gt;
&lt;br /&gt;
       static readonly List&amp;lt;RoutingRule&amp;gt; routingRules = new List&amp;lt;RoutingRule&amp;gt;&lt;br /&gt;
        {&lt;br /&gt;
            // Règle 1 - Mairie ouverte - routage vers le 801 qui route vers le 100 ( pas de changements&lt;br /&gt;
            new RoutingRule(&lt;br /&gt;
                new Schedule(RuleHoursType.SpecificHours)&lt;br /&gt;
                {&lt;br /&gt;
					{ DayOfWeek.Monday,    new Schedule.PeriodOfDay(new TimeSpan(14,00,0), new TimeSpan(17,00,0)) },&lt;br /&gt;
					{ DayOfWeek.Tuesday,    new Schedule.PeriodOfDay(new TimeSpan(14,00,0), new TimeSpan(17,00,0)) },&lt;br /&gt;
					{ DayOfWeek.Wednesday,    new Schedule.PeriodOfDay(new TimeSpan(09,00,0), new TimeSpan(12,00,0)) },&lt;br /&gt;
                    { DayOfWeek.Thursday,    new Schedule.PeriodOfDay(new TimeSpan(09,00,0), new TimeSpan(12,00,0)) },&lt;br /&gt;
					{ DayOfWeek.Friday,    new Schedule.PeriodOfDay(new TimeSpan(09,00,0), new TimeSpan(12,00,0)) }&lt;br /&gt;
                },&lt;br /&gt;
                &amp;quot;801&amp;quot;,&lt;br /&gt;
                new[] { &amp;quot;*&amp;quot; },   // Tous les DIDs&lt;br /&gt;
                new[] { &amp;quot;*&amp;quot; }    // Tous les callers&lt;br /&gt;
            ),&lt;br /&gt;
			&lt;br /&gt;
			 // Règle 2 — Mairie fermée en semaine ( routage vers le 800 )&lt;br /&gt;
            new RoutingRule(&lt;br /&gt;
                new Schedule(RuleHoursType.SpecificHours)&lt;br /&gt;
                {&lt;br /&gt;
					{ DayOfWeek.Monday,    new Schedule.PeriodOfDay(new TimeSpan(8,00,0), new TimeSpan(14,00,0)) },&lt;br /&gt;
     				{ DayOfWeek.Monday,    new Schedule.PeriodOfDay(new TimeSpan(17,00,0), new TimeSpan(24,00,0)) },&lt;br /&gt;
					{ DayOfWeek.Tuesday,    new Schedule.PeriodOfDay(new TimeSpan(0,00,0), new TimeSpan(14,00,0)) },&lt;br /&gt;
					{ DayOfWeek.Tuesday,    new Schedule.PeriodOfDay(new TimeSpan(17,00,0), new TimeSpan(24,00,0)) },&lt;br /&gt;
					{ DayOfWeek.Wednesday,    new Schedule.PeriodOfDay(new TimeSpan(0,00,0), new TimeSpan(09,00,0)) },&lt;br /&gt;
					{ DayOfWeek.Wednesday,    new Schedule.PeriodOfDay(new TimeSpan(12,00,0), new TimeSpan(24,00,0)) },&lt;br /&gt;
      				{ DayOfWeek.Thursday,    new Schedule.PeriodOfDay(new TimeSpan(0,00,0), new TimeSpan(09,00,0)) },&lt;br /&gt;
					{ DayOfWeek.Thursday,    new Schedule.PeriodOfDay(new TimeSpan(12,00,0), new TimeSpan(24,00,0)) },&lt;br /&gt;
      				{ DayOfWeek.Friday,    new Schedule.PeriodOfDay(new TimeSpan(0,00,0), new TimeSpan(09,00,0)) },&lt;br /&gt;
					{ DayOfWeek.Friday,    new Schedule.PeriodOfDay(new TimeSpan(12,00,0), new TimeSpan(24,00,0)) }&lt;br /&gt;
                },&lt;br /&gt;
                &amp;quot;800&amp;quot;,&lt;br /&gt;
                new[] { &amp;quot;*&amp;quot; },&lt;br /&gt;
                new[] { &amp;quot;*&amp;quot; }&lt;br /&gt;
            ),&lt;br /&gt;
			&lt;br /&gt;
			 // Règle 3 — Mairie fermée le week-end ( vendredi 16h30 au lundi ? )&lt;br /&gt;
            new RoutingRule(&lt;br /&gt;
                new Schedule(RuleHoursType.SpecificHours)&lt;br /&gt;
                {&lt;br /&gt;
					&lt;br /&gt;
					{ DayOfWeek.Friday,    new Schedule.PeriodOfDay(new TimeSpan(16,30,0), new TimeSpan(24,00,0)) },&lt;br /&gt;
					{ DayOfWeek.Saturday, new Schedule.PeriodOfDay(new TimeSpan(0,00,0), new TimeSpan(24,00,0)) },&lt;br /&gt;
					{ DayOfWeek.Sunday, new Schedule.PeriodOfDay(new TimeSpan(0,00,0), new TimeSpan(24,00,0)) }&lt;br /&gt;
      				{ DayOfWeek.Monday, new Schedule.PeriodOfDay(new TimeSpan(0,00,0), new TimeSpan(08,00,0)) }&lt;br /&gt;
                },&lt;br /&gt;
                &amp;quot;804&amp;quot;,&lt;br /&gt;
                new[] { &amp;quot;*&amp;quot; },&lt;br /&gt;
                new[] { &amp;quot;*&amp;quot; }&lt;br /&gt;
            ),&lt;br /&gt;
			&lt;br /&gt;
        };&lt;br /&gt;
&lt;br /&gt;
        // Appel de la fonction principale&lt;br /&gt;
&lt;br /&gt;
        public override async void Start()&lt;br /&gt;
        {&lt;br /&gt;
            try&lt;br /&gt;
            {&lt;br /&gt;
                await Task.Run(async () =&amp;gt;&lt;br /&gt;
                {&lt;br /&gt;
                    bool intercepted = false;&lt;br /&gt;
                    var ps = MyCall.PS as PhoneSystem;&lt;br /&gt;
&lt;br /&gt;
                    if (!(MyCall.Caller.DN is ExternalLine externalLine))&lt;br /&gt;
                    {&lt;br /&gt;
                        MyCall.Return(false);&lt;br /&gt;
                        return;&lt;br /&gt;
                    }&lt;br /&gt;
&lt;br /&gt;
                    var DIDNumber = MyCall.Caller[&amp;quot;inbound_did&amp;quot;] ?? &amp;quot;&amp;quot;;&lt;br /&gt;
                    var CallerID = MyCall.Caller.CallerID ?? &amp;quot;&amp;quot;;&lt;br /&gt;
                    var currentTime = externalLine.Now(out var utc, out var timezone, out var groupmode);&lt;br /&gt;
&lt;br /&gt;
                    MyCall.Info($&amp;quot;Incoming call | Caller: {CallerID} | DID: {DIDNumber} | Time: {currentTime}&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
                    foreach (var rule in routingRules)&lt;br /&gt;
                    {&lt;br /&gt;
                        if (!rule.Schedule.IsActiveTime(currentTime))&lt;br /&gt;
                            continue;&lt;br /&gt;
&lt;br /&gt;
                        bool didMatch = rule.DIDs.Contains(&amp;quot;*&amp;quot;) || rule.DIDs.Contains(DIDNumber);&lt;br /&gt;
                        bool callerMatch = rule.Callers.Contains(&amp;quot;*&amp;quot;) || rule.Callers.Contains(CallerID);&lt;br /&gt;
&lt;br /&gt;
                        if (!didMatch || !callerMatch)&lt;br /&gt;
                            continue;&lt;br /&gt;
&lt;br /&gt;
                        var destinationDN = ps.GetDNByNumber(rule.DestinationDN);&lt;br /&gt;
&lt;br /&gt;
                        if (destinationDN == null)&lt;br /&gt;
                        {&lt;br /&gt;
                            MyCall.Error($&amp;quot;Destination {rule.DestinationDN} not found.&amp;quot;);&lt;br /&gt;
                            continue;&lt;br /&gt;
                        }&lt;br /&gt;
&lt;br /&gt;
                        try&lt;br /&gt;
                        {&lt;br /&gt;
                            var result = await MyCall.RouteToAsync(new DestinationStruct(destinationDN));&lt;br /&gt;
                            MyCall.Info($&amp;quot;Routed to {rule.DestinationDN} | Result: {result}&amp;quot;);&lt;br /&gt;
                            intercepted = true;&lt;br /&gt;
                            break; // Stop at first matching rule&lt;br /&gt;
                        }&lt;br /&gt;
                        catch (Exception ex)&lt;br /&gt;
                        {&lt;br /&gt;
                            MyCall.Error($&amp;quot;Routing failed to {rule.DestinationDN}: {ex}&amp;quot;);&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
&lt;br /&gt;
                &lt;br /&gt;
                    // Utilisation de la route par défaut&lt;br /&gt;
                    &lt;br /&gt;
                    if (!intercepted)&lt;br /&gt;
                    {&lt;br /&gt;
                        var fallbackDN = ps.GetDNByNumber(DefaultDestinationDN);&lt;br /&gt;
                        if (fallbackDN != null)&lt;br /&gt;
                        {&lt;br /&gt;
                            try&lt;br /&gt;
                            {&lt;br /&gt;
                                var result = await MyCall.RouteToAsync(new DestinationStruct(fallbackDN));&lt;br /&gt;
                                MyCall.Info($&amp;quot;Fallback routing to {DefaultDestinationDN} | Result: {result}&amp;quot;);&lt;br /&gt;
                                intercepted = true;&lt;br /&gt;
                            }&lt;br /&gt;
                            catch (Exception ex)&lt;br /&gt;
                            {&lt;br /&gt;
                                MyCall.Error($&amp;quot;Fallback routing failed: {ex}&amp;quot;);&lt;br /&gt;
                            }&lt;br /&gt;
                        }&lt;br /&gt;
                        else&lt;br /&gt;
                        {&lt;br /&gt;
                            MyCall.Error($&amp;quot;Fallback DN {DefaultDestinationDN} not found.&amp;quot;);&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
&lt;br /&gt;
                    MyCall.Return(intercepted);&lt;br /&gt;
                });&lt;br /&gt;
            }&lt;br /&gt;
            catch (Exception ex)&lt;br /&gt;
            {&lt;br /&gt;
                MyCall.Error($&amp;quot;Script execution failed: {ex}&amp;quot;);&lt;br /&gt;
                MyCall.Return(false);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Mise en place du script===&lt;br /&gt;
&lt;br /&gt;
Connecté en admin dans 3CX :&lt;br /&gt;
 &lt;br /&gt;
 Admin / Intégrations / Scripts d&#039;appels / + Ajouter personnalisé&lt;br /&gt;
&lt;br /&gt;
[[Fichier:2026-05-27 15h34 23.png|cadre|néant]]&lt;br /&gt;
# Nommer le script&lt;br /&gt;
#Choisir &#039;&#039;&#039;Quand cette SDA est composée&#039;&#039;&#039;&lt;br /&gt;
#Choisir la SDA appelée qui va déclencher le script&lt;br /&gt;
#Choisir le scope d&#039;action du script&lt;br /&gt;
#Cliquer sur OK&lt;br /&gt;
#Coller le script préparé dans la zone script&lt;br /&gt;
#Sauvegarder&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Catégorie:3CX]]&lt;/div&gt;</summary>
		<author><name>Anthony</name></author>
	</entry>
	<entry>
		<id>https://indywiki.fr/index.php?title=Script_de_routage_des_appels&amp;diff=22278</id>
		<title>Script de routage des appels</title>
		<link rel="alternate" type="text/html" href="https://indywiki.fr/index.php?title=Script_de_routage_des_appels&amp;diff=22278"/>
		<updated>2026-05-27T13:43:21Z</updated>

		<summary type="html">&lt;p&gt;Anthony : /* Mise en place du script */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Permet en fonction du moment de la semaine de router les appels vers telle ou telle destination.&lt;br /&gt;
&#039;&#039;&#039;Nécessite de supprimer les horaires de fermeture&#039;&#039;&#039; sur le département / instance 3CX ( c&#039;est le script qui gère )&lt;br /&gt;
&lt;br /&gt;
⚠️ les règles sont évaluées dans l&#039;ordre de leur apparition, il faut donc les déclarer de la plus spécifique à la plus générale ⚠️&lt;br /&gt;
&lt;br /&gt;
===Le script===&lt;br /&gt;
&lt;br /&gt;
Seules les lignes jaune requiert d&#039;être éditées. Si plus de règles sont à prévoir, dupliquer les sections &#039;&#039;&#039;new RoutingRule&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
* Ligne 16 : si aucune règle dans le script ne permet de déterminer un chemin, alors c&#039;est cette extension la cible&lt;br /&gt;
* Ligne 44 : Pour chaque règle, il faut définir les jours et horaires. sur cet exemple, le lundi de 14 à 17h, c&#039;est la règle 1 qui s&#039;applique.&lt;br /&gt;
* Ligne 50 : C&#039;est l&#039;extension qui va être visée par la règle, peut être un utilisateur, un SVI, un groupe , une file d&#039;attente.&lt;br /&gt;
* Ligne 51 : DID : ce filtre permet de tester le &#039;&#039;&#039;numéro appelé&#039;&#039;&#039; ( SDA  actif sur le système). En pratique on ne s&#039;en sert pas ici car le filtre se fait en amont de l&#039;appel du script. Mais possible. La syntaxe &#039;&#039;&#039;*&#039;&#039;&#039; permet de tout laisser passer&lt;br /&gt;
* Ligne 52 : Callers, on peut filtrer sur le &#039;&#039;&#039;numéros de l&#039;appelant&#039;&#039;&#039;. La syntaxe &#039;&#039;&#039;*&#039;&#039;&#039; permet de tout laisser passer&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;csharp&amp;quot; line highlight=&amp;quot;16,44,50-52&amp;quot;&amp;gt;&lt;br /&gt;
#nullable disable&lt;br /&gt;
using CallFlow;&lt;br /&gt;
using System;&lt;br /&gt;
using System.Threading.Tasks;&lt;br /&gt;
using TCX.Configuration;&lt;br /&gt;
using TCX.PBXAPI;&lt;br /&gt;
using System.Collections.Generic;&lt;br /&gt;
using System.Linq;&lt;br /&gt;
using CallFlow.CFD;&lt;br /&gt;
&lt;br /&gt;
namespace interceptcall&lt;br /&gt;
{&lt;br /&gt;
    public class InterceptInboundCall : ScriptBase&amp;lt;InterceptInboundCall&amp;gt;&lt;br /&gt;
    {&lt;br /&gt;
        // Destination par Défaut, à priori jamais utilisé car ce numéro doit toujours être joignable&lt;br /&gt;
        const string DefaultDestinationDN = &amp;quot;812&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
        // Structure d&#039;une règle de routage&lt;br /&gt;
        class RoutingRule&lt;br /&gt;
        {&lt;br /&gt;
            public Schedule Schedule { get; set; }&lt;br /&gt;
            public string DestinationDN { get; set; }&lt;br /&gt;
            public string[] DIDs { get; set; }&lt;br /&gt;
            public string[] Callers { get; set; }&lt;br /&gt;
&lt;br /&gt;
            public RoutingRule(Schedule schedule, string destinationDN, string[] dids, string[] callers)&lt;br /&gt;
            {&lt;br /&gt;
                Schedule = schedule;&lt;br /&gt;
                DestinationDN = destinationDN;&lt;br /&gt;
                DIDs = dids;&lt;br /&gt;
                Callers = callers;&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
		// Règle(s) de routage &amp;quot;First Match&amp;quot; : La première règle satisfaite est éxécutée, les suivantes sont ignorées&lt;br /&gt;
&lt;br /&gt;
       static readonly List&amp;lt;RoutingRule&amp;gt; routingRules = new List&amp;lt;RoutingRule&amp;gt;&lt;br /&gt;
        {&lt;br /&gt;
            // Règle 1 - Mairie ouverte - routage vers le 801 qui route vers le 100 ( pas de changements&lt;br /&gt;
            new RoutingRule(&lt;br /&gt;
                new Schedule(RuleHoursType.SpecificHours)&lt;br /&gt;
                {&lt;br /&gt;
					{ DayOfWeek.Monday,    new Schedule.PeriodOfDay(new TimeSpan(14,00,0), new TimeSpan(17,00,0)) },&lt;br /&gt;
					{ DayOfWeek.Tuesday,    new Schedule.PeriodOfDay(new TimeSpan(14,00,0), new TimeSpan(17,00,0)) },&lt;br /&gt;
					{ DayOfWeek.Wednesday,    new Schedule.PeriodOfDay(new TimeSpan(09,00,0), new TimeSpan(12,00,0)) },&lt;br /&gt;
                    { DayOfWeek.Thursday,    new Schedule.PeriodOfDay(new TimeSpan(09,00,0), new TimeSpan(12,00,0)) },&lt;br /&gt;
					{ DayOfWeek.Friday,    new Schedule.PeriodOfDay(new TimeSpan(09,00,0), new TimeSpan(12,00,0)) }&lt;br /&gt;
                },&lt;br /&gt;
                &amp;quot;801&amp;quot;,&lt;br /&gt;
                new[] { &amp;quot;*&amp;quot; },   // Tous les DIDs&lt;br /&gt;
                new[] { &amp;quot;*&amp;quot; }    // Tous les callers&lt;br /&gt;
            ),&lt;br /&gt;
			&lt;br /&gt;
			 // Règle 2 — Mairie fermée en semaine ( routage vers le 800 )&lt;br /&gt;
            new RoutingRule(&lt;br /&gt;
                new Schedule(RuleHoursType.SpecificHours)&lt;br /&gt;
                {&lt;br /&gt;
					{ DayOfWeek.Monday,    new Schedule.PeriodOfDay(new TimeSpan(8,00,0), new TimeSpan(14,00,0)) },&lt;br /&gt;
     				{ DayOfWeek.Monday,    new Schedule.PeriodOfDay(new TimeSpan(17,00,0), new TimeSpan(24,00,0)) },&lt;br /&gt;
					{ DayOfWeek.Tuesday,    new Schedule.PeriodOfDay(new TimeSpan(0,00,0), new TimeSpan(14,00,0)) },&lt;br /&gt;
					{ DayOfWeek.Tuesday,    new Schedule.PeriodOfDay(new TimeSpan(17,00,0), new TimeSpan(24,00,0)) },&lt;br /&gt;
					{ DayOfWeek.Wednesday,    new Schedule.PeriodOfDay(new TimeSpan(0,00,0), new TimeSpan(09,00,0)) },&lt;br /&gt;
					{ DayOfWeek.Wednesday,    new Schedule.PeriodOfDay(new TimeSpan(12,00,0), new TimeSpan(24,00,0)) },&lt;br /&gt;
      				{ DayOfWeek.Thursday,    new Schedule.PeriodOfDay(new TimeSpan(0,00,0), new TimeSpan(09,00,0)) },&lt;br /&gt;
					{ DayOfWeek.Thursday,    new Schedule.PeriodOfDay(new TimeSpan(12,00,0), new TimeSpan(24,00,0)) },&lt;br /&gt;
      				{ DayOfWeek.Friday,    new Schedule.PeriodOfDay(new TimeSpan(0,00,0), new TimeSpan(09,00,0)) },&lt;br /&gt;
					{ DayOfWeek.Friday,    new Schedule.PeriodOfDay(new TimeSpan(12,00,0), new TimeSpan(24,00,0)) }&lt;br /&gt;
                },&lt;br /&gt;
                &amp;quot;800&amp;quot;,&lt;br /&gt;
                new[] { &amp;quot;*&amp;quot; },&lt;br /&gt;
                new[] { &amp;quot;*&amp;quot; }&lt;br /&gt;
            ),&lt;br /&gt;
			&lt;br /&gt;
			 // Règle 3 — Mairie fermée le week-end ( vendredi 16h30 au lundi ? )&lt;br /&gt;
            new RoutingRule(&lt;br /&gt;
                new Schedule(RuleHoursType.SpecificHours)&lt;br /&gt;
                {&lt;br /&gt;
					&lt;br /&gt;
					{ DayOfWeek.Friday,    new Schedule.PeriodOfDay(new TimeSpan(16,30,0), new TimeSpan(24,00,0)) },&lt;br /&gt;
					{ DayOfWeek.Saturday, new Schedule.PeriodOfDay(new TimeSpan(0,00,0), new TimeSpan(24,00,0)) },&lt;br /&gt;
					{ DayOfWeek.Sunday, new Schedule.PeriodOfDay(new TimeSpan(0,00,0), new TimeSpan(24,00,0)) }&lt;br /&gt;
      				{ DayOfWeek.Monday, new Schedule.PeriodOfDay(new TimeSpan(0,00,0), new TimeSpan(08,00,0)) }&lt;br /&gt;
                },&lt;br /&gt;
                &amp;quot;804&amp;quot;,&lt;br /&gt;
                new[] { &amp;quot;*&amp;quot; },&lt;br /&gt;
                new[] { &amp;quot;*&amp;quot; }&lt;br /&gt;
            ),&lt;br /&gt;
			&lt;br /&gt;
        };&lt;br /&gt;
&lt;br /&gt;
        // Appel de la fonction principale&lt;br /&gt;
&lt;br /&gt;
        public override async void Start()&lt;br /&gt;
        {&lt;br /&gt;
            try&lt;br /&gt;
            {&lt;br /&gt;
                await Task.Run(async () =&amp;gt;&lt;br /&gt;
                {&lt;br /&gt;
                    bool intercepted = false;&lt;br /&gt;
                    var ps = MyCall.PS as PhoneSystem;&lt;br /&gt;
&lt;br /&gt;
                    if (!(MyCall.Caller.DN is ExternalLine externalLine))&lt;br /&gt;
                    {&lt;br /&gt;
                        MyCall.Return(false);&lt;br /&gt;
                        return;&lt;br /&gt;
                    }&lt;br /&gt;
&lt;br /&gt;
                    var DIDNumber = MyCall.Caller[&amp;quot;inbound_did&amp;quot;] ?? &amp;quot;&amp;quot;;&lt;br /&gt;
                    var CallerID = MyCall.Caller.CallerID ?? &amp;quot;&amp;quot;;&lt;br /&gt;
                    var currentTime = externalLine.Now(out var utc, out var timezone, out var groupmode);&lt;br /&gt;
&lt;br /&gt;
                    MyCall.Info($&amp;quot;Incoming call | Caller: {CallerID} | DID: {DIDNumber} | Time: {currentTime}&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
                    foreach (var rule in routingRules)&lt;br /&gt;
                    {&lt;br /&gt;
                        if (!rule.Schedule.IsActiveTime(currentTime))&lt;br /&gt;
                            continue;&lt;br /&gt;
&lt;br /&gt;
                        bool didMatch = rule.DIDs.Contains(&amp;quot;*&amp;quot;) || rule.DIDs.Contains(DIDNumber);&lt;br /&gt;
                        bool callerMatch = rule.Callers.Contains(&amp;quot;*&amp;quot;) || rule.Callers.Contains(CallerID);&lt;br /&gt;
&lt;br /&gt;
                        if (!didMatch || !callerMatch)&lt;br /&gt;
                            continue;&lt;br /&gt;
&lt;br /&gt;
                        var destinationDN = ps.GetDNByNumber(rule.DestinationDN);&lt;br /&gt;
&lt;br /&gt;
                        if (destinationDN == null)&lt;br /&gt;
                        {&lt;br /&gt;
                            MyCall.Error($&amp;quot;Destination {rule.DestinationDN} not found.&amp;quot;);&lt;br /&gt;
                            continue;&lt;br /&gt;
                        }&lt;br /&gt;
&lt;br /&gt;
                        try&lt;br /&gt;
                        {&lt;br /&gt;
                            var result = await MyCall.RouteToAsync(new DestinationStruct(destinationDN));&lt;br /&gt;
                            MyCall.Info($&amp;quot;Routed to {rule.DestinationDN} | Result: {result}&amp;quot;);&lt;br /&gt;
                            intercepted = true;&lt;br /&gt;
                            break; // Stop at first matching rule&lt;br /&gt;
                        }&lt;br /&gt;
                        catch (Exception ex)&lt;br /&gt;
                        {&lt;br /&gt;
                            MyCall.Error($&amp;quot;Routing failed to {rule.DestinationDN}: {ex}&amp;quot;);&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
&lt;br /&gt;
                &lt;br /&gt;
                    // Utilisation de la route par défaut&lt;br /&gt;
                    &lt;br /&gt;
                    if (!intercepted)&lt;br /&gt;
                    {&lt;br /&gt;
                        var fallbackDN = ps.GetDNByNumber(DefaultDestinationDN);&lt;br /&gt;
                        if (fallbackDN != null)&lt;br /&gt;
                        {&lt;br /&gt;
                            try&lt;br /&gt;
                            {&lt;br /&gt;
                                var result = await MyCall.RouteToAsync(new DestinationStruct(fallbackDN));&lt;br /&gt;
                                MyCall.Info($&amp;quot;Fallback routing to {DefaultDestinationDN} | Result: {result}&amp;quot;);&lt;br /&gt;
                                intercepted = true;&lt;br /&gt;
                            }&lt;br /&gt;
                            catch (Exception ex)&lt;br /&gt;
                            {&lt;br /&gt;
                                MyCall.Error($&amp;quot;Fallback routing failed: {ex}&amp;quot;);&lt;br /&gt;
                            }&lt;br /&gt;
                        }&lt;br /&gt;
                        else&lt;br /&gt;
                        {&lt;br /&gt;
                            MyCall.Error($&amp;quot;Fallback DN {DefaultDestinationDN} not found.&amp;quot;);&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
&lt;br /&gt;
                    MyCall.Return(intercepted);&lt;br /&gt;
                });&lt;br /&gt;
            }&lt;br /&gt;
            catch (Exception ex)&lt;br /&gt;
            {&lt;br /&gt;
                MyCall.Error($&amp;quot;Script execution failed: {ex}&amp;quot;);&lt;br /&gt;
                MyCall.Return(false);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Mise en place du script===&lt;br /&gt;
&lt;br /&gt;
Connecté en admin dans 3CX :&lt;br /&gt;
 &lt;br /&gt;
 Admin / Intégrations / Scripts d&#039;appels / + Ajouter personnalisé&lt;br /&gt;
&lt;br /&gt;
# Nommer le script&lt;br /&gt;
#Choisir &#039;&#039;&#039;Quand cette SDA est composée&#039;&#039;&#039;&lt;br /&gt;
#Choisir la SDA appelée qui va déclencher le script&lt;br /&gt;
#Choisir le scope d&#039;action du script&lt;br /&gt;
#Cliquer sur OK&lt;br /&gt;
#Coller le script préparé dans la zone script&lt;br /&gt;
#Sauvegarder&lt;br /&gt;
[[Fichier:2026-05-27 15h34 23.png|cadre|néant]]&lt;br /&gt;
&lt;br /&gt;
[[Catégorie:3CX]]&lt;/div&gt;</summary>
		<author><name>Anthony</name></author>
	</entry>
	<entry>
		<id>https://indywiki.fr/index.php?title=Script_de_routage_des_appels&amp;diff=22277</id>
		<title>Script de routage des appels</title>
		<link rel="alternate" type="text/html" href="https://indywiki.fr/index.php?title=Script_de_routage_des_appels&amp;diff=22277"/>
		<updated>2026-05-27T13:42:08Z</updated>

		<summary type="html">&lt;p&gt;Anthony : /* Mise en place du script */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Permet en fonction du moment de la semaine de router les appels vers telle ou telle destination.&lt;br /&gt;
&#039;&#039;&#039;Nécessite de supprimer les horaires de fermeture&#039;&#039;&#039; sur le département / instance 3CX ( c&#039;est le script qui gère )&lt;br /&gt;
&lt;br /&gt;
⚠️ les règles sont évaluées dans l&#039;ordre de leur apparition, il faut donc les déclarer de la plus spécifique à la plus générale ⚠️&lt;br /&gt;
&lt;br /&gt;
===Le script===&lt;br /&gt;
&lt;br /&gt;
Seules les lignes jaune requiert d&#039;être éditées. Si plus de règles sont à prévoir, dupliquer les sections &#039;&#039;&#039;new RoutingRule&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
* Ligne 16 : si aucune règle dans le script ne permet de déterminer un chemin, alors c&#039;est cette extension la cible&lt;br /&gt;
* Ligne 44 : Pour chaque règle, il faut définir les jours et horaires. sur cet exemple, le lundi de 14 à 17h, c&#039;est la règle 1 qui s&#039;applique.&lt;br /&gt;
* Ligne 50 : C&#039;est l&#039;extension qui va être visée par la règle, peut être un utilisateur, un SVI, un groupe , une file d&#039;attente.&lt;br /&gt;
* Ligne 51 : DID : ce filtre permet de tester le &#039;&#039;&#039;numéro appelé&#039;&#039;&#039; ( SDA  actif sur le système). En pratique on ne s&#039;en sert pas ici car le filtre se fait en amont de l&#039;appel du script. Mais possible. La syntaxe &#039;&#039;&#039;*&#039;&#039;&#039; permet de tout laisser passer&lt;br /&gt;
* Ligne 52 : Callers, on peut filtrer sur le &#039;&#039;&#039;numéros de l&#039;appelant&#039;&#039;&#039;. La syntaxe &#039;&#039;&#039;*&#039;&#039;&#039; permet de tout laisser passer&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;csharp&amp;quot; line highlight=&amp;quot;16,44,50-52&amp;quot;&amp;gt;&lt;br /&gt;
#nullable disable&lt;br /&gt;
using CallFlow;&lt;br /&gt;
using System;&lt;br /&gt;
using System.Threading.Tasks;&lt;br /&gt;
using TCX.Configuration;&lt;br /&gt;
using TCX.PBXAPI;&lt;br /&gt;
using System.Collections.Generic;&lt;br /&gt;
using System.Linq;&lt;br /&gt;
using CallFlow.CFD;&lt;br /&gt;
&lt;br /&gt;
namespace interceptcall&lt;br /&gt;
{&lt;br /&gt;
    public class InterceptInboundCall : ScriptBase&amp;lt;InterceptInboundCall&amp;gt;&lt;br /&gt;
    {&lt;br /&gt;
        // Destination par Défaut, à priori jamais utilisé car ce numéro doit toujours être joignable&lt;br /&gt;
        const string DefaultDestinationDN = &amp;quot;812&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
        // Structure d&#039;une règle de routage&lt;br /&gt;
        class RoutingRule&lt;br /&gt;
        {&lt;br /&gt;
            public Schedule Schedule { get; set; }&lt;br /&gt;
            public string DestinationDN { get; set; }&lt;br /&gt;
            public string[] DIDs { get; set; }&lt;br /&gt;
            public string[] Callers { get; set; }&lt;br /&gt;
&lt;br /&gt;
            public RoutingRule(Schedule schedule, string destinationDN, string[] dids, string[] callers)&lt;br /&gt;
            {&lt;br /&gt;
                Schedule = schedule;&lt;br /&gt;
                DestinationDN = destinationDN;&lt;br /&gt;
                DIDs = dids;&lt;br /&gt;
                Callers = callers;&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
		// Règle(s) de routage &amp;quot;First Match&amp;quot; : La première règle satisfaite est éxécutée, les suivantes sont ignorées&lt;br /&gt;
&lt;br /&gt;
       static readonly List&amp;lt;RoutingRule&amp;gt; routingRules = new List&amp;lt;RoutingRule&amp;gt;&lt;br /&gt;
        {&lt;br /&gt;
            // Règle 1 - Mairie ouverte - routage vers le 801 qui route vers le 100 ( pas de changements&lt;br /&gt;
            new RoutingRule(&lt;br /&gt;
                new Schedule(RuleHoursType.SpecificHours)&lt;br /&gt;
                {&lt;br /&gt;
					{ DayOfWeek.Monday,    new Schedule.PeriodOfDay(new TimeSpan(14,00,0), new TimeSpan(17,00,0)) },&lt;br /&gt;
					{ DayOfWeek.Tuesday,    new Schedule.PeriodOfDay(new TimeSpan(14,00,0), new TimeSpan(17,00,0)) },&lt;br /&gt;
					{ DayOfWeek.Wednesday,    new Schedule.PeriodOfDay(new TimeSpan(09,00,0), new TimeSpan(12,00,0)) },&lt;br /&gt;
                    { DayOfWeek.Thursday,    new Schedule.PeriodOfDay(new TimeSpan(09,00,0), new TimeSpan(12,00,0)) },&lt;br /&gt;
					{ DayOfWeek.Friday,    new Schedule.PeriodOfDay(new TimeSpan(09,00,0), new TimeSpan(12,00,0)) }&lt;br /&gt;
                },&lt;br /&gt;
                &amp;quot;801&amp;quot;,&lt;br /&gt;
                new[] { &amp;quot;*&amp;quot; },   // Tous les DIDs&lt;br /&gt;
                new[] { &amp;quot;*&amp;quot; }    // Tous les callers&lt;br /&gt;
            ),&lt;br /&gt;
			&lt;br /&gt;
			 // Règle 2 — Mairie fermée en semaine ( routage vers le 800 )&lt;br /&gt;
            new RoutingRule(&lt;br /&gt;
                new Schedule(RuleHoursType.SpecificHours)&lt;br /&gt;
                {&lt;br /&gt;
					{ DayOfWeek.Monday,    new Schedule.PeriodOfDay(new TimeSpan(8,00,0), new TimeSpan(14,00,0)) },&lt;br /&gt;
     				{ DayOfWeek.Monday,    new Schedule.PeriodOfDay(new TimeSpan(17,00,0), new TimeSpan(24,00,0)) },&lt;br /&gt;
					{ DayOfWeek.Tuesday,    new Schedule.PeriodOfDay(new TimeSpan(0,00,0), new TimeSpan(14,00,0)) },&lt;br /&gt;
					{ DayOfWeek.Tuesday,    new Schedule.PeriodOfDay(new TimeSpan(17,00,0), new TimeSpan(24,00,0)) },&lt;br /&gt;
					{ DayOfWeek.Wednesday,    new Schedule.PeriodOfDay(new TimeSpan(0,00,0), new TimeSpan(09,00,0)) },&lt;br /&gt;
					{ DayOfWeek.Wednesday,    new Schedule.PeriodOfDay(new TimeSpan(12,00,0), new TimeSpan(24,00,0)) },&lt;br /&gt;
      				{ DayOfWeek.Thursday,    new Schedule.PeriodOfDay(new TimeSpan(0,00,0), new TimeSpan(09,00,0)) },&lt;br /&gt;
					{ DayOfWeek.Thursday,    new Schedule.PeriodOfDay(new TimeSpan(12,00,0), new TimeSpan(24,00,0)) },&lt;br /&gt;
      				{ DayOfWeek.Friday,    new Schedule.PeriodOfDay(new TimeSpan(0,00,0), new TimeSpan(09,00,0)) },&lt;br /&gt;
					{ DayOfWeek.Friday,    new Schedule.PeriodOfDay(new TimeSpan(12,00,0), new TimeSpan(24,00,0)) }&lt;br /&gt;
                },&lt;br /&gt;
                &amp;quot;800&amp;quot;,&lt;br /&gt;
                new[] { &amp;quot;*&amp;quot; },&lt;br /&gt;
                new[] { &amp;quot;*&amp;quot; }&lt;br /&gt;
            ),&lt;br /&gt;
			&lt;br /&gt;
			 // Règle 3 — Mairie fermée le week-end ( vendredi 16h30 au lundi ? )&lt;br /&gt;
            new RoutingRule(&lt;br /&gt;
                new Schedule(RuleHoursType.SpecificHours)&lt;br /&gt;
                {&lt;br /&gt;
					&lt;br /&gt;
					{ DayOfWeek.Friday,    new Schedule.PeriodOfDay(new TimeSpan(16,30,0), new TimeSpan(24,00,0)) },&lt;br /&gt;
					{ DayOfWeek.Saturday, new Schedule.PeriodOfDay(new TimeSpan(0,00,0), new TimeSpan(24,00,0)) },&lt;br /&gt;
					{ DayOfWeek.Sunday, new Schedule.PeriodOfDay(new TimeSpan(0,00,0), new TimeSpan(24,00,0)) }&lt;br /&gt;
      				{ DayOfWeek.Monday, new Schedule.PeriodOfDay(new TimeSpan(0,00,0), new TimeSpan(08,00,0)) }&lt;br /&gt;
                },&lt;br /&gt;
                &amp;quot;804&amp;quot;,&lt;br /&gt;
                new[] { &amp;quot;*&amp;quot; },&lt;br /&gt;
                new[] { &amp;quot;*&amp;quot; }&lt;br /&gt;
            ),&lt;br /&gt;
			&lt;br /&gt;
        };&lt;br /&gt;
&lt;br /&gt;
        // Appel de la fonction principale&lt;br /&gt;
&lt;br /&gt;
        public override async void Start()&lt;br /&gt;
        {&lt;br /&gt;
            try&lt;br /&gt;
            {&lt;br /&gt;
                await Task.Run(async () =&amp;gt;&lt;br /&gt;
                {&lt;br /&gt;
                    bool intercepted = false;&lt;br /&gt;
                    var ps = MyCall.PS as PhoneSystem;&lt;br /&gt;
&lt;br /&gt;
                    if (!(MyCall.Caller.DN is ExternalLine externalLine))&lt;br /&gt;
                    {&lt;br /&gt;
                        MyCall.Return(false);&lt;br /&gt;
                        return;&lt;br /&gt;
                    }&lt;br /&gt;
&lt;br /&gt;
                    var DIDNumber = MyCall.Caller[&amp;quot;inbound_did&amp;quot;] ?? &amp;quot;&amp;quot;;&lt;br /&gt;
                    var CallerID = MyCall.Caller.CallerID ?? &amp;quot;&amp;quot;;&lt;br /&gt;
                    var currentTime = externalLine.Now(out var utc, out var timezone, out var groupmode);&lt;br /&gt;
&lt;br /&gt;
                    MyCall.Info($&amp;quot;Incoming call | Caller: {CallerID} | DID: {DIDNumber} | Time: {currentTime}&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
                    foreach (var rule in routingRules)&lt;br /&gt;
                    {&lt;br /&gt;
                        if (!rule.Schedule.IsActiveTime(currentTime))&lt;br /&gt;
                            continue;&lt;br /&gt;
&lt;br /&gt;
                        bool didMatch = rule.DIDs.Contains(&amp;quot;*&amp;quot;) || rule.DIDs.Contains(DIDNumber);&lt;br /&gt;
                        bool callerMatch = rule.Callers.Contains(&amp;quot;*&amp;quot;) || rule.Callers.Contains(CallerID);&lt;br /&gt;
&lt;br /&gt;
                        if (!didMatch || !callerMatch)&lt;br /&gt;
                            continue;&lt;br /&gt;
&lt;br /&gt;
                        var destinationDN = ps.GetDNByNumber(rule.DestinationDN);&lt;br /&gt;
&lt;br /&gt;
                        if (destinationDN == null)&lt;br /&gt;
                        {&lt;br /&gt;
                            MyCall.Error($&amp;quot;Destination {rule.DestinationDN} not found.&amp;quot;);&lt;br /&gt;
                            continue;&lt;br /&gt;
                        }&lt;br /&gt;
&lt;br /&gt;
                        try&lt;br /&gt;
                        {&lt;br /&gt;
                            var result = await MyCall.RouteToAsync(new DestinationStruct(destinationDN));&lt;br /&gt;
                            MyCall.Info($&amp;quot;Routed to {rule.DestinationDN} | Result: {result}&amp;quot;);&lt;br /&gt;
                            intercepted = true;&lt;br /&gt;
                            break; // Stop at first matching rule&lt;br /&gt;
                        }&lt;br /&gt;
                        catch (Exception ex)&lt;br /&gt;
                        {&lt;br /&gt;
                            MyCall.Error($&amp;quot;Routing failed to {rule.DestinationDN}: {ex}&amp;quot;);&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
&lt;br /&gt;
                &lt;br /&gt;
                    // Utilisation de la route par défaut&lt;br /&gt;
                    &lt;br /&gt;
                    if (!intercepted)&lt;br /&gt;
                    {&lt;br /&gt;
                        var fallbackDN = ps.GetDNByNumber(DefaultDestinationDN);&lt;br /&gt;
                        if (fallbackDN != null)&lt;br /&gt;
                        {&lt;br /&gt;
                            try&lt;br /&gt;
                            {&lt;br /&gt;
                                var result = await MyCall.RouteToAsync(new DestinationStruct(fallbackDN));&lt;br /&gt;
                                MyCall.Info($&amp;quot;Fallback routing to {DefaultDestinationDN} | Result: {result}&amp;quot;);&lt;br /&gt;
                                intercepted = true;&lt;br /&gt;
                            }&lt;br /&gt;
                            catch (Exception ex)&lt;br /&gt;
                            {&lt;br /&gt;
                                MyCall.Error($&amp;quot;Fallback routing failed: {ex}&amp;quot;);&lt;br /&gt;
                            }&lt;br /&gt;
                        }&lt;br /&gt;
                        else&lt;br /&gt;
                        {&lt;br /&gt;
                            MyCall.Error($&amp;quot;Fallback DN {DefaultDestinationDN} not found.&amp;quot;);&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
&lt;br /&gt;
                    MyCall.Return(intercepted);&lt;br /&gt;
                });&lt;br /&gt;
            }&lt;br /&gt;
            catch (Exception ex)&lt;br /&gt;
            {&lt;br /&gt;
                MyCall.Error($&amp;quot;Script execution failed: {ex}&amp;quot;);&lt;br /&gt;
                MyCall.Return(false);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Mise en place du script===&lt;br /&gt;
&lt;br /&gt;
Connecté en admin dans 3CX :&lt;br /&gt;
 &lt;br /&gt;
 Admin / Intégrations / Scripts d&#039;appels / + Ajouter personnalisé&lt;br /&gt;
&lt;br /&gt;
# Nommer le script&lt;br /&gt;
#Choisir &#039;&#039;&#039;Quand cette SDA est composée&#039;&#039;&#039;&lt;br /&gt;
#Choisir la SDA appelée qui va déclencher le script&lt;br /&gt;
#Choisir le scope d&#039;action du script&lt;br /&gt;
#Cliquer sur OK&lt;br /&gt;
#Coller le script préparé dans la zone script&lt;br /&gt;
#Sauvegarder&lt;br /&gt;
[[Fichier:2026-05-27 15h34 23.png|right]]&lt;br /&gt;
&lt;br /&gt;
[[Catégorie:3CX]]&lt;/div&gt;</summary>
		<author><name>Anthony</name></author>
	</entry>
	<entry>
		<id>https://indywiki.fr/index.php?title=Script_de_routage_des_appels&amp;diff=22276</id>
		<title>Script de routage des appels</title>
		<link rel="alternate" type="text/html" href="https://indywiki.fr/index.php?title=Script_de_routage_des_appels&amp;diff=22276"/>
		<updated>2026-05-27T13:41:20Z</updated>

		<summary type="html">&lt;p&gt;Anthony : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Permet en fonction du moment de la semaine de router les appels vers telle ou telle destination.&lt;br /&gt;
&#039;&#039;&#039;Nécessite de supprimer les horaires de fermeture&#039;&#039;&#039; sur le département / instance 3CX ( c&#039;est le script qui gère )&lt;br /&gt;
&lt;br /&gt;
⚠️ les règles sont évaluées dans l&#039;ordre de leur apparition, il faut donc les déclarer de la plus spécifique à la plus générale ⚠️&lt;br /&gt;
&lt;br /&gt;
===Le script===&lt;br /&gt;
&lt;br /&gt;
Seules les lignes jaune requiert d&#039;être éditées. Si plus de règles sont à prévoir, dupliquer les sections &#039;&#039;&#039;new RoutingRule&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
* Ligne 16 : si aucune règle dans le script ne permet de déterminer un chemin, alors c&#039;est cette extension la cible&lt;br /&gt;
* Ligne 44 : Pour chaque règle, il faut définir les jours et horaires. sur cet exemple, le lundi de 14 à 17h, c&#039;est la règle 1 qui s&#039;applique.&lt;br /&gt;
* Ligne 50 : C&#039;est l&#039;extension qui va être visée par la règle, peut être un utilisateur, un SVI, un groupe , une file d&#039;attente.&lt;br /&gt;
* Ligne 51 : DID : ce filtre permet de tester le &#039;&#039;&#039;numéro appelé&#039;&#039;&#039; ( SDA  actif sur le système). En pratique on ne s&#039;en sert pas ici car le filtre se fait en amont de l&#039;appel du script. Mais possible. La syntaxe &#039;&#039;&#039;*&#039;&#039;&#039; permet de tout laisser passer&lt;br /&gt;
* Ligne 52 : Callers, on peut filtrer sur le &#039;&#039;&#039;numéros de l&#039;appelant&#039;&#039;&#039;. La syntaxe &#039;&#039;&#039;*&#039;&#039;&#039; permet de tout laisser passer&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;csharp&amp;quot; line highlight=&amp;quot;16,44,50-52&amp;quot;&amp;gt;&lt;br /&gt;
#nullable disable&lt;br /&gt;
using CallFlow;&lt;br /&gt;
using System;&lt;br /&gt;
using System.Threading.Tasks;&lt;br /&gt;
using TCX.Configuration;&lt;br /&gt;
using TCX.PBXAPI;&lt;br /&gt;
using System.Collections.Generic;&lt;br /&gt;
using System.Linq;&lt;br /&gt;
using CallFlow.CFD;&lt;br /&gt;
&lt;br /&gt;
namespace interceptcall&lt;br /&gt;
{&lt;br /&gt;
    public class InterceptInboundCall : ScriptBase&amp;lt;InterceptInboundCall&amp;gt;&lt;br /&gt;
    {&lt;br /&gt;
        // Destination par Défaut, à priori jamais utilisé car ce numéro doit toujours être joignable&lt;br /&gt;
        const string DefaultDestinationDN = &amp;quot;812&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
        // Structure d&#039;une règle de routage&lt;br /&gt;
        class RoutingRule&lt;br /&gt;
        {&lt;br /&gt;
            public Schedule Schedule { get; set; }&lt;br /&gt;
            public string DestinationDN { get; set; }&lt;br /&gt;
            public string[] DIDs { get; set; }&lt;br /&gt;
            public string[] Callers { get; set; }&lt;br /&gt;
&lt;br /&gt;
            public RoutingRule(Schedule schedule, string destinationDN, string[] dids, string[] callers)&lt;br /&gt;
            {&lt;br /&gt;
                Schedule = schedule;&lt;br /&gt;
                DestinationDN = destinationDN;&lt;br /&gt;
                DIDs = dids;&lt;br /&gt;
                Callers = callers;&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
		// Règle(s) de routage &amp;quot;First Match&amp;quot; : La première règle satisfaite est éxécutée, les suivantes sont ignorées&lt;br /&gt;
&lt;br /&gt;
       static readonly List&amp;lt;RoutingRule&amp;gt; routingRules = new List&amp;lt;RoutingRule&amp;gt;&lt;br /&gt;
        {&lt;br /&gt;
            // Règle 1 - Mairie ouverte - routage vers le 801 qui route vers le 100 ( pas de changements&lt;br /&gt;
            new RoutingRule(&lt;br /&gt;
                new Schedule(RuleHoursType.SpecificHours)&lt;br /&gt;
                {&lt;br /&gt;
					{ DayOfWeek.Monday,    new Schedule.PeriodOfDay(new TimeSpan(14,00,0), new TimeSpan(17,00,0)) },&lt;br /&gt;
					{ DayOfWeek.Tuesday,    new Schedule.PeriodOfDay(new TimeSpan(14,00,0), new TimeSpan(17,00,0)) },&lt;br /&gt;
					{ DayOfWeek.Wednesday,    new Schedule.PeriodOfDay(new TimeSpan(09,00,0), new TimeSpan(12,00,0)) },&lt;br /&gt;
                    { DayOfWeek.Thursday,    new Schedule.PeriodOfDay(new TimeSpan(09,00,0), new TimeSpan(12,00,0)) },&lt;br /&gt;
					{ DayOfWeek.Friday,    new Schedule.PeriodOfDay(new TimeSpan(09,00,0), new TimeSpan(12,00,0)) }&lt;br /&gt;
                },&lt;br /&gt;
                &amp;quot;801&amp;quot;,&lt;br /&gt;
                new[] { &amp;quot;*&amp;quot; },   // Tous les DIDs&lt;br /&gt;
                new[] { &amp;quot;*&amp;quot; }    // Tous les callers&lt;br /&gt;
            ),&lt;br /&gt;
			&lt;br /&gt;
			 // Règle 2 — Mairie fermée en semaine ( routage vers le 800 )&lt;br /&gt;
            new RoutingRule(&lt;br /&gt;
                new Schedule(RuleHoursType.SpecificHours)&lt;br /&gt;
                {&lt;br /&gt;
					{ DayOfWeek.Monday,    new Schedule.PeriodOfDay(new TimeSpan(8,00,0), new TimeSpan(14,00,0)) },&lt;br /&gt;
     				{ DayOfWeek.Monday,    new Schedule.PeriodOfDay(new TimeSpan(17,00,0), new TimeSpan(24,00,0)) },&lt;br /&gt;
					{ DayOfWeek.Tuesday,    new Schedule.PeriodOfDay(new TimeSpan(0,00,0), new TimeSpan(14,00,0)) },&lt;br /&gt;
					{ DayOfWeek.Tuesday,    new Schedule.PeriodOfDay(new TimeSpan(17,00,0), new TimeSpan(24,00,0)) },&lt;br /&gt;
					{ DayOfWeek.Wednesday,    new Schedule.PeriodOfDay(new TimeSpan(0,00,0), new TimeSpan(09,00,0)) },&lt;br /&gt;
					{ DayOfWeek.Wednesday,    new Schedule.PeriodOfDay(new TimeSpan(12,00,0), new TimeSpan(24,00,0)) },&lt;br /&gt;
      				{ DayOfWeek.Thursday,    new Schedule.PeriodOfDay(new TimeSpan(0,00,0), new TimeSpan(09,00,0)) },&lt;br /&gt;
					{ DayOfWeek.Thursday,    new Schedule.PeriodOfDay(new TimeSpan(12,00,0), new TimeSpan(24,00,0)) },&lt;br /&gt;
      				{ DayOfWeek.Friday,    new Schedule.PeriodOfDay(new TimeSpan(0,00,0), new TimeSpan(09,00,0)) },&lt;br /&gt;
					{ DayOfWeek.Friday,    new Schedule.PeriodOfDay(new TimeSpan(12,00,0), new TimeSpan(24,00,0)) }&lt;br /&gt;
                },&lt;br /&gt;
                &amp;quot;800&amp;quot;,&lt;br /&gt;
                new[] { &amp;quot;*&amp;quot; },&lt;br /&gt;
                new[] { &amp;quot;*&amp;quot; }&lt;br /&gt;
            ),&lt;br /&gt;
			&lt;br /&gt;
			 // Règle 3 — Mairie fermée le week-end ( vendredi 16h30 au lundi ? )&lt;br /&gt;
            new RoutingRule(&lt;br /&gt;
                new Schedule(RuleHoursType.SpecificHours)&lt;br /&gt;
                {&lt;br /&gt;
					&lt;br /&gt;
					{ DayOfWeek.Friday,    new Schedule.PeriodOfDay(new TimeSpan(16,30,0), new TimeSpan(24,00,0)) },&lt;br /&gt;
					{ DayOfWeek.Saturday, new Schedule.PeriodOfDay(new TimeSpan(0,00,0), new TimeSpan(24,00,0)) },&lt;br /&gt;
					{ DayOfWeek.Sunday, new Schedule.PeriodOfDay(new TimeSpan(0,00,0), new TimeSpan(24,00,0)) }&lt;br /&gt;
      				{ DayOfWeek.Monday, new Schedule.PeriodOfDay(new TimeSpan(0,00,0), new TimeSpan(08,00,0)) }&lt;br /&gt;
                },&lt;br /&gt;
                &amp;quot;804&amp;quot;,&lt;br /&gt;
                new[] { &amp;quot;*&amp;quot; },&lt;br /&gt;
                new[] { &amp;quot;*&amp;quot; }&lt;br /&gt;
            ),&lt;br /&gt;
			&lt;br /&gt;
        };&lt;br /&gt;
&lt;br /&gt;
        // Appel de la fonction principale&lt;br /&gt;
&lt;br /&gt;
        public override async void Start()&lt;br /&gt;
        {&lt;br /&gt;
            try&lt;br /&gt;
            {&lt;br /&gt;
                await Task.Run(async () =&amp;gt;&lt;br /&gt;
                {&lt;br /&gt;
                    bool intercepted = false;&lt;br /&gt;
                    var ps = MyCall.PS as PhoneSystem;&lt;br /&gt;
&lt;br /&gt;
                    if (!(MyCall.Caller.DN is ExternalLine externalLine))&lt;br /&gt;
                    {&lt;br /&gt;
                        MyCall.Return(false);&lt;br /&gt;
                        return;&lt;br /&gt;
                    }&lt;br /&gt;
&lt;br /&gt;
                    var DIDNumber = MyCall.Caller[&amp;quot;inbound_did&amp;quot;] ?? &amp;quot;&amp;quot;;&lt;br /&gt;
                    var CallerID = MyCall.Caller.CallerID ?? &amp;quot;&amp;quot;;&lt;br /&gt;
                    var currentTime = externalLine.Now(out var utc, out var timezone, out var groupmode);&lt;br /&gt;
&lt;br /&gt;
                    MyCall.Info($&amp;quot;Incoming call | Caller: {CallerID} | DID: {DIDNumber} | Time: {currentTime}&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
                    foreach (var rule in routingRules)&lt;br /&gt;
                    {&lt;br /&gt;
                        if (!rule.Schedule.IsActiveTime(currentTime))&lt;br /&gt;
                            continue;&lt;br /&gt;
&lt;br /&gt;
                        bool didMatch = rule.DIDs.Contains(&amp;quot;*&amp;quot;) || rule.DIDs.Contains(DIDNumber);&lt;br /&gt;
                        bool callerMatch = rule.Callers.Contains(&amp;quot;*&amp;quot;) || rule.Callers.Contains(CallerID);&lt;br /&gt;
&lt;br /&gt;
                        if (!didMatch || !callerMatch)&lt;br /&gt;
                            continue;&lt;br /&gt;
&lt;br /&gt;
                        var destinationDN = ps.GetDNByNumber(rule.DestinationDN);&lt;br /&gt;
&lt;br /&gt;
                        if (destinationDN == null)&lt;br /&gt;
                        {&lt;br /&gt;
                            MyCall.Error($&amp;quot;Destination {rule.DestinationDN} not found.&amp;quot;);&lt;br /&gt;
                            continue;&lt;br /&gt;
                        }&lt;br /&gt;
&lt;br /&gt;
                        try&lt;br /&gt;
                        {&lt;br /&gt;
                            var result = await MyCall.RouteToAsync(new DestinationStruct(destinationDN));&lt;br /&gt;
                            MyCall.Info($&amp;quot;Routed to {rule.DestinationDN} | Result: {result}&amp;quot;);&lt;br /&gt;
                            intercepted = true;&lt;br /&gt;
                            break; // Stop at first matching rule&lt;br /&gt;
                        }&lt;br /&gt;
                        catch (Exception ex)&lt;br /&gt;
                        {&lt;br /&gt;
                            MyCall.Error($&amp;quot;Routing failed to {rule.DestinationDN}: {ex}&amp;quot;);&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
&lt;br /&gt;
                &lt;br /&gt;
                    // Utilisation de la route par défaut&lt;br /&gt;
                    &lt;br /&gt;
                    if (!intercepted)&lt;br /&gt;
                    {&lt;br /&gt;
                        var fallbackDN = ps.GetDNByNumber(DefaultDestinationDN);&lt;br /&gt;
                        if (fallbackDN != null)&lt;br /&gt;
                        {&lt;br /&gt;
                            try&lt;br /&gt;
                            {&lt;br /&gt;
                                var result = await MyCall.RouteToAsync(new DestinationStruct(fallbackDN));&lt;br /&gt;
                                MyCall.Info($&amp;quot;Fallback routing to {DefaultDestinationDN} | Result: {result}&amp;quot;);&lt;br /&gt;
                                intercepted = true;&lt;br /&gt;
                            }&lt;br /&gt;
                            catch (Exception ex)&lt;br /&gt;
                            {&lt;br /&gt;
                                MyCall.Error($&amp;quot;Fallback routing failed: {ex}&amp;quot;);&lt;br /&gt;
                            }&lt;br /&gt;
                        }&lt;br /&gt;
                        else&lt;br /&gt;
                        {&lt;br /&gt;
                            MyCall.Error($&amp;quot;Fallback DN {DefaultDestinationDN} not found.&amp;quot;);&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
&lt;br /&gt;
                    MyCall.Return(intercepted);&lt;br /&gt;
                });&lt;br /&gt;
            }&lt;br /&gt;
            catch (Exception ex)&lt;br /&gt;
            {&lt;br /&gt;
                MyCall.Error($&amp;quot;Script execution failed: {ex}&amp;quot;);&lt;br /&gt;
                MyCall.Return(false);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Mise en place du script===&lt;br /&gt;
&lt;br /&gt;
Connecté en admin dans 3CX :&lt;br /&gt;
 &lt;br /&gt;
 Admin / Intégrations / Scripts d&#039;appels / + Ajouter personnalisé&lt;br /&gt;
&lt;br /&gt;
# Nommer le script&lt;br /&gt;
#Choisir &#039;&#039;&#039;Quand cette SDA est composée&#039;&#039;&#039;&lt;br /&gt;
#Choisir la SDA appelée qui va déclencher le script&lt;br /&gt;
#Choisir le scope d&#039;action du script&lt;br /&gt;
#Cliquer sur OK&lt;br /&gt;
#Coller le script préparé dans la zone script&lt;br /&gt;
#Sauvegarder&lt;br /&gt;
[[Fichier:2026-05-27 15h34 23.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 &lt;br /&gt;
&lt;br /&gt;
[[Catégorie:3CX]]&lt;/div&gt;</summary>
		<author><name>Anthony</name></author>
	</entry>
	<entry>
		<id>https://indywiki.fr/index.php?title=Script_de_routage_des_appels&amp;diff=22275</id>
		<title>Script de routage des appels</title>
		<link rel="alternate" type="text/html" href="https://indywiki.fr/index.php?title=Script_de_routage_des_appels&amp;diff=22275"/>
		<updated>2026-05-27T13:39:40Z</updated>

		<summary type="html">&lt;p&gt;Anthony : /* Le script */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Permet en fonction du moment de la semaine de router les appels vers telle ou telle destination.&lt;br /&gt;
&#039;&#039;&#039;Nécessite de supprimer les horaires de fermeture&#039;&#039;&#039; sur le département / instance 3CX ( c&#039;est le script qui gère )&lt;br /&gt;
&lt;br /&gt;
===Le script===&lt;br /&gt;
&lt;br /&gt;
Seules les lignes jaune requiert d&#039;être éditées. Si plus de règles sont à prévoir, dupliquer les sections &#039;&#039;&#039;new RoutingRule&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
* Ligne 16 : si aucune règle dans le script ne permet de déterminer un chemin, alors c&#039;est cette extension la cible&lt;br /&gt;
* Ligne 44 : Pour chaque règle, il faut définir les jours et horaires. sur cet exemple, le lundi de 14 à 17h, c&#039;est la règle 1 qui s&#039;applique.&lt;br /&gt;
* Ligne 50 : C&#039;est l&#039;extension qui va être visée par la règle, peut être un utilisateur, un SVI, un groupe , une file d&#039;attente.&lt;br /&gt;
* Ligne 51 : DID : ce filtre permet de tester le &#039;&#039;&#039;numéro appelé&#039;&#039;&#039; ( SDA  actif sur le système). En pratique on ne s&#039;en sert pas ici car le filtre se fait en amont de l&#039;appel du script. Mais possible. La syntaxe &#039;&#039;&#039;*&#039;&#039;&#039; permet de tout laisser passer&lt;br /&gt;
* Ligne 52 : Callers, on peut filtrer sur le &#039;&#039;&#039;numéros de l&#039;appelant&#039;&#039;&#039;. La syntaxe &#039;&#039;&#039;*&#039;&#039;&#039; permet de tout laisser passer&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;csharp&amp;quot; line highlight=&amp;quot;16,44,50-52&amp;quot;&amp;gt;&lt;br /&gt;
#nullable disable&lt;br /&gt;
using CallFlow;&lt;br /&gt;
using System;&lt;br /&gt;
using System.Threading.Tasks;&lt;br /&gt;
using TCX.Configuration;&lt;br /&gt;
using TCX.PBXAPI;&lt;br /&gt;
using System.Collections.Generic;&lt;br /&gt;
using System.Linq;&lt;br /&gt;
using CallFlow.CFD;&lt;br /&gt;
&lt;br /&gt;
namespace interceptcall&lt;br /&gt;
{&lt;br /&gt;
    public class InterceptInboundCall : ScriptBase&amp;lt;InterceptInboundCall&amp;gt;&lt;br /&gt;
    {&lt;br /&gt;
        // Destination par Défaut, à priori jamais utilisé car ce numéro doit toujours être joignable&lt;br /&gt;
        const string DefaultDestinationDN = &amp;quot;812&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
        // Structure d&#039;une règle de routage&lt;br /&gt;
        class RoutingRule&lt;br /&gt;
        {&lt;br /&gt;
            public Schedule Schedule { get; set; }&lt;br /&gt;
            public string DestinationDN { get; set; }&lt;br /&gt;
            public string[] DIDs { get; set; }&lt;br /&gt;
            public string[] Callers { get; set; }&lt;br /&gt;
&lt;br /&gt;
            public RoutingRule(Schedule schedule, string destinationDN, string[] dids, string[] callers)&lt;br /&gt;
            {&lt;br /&gt;
                Schedule = schedule;&lt;br /&gt;
                DestinationDN = destinationDN;&lt;br /&gt;
                DIDs = dids;&lt;br /&gt;
                Callers = callers;&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
		// Règle(s) de routage &amp;quot;First Match&amp;quot; : La première règle satisfaite est éxécutée, les suivantes sont ignorées&lt;br /&gt;
&lt;br /&gt;
       static readonly List&amp;lt;RoutingRule&amp;gt; routingRules = new List&amp;lt;RoutingRule&amp;gt;&lt;br /&gt;
        {&lt;br /&gt;
            // Règle 1 - Mairie ouverte - routage vers le 801 qui route vers le 100 ( pas de changements&lt;br /&gt;
            new RoutingRule(&lt;br /&gt;
                new Schedule(RuleHoursType.SpecificHours)&lt;br /&gt;
                {&lt;br /&gt;
					{ DayOfWeek.Monday,    new Schedule.PeriodOfDay(new TimeSpan(14,00,0), new TimeSpan(17,00,0)) },&lt;br /&gt;
					{ DayOfWeek.Tuesday,    new Schedule.PeriodOfDay(new TimeSpan(14,00,0), new TimeSpan(17,00,0)) },&lt;br /&gt;
					{ DayOfWeek.Wednesday,    new Schedule.PeriodOfDay(new TimeSpan(09,00,0), new TimeSpan(12,00,0)) },&lt;br /&gt;
                    { DayOfWeek.Thursday,    new Schedule.PeriodOfDay(new TimeSpan(09,00,0), new TimeSpan(12,00,0)) },&lt;br /&gt;
					{ DayOfWeek.Friday,    new Schedule.PeriodOfDay(new TimeSpan(09,00,0), new TimeSpan(12,00,0)) }&lt;br /&gt;
                },&lt;br /&gt;
                &amp;quot;801&amp;quot;,&lt;br /&gt;
                new[] { &amp;quot;*&amp;quot; },   // Tous les DIDs&lt;br /&gt;
                new[] { &amp;quot;*&amp;quot; }    // Tous les callers&lt;br /&gt;
            ),&lt;br /&gt;
			&lt;br /&gt;
			 // Règle 2 — Mairie fermée en semaine ( routage vers le 800 )&lt;br /&gt;
            new RoutingRule(&lt;br /&gt;
                new Schedule(RuleHoursType.SpecificHours)&lt;br /&gt;
                {&lt;br /&gt;
					{ DayOfWeek.Monday,    new Schedule.PeriodOfDay(new TimeSpan(8,00,0), new TimeSpan(14,00,0)) },&lt;br /&gt;
     				{ DayOfWeek.Monday,    new Schedule.PeriodOfDay(new TimeSpan(17,00,0), new TimeSpan(24,00,0)) },&lt;br /&gt;
					{ DayOfWeek.Tuesday,    new Schedule.PeriodOfDay(new TimeSpan(0,00,0), new TimeSpan(14,00,0)) },&lt;br /&gt;
					{ DayOfWeek.Tuesday,    new Schedule.PeriodOfDay(new TimeSpan(17,00,0), new TimeSpan(24,00,0)) },&lt;br /&gt;
					{ DayOfWeek.Wednesday,    new Schedule.PeriodOfDay(new TimeSpan(0,00,0), new TimeSpan(09,00,0)) },&lt;br /&gt;
					{ DayOfWeek.Wednesday,    new Schedule.PeriodOfDay(new TimeSpan(12,00,0), new TimeSpan(24,00,0)) },&lt;br /&gt;
      				{ DayOfWeek.Thursday,    new Schedule.PeriodOfDay(new TimeSpan(0,00,0), new TimeSpan(09,00,0)) },&lt;br /&gt;
					{ DayOfWeek.Thursday,    new Schedule.PeriodOfDay(new TimeSpan(12,00,0), new TimeSpan(24,00,0)) },&lt;br /&gt;
      				{ DayOfWeek.Friday,    new Schedule.PeriodOfDay(new TimeSpan(0,00,0), new TimeSpan(09,00,0)) },&lt;br /&gt;
					{ DayOfWeek.Friday,    new Schedule.PeriodOfDay(new TimeSpan(12,00,0), new TimeSpan(24,00,0)) }&lt;br /&gt;
                },&lt;br /&gt;
                &amp;quot;800&amp;quot;,&lt;br /&gt;
                new[] { &amp;quot;*&amp;quot; },&lt;br /&gt;
                new[] { &amp;quot;*&amp;quot; }&lt;br /&gt;
            ),&lt;br /&gt;
			&lt;br /&gt;
			 // Règle 3 — Mairie fermée le week-end ( vendredi 16h30 au lundi ? )&lt;br /&gt;
            new RoutingRule(&lt;br /&gt;
                new Schedule(RuleHoursType.SpecificHours)&lt;br /&gt;
                {&lt;br /&gt;
					&lt;br /&gt;
					{ DayOfWeek.Friday,    new Schedule.PeriodOfDay(new TimeSpan(16,30,0), new TimeSpan(24,00,0)) },&lt;br /&gt;
					{ DayOfWeek.Saturday, new Schedule.PeriodOfDay(new TimeSpan(0,00,0), new TimeSpan(24,00,0)) },&lt;br /&gt;
					{ DayOfWeek.Sunday, new Schedule.PeriodOfDay(new TimeSpan(0,00,0), new TimeSpan(24,00,0)) }&lt;br /&gt;
      				{ DayOfWeek.Monday, new Schedule.PeriodOfDay(new TimeSpan(0,00,0), new TimeSpan(08,00,0)) }&lt;br /&gt;
                },&lt;br /&gt;
                &amp;quot;804&amp;quot;,&lt;br /&gt;
                new[] { &amp;quot;*&amp;quot; },&lt;br /&gt;
                new[] { &amp;quot;*&amp;quot; }&lt;br /&gt;
            ),&lt;br /&gt;
			&lt;br /&gt;
        };&lt;br /&gt;
&lt;br /&gt;
        // Appel de la fonction principale&lt;br /&gt;
&lt;br /&gt;
        public override async void Start()&lt;br /&gt;
        {&lt;br /&gt;
            try&lt;br /&gt;
            {&lt;br /&gt;
                await Task.Run(async () =&amp;gt;&lt;br /&gt;
                {&lt;br /&gt;
                    bool intercepted = false;&lt;br /&gt;
                    var ps = MyCall.PS as PhoneSystem;&lt;br /&gt;
&lt;br /&gt;
                    if (!(MyCall.Caller.DN is ExternalLine externalLine))&lt;br /&gt;
                    {&lt;br /&gt;
                        MyCall.Return(false);&lt;br /&gt;
                        return;&lt;br /&gt;
                    }&lt;br /&gt;
&lt;br /&gt;
                    var DIDNumber = MyCall.Caller[&amp;quot;inbound_did&amp;quot;] ?? &amp;quot;&amp;quot;;&lt;br /&gt;
                    var CallerID = MyCall.Caller.CallerID ?? &amp;quot;&amp;quot;;&lt;br /&gt;
                    var currentTime = externalLine.Now(out var utc, out var timezone, out var groupmode);&lt;br /&gt;
&lt;br /&gt;
                    MyCall.Info($&amp;quot;Incoming call | Caller: {CallerID} | DID: {DIDNumber} | Time: {currentTime}&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
                    foreach (var rule in routingRules)&lt;br /&gt;
                    {&lt;br /&gt;
                        if (!rule.Schedule.IsActiveTime(currentTime))&lt;br /&gt;
                            continue;&lt;br /&gt;
&lt;br /&gt;
                        bool didMatch = rule.DIDs.Contains(&amp;quot;*&amp;quot;) || rule.DIDs.Contains(DIDNumber);&lt;br /&gt;
                        bool callerMatch = rule.Callers.Contains(&amp;quot;*&amp;quot;) || rule.Callers.Contains(CallerID);&lt;br /&gt;
&lt;br /&gt;
                        if (!didMatch || !callerMatch)&lt;br /&gt;
                            continue;&lt;br /&gt;
&lt;br /&gt;
                        var destinationDN = ps.GetDNByNumber(rule.DestinationDN);&lt;br /&gt;
&lt;br /&gt;
                        if (destinationDN == null)&lt;br /&gt;
                        {&lt;br /&gt;
                            MyCall.Error($&amp;quot;Destination {rule.DestinationDN} not found.&amp;quot;);&lt;br /&gt;
                            continue;&lt;br /&gt;
                        }&lt;br /&gt;
&lt;br /&gt;
                        try&lt;br /&gt;
                        {&lt;br /&gt;
                            var result = await MyCall.RouteToAsync(new DestinationStruct(destinationDN));&lt;br /&gt;
                            MyCall.Info($&amp;quot;Routed to {rule.DestinationDN} | Result: {result}&amp;quot;);&lt;br /&gt;
                            intercepted = true;&lt;br /&gt;
                            break; // Stop at first matching rule&lt;br /&gt;
                        }&lt;br /&gt;
                        catch (Exception ex)&lt;br /&gt;
                        {&lt;br /&gt;
                            MyCall.Error($&amp;quot;Routing failed to {rule.DestinationDN}: {ex}&amp;quot;);&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
&lt;br /&gt;
                &lt;br /&gt;
                    // Utilisation de la route par défaut&lt;br /&gt;
                    &lt;br /&gt;
                    if (!intercepted)&lt;br /&gt;
                    {&lt;br /&gt;
                        var fallbackDN = ps.GetDNByNumber(DefaultDestinationDN);&lt;br /&gt;
                        if (fallbackDN != null)&lt;br /&gt;
                        {&lt;br /&gt;
                            try&lt;br /&gt;
                            {&lt;br /&gt;
                                var result = await MyCall.RouteToAsync(new DestinationStruct(fallbackDN));&lt;br /&gt;
                                MyCall.Info($&amp;quot;Fallback routing to {DefaultDestinationDN} | Result: {result}&amp;quot;);&lt;br /&gt;
                                intercepted = true;&lt;br /&gt;
                            }&lt;br /&gt;
                            catch (Exception ex)&lt;br /&gt;
                            {&lt;br /&gt;
                                MyCall.Error($&amp;quot;Fallback routing failed: {ex}&amp;quot;);&lt;br /&gt;
                            }&lt;br /&gt;
                        }&lt;br /&gt;
                        else&lt;br /&gt;
                        {&lt;br /&gt;
                            MyCall.Error($&amp;quot;Fallback DN {DefaultDestinationDN} not found.&amp;quot;);&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
&lt;br /&gt;
                    MyCall.Return(intercepted);&lt;br /&gt;
                });&lt;br /&gt;
            }&lt;br /&gt;
            catch (Exception ex)&lt;br /&gt;
            {&lt;br /&gt;
                MyCall.Error($&amp;quot;Script execution failed: {ex}&amp;quot;);&lt;br /&gt;
                MyCall.Return(false);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Mise en place du script===&lt;br /&gt;
&lt;br /&gt;
Connecté en admin dans 3CX :&lt;br /&gt;
 &lt;br /&gt;
 Admin / Intégrations / Scripts d&#039;appels / + Ajouter personnalisé&lt;br /&gt;
&lt;br /&gt;
# Nommer le script&lt;br /&gt;
#Choisir &#039;&#039;&#039;Quand cette SDA est composée&#039;&#039;&#039;&lt;br /&gt;
#Choisir la SDA appelée qui va déclencher le script&lt;br /&gt;
#Choisir le scope d&#039;action du script&lt;br /&gt;
#Cliquer sur OK&lt;br /&gt;
#Coller le script préparé dans la zone script&lt;br /&gt;
#Sauvegarder&lt;br /&gt;
[[Fichier:2026-05-27 15h34 23.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 &lt;br /&gt;
&lt;br /&gt;
[[Catégorie:3CX]]&lt;/div&gt;</summary>
		<author><name>Anthony</name></author>
	</entry>
	<entry>
		<id>https://indywiki.fr/index.php?title=Script_de_routage_des_appels&amp;diff=22274</id>
		<title>Script de routage des appels</title>
		<link rel="alternate" type="text/html" href="https://indywiki.fr/index.php?title=Script_de_routage_des_appels&amp;diff=22274"/>
		<updated>2026-05-27T13:38:17Z</updated>

		<summary type="html">&lt;p&gt;Anthony : /* Mise en place du script */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Permet en fonction du moment de la semaine de router les appels vers telle ou telle destination.&lt;br /&gt;
&#039;&#039;&#039;Nécessite de supprimer les horaires de fermeture&#039;&#039;&#039; sur le département / instance 3CX ( c&#039;est le script qui gère )&lt;br /&gt;
&lt;br /&gt;
===Le script===&lt;br /&gt;
&lt;br /&gt;
Seul les lignes en jaune requiert d&#039;être éditer. Si plus de règles sont à prévoir, dupliquer les sections.&lt;br /&gt;
&lt;br /&gt;
* Ligne 16 : si aucune règle dans le script ne permet de déterminer un chemin, alors c&#039;est cette extension la cible&lt;br /&gt;
* Ligne 44 : Pour chaque règle, il faut définir les jours et horaires. sur cet exemple, le lundi de 14 à 17h, c&#039;est la règle 1 qui s&#039;applique.&lt;br /&gt;
* Ligne 50 : C&#039;est l&#039;extension qui va être visée par la règle, peut être un utilisateur, un SVI, un groupe , une file d&#039;attente.&lt;br /&gt;
* Ligne 51 : DID : ce filtre permet de tester le &#039;&#039;&#039;numéro appelé&#039;&#039;&#039; ( SDA  actif sur le système). En pratique on ne s&#039;en sert pas ici car le filtre se fait en amont de l&#039;appel du script. Mais possible. La syntaxe &#039;&#039;&#039;*&#039;&#039;&#039; permet de tout laisser passer&lt;br /&gt;
* Ligne 52 : Callers, on peut filtrer sur le &#039;&#039;&#039;numéros de l&#039;appelant&#039;&#039;&#039;. La syntaxe &#039;&#039;&#039;*&#039;&#039;&#039; permet de tout laisser passer&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;csharp&amp;quot; line highlight=&amp;quot;16,44,50-52&amp;quot;&amp;gt;&lt;br /&gt;
#nullable disable&lt;br /&gt;
using CallFlow;&lt;br /&gt;
using System;&lt;br /&gt;
using System.Threading.Tasks;&lt;br /&gt;
using TCX.Configuration;&lt;br /&gt;
using TCX.PBXAPI;&lt;br /&gt;
using System.Collections.Generic;&lt;br /&gt;
using System.Linq;&lt;br /&gt;
using CallFlow.CFD;&lt;br /&gt;
&lt;br /&gt;
namespace interceptcall&lt;br /&gt;
{&lt;br /&gt;
    public class InterceptInboundCall : ScriptBase&amp;lt;InterceptInboundCall&amp;gt;&lt;br /&gt;
    {&lt;br /&gt;
        // Destination par Défaut, à priori jamais utilisé car ce numéro doit toujours être joignable&lt;br /&gt;
        const string DefaultDestinationDN = &amp;quot;812&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
        // Structure d&#039;une règle de routage&lt;br /&gt;
        class RoutingRule&lt;br /&gt;
        {&lt;br /&gt;
            public Schedule Schedule { get; set; }&lt;br /&gt;
            public string DestinationDN { get; set; }&lt;br /&gt;
            public string[] DIDs { get; set; }&lt;br /&gt;
            public string[] Callers { get; set; }&lt;br /&gt;
&lt;br /&gt;
            public RoutingRule(Schedule schedule, string destinationDN, string[] dids, string[] callers)&lt;br /&gt;
            {&lt;br /&gt;
                Schedule = schedule;&lt;br /&gt;
                DestinationDN = destinationDN;&lt;br /&gt;
                DIDs = dids;&lt;br /&gt;
                Callers = callers;&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
		// Règle(s) de routage &amp;quot;First Match&amp;quot; : La première règle satisfaite est éxécutée, les suivantes sont ignorées&lt;br /&gt;
&lt;br /&gt;
       static readonly List&amp;lt;RoutingRule&amp;gt; routingRules = new List&amp;lt;RoutingRule&amp;gt;&lt;br /&gt;
        {&lt;br /&gt;
            // Règle 1 - Mairie ouverte - routage vers le 801 qui route vers le 100 ( pas de changements&lt;br /&gt;
            new RoutingRule(&lt;br /&gt;
                new Schedule(RuleHoursType.SpecificHours)&lt;br /&gt;
                {&lt;br /&gt;
					{ DayOfWeek.Monday,    new Schedule.PeriodOfDay(new TimeSpan(14,00,0), new TimeSpan(17,00,0)) },&lt;br /&gt;
					{ DayOfWeek.Tuesday,    new Schedule.PeriodOfDay(new TimeSpan(14,00,0), new TimeSpan(17,00,0)) },&lt;br /&gt;
					{ DayOfWeek.Wednesday,    new Schedule.PeriodOfDay(new TimeSpan(09,00,0), new TimeSpan(12,00,0)) },&lt;br /&gt;
                    { DayOfWeek.Thursday,    new Schedule.PeriodOfDay(new TimeSpan(09,00,0), new TimeSpan(12,00,0)) },&lt;br /&gt;
					{ DayOfWeek.Friday,    new Schedule.PeriodOfDay(new TimeSpan(09,00,0), new TimeSpan(12,00,0)) }&lt;br /&gt;
                },&lt;br /&gt;
                &amp;quot;801&amp;quot;,&lt;br /&gt;
                new[] { &amp;quot;*&amp;quot; },   // Tous les DIDs&lt;br /&gt;
                new[] { &amp;quot;*&amp;quot; }    // Tous les callers&lt;br /&gt;
            ),&lt;br /&gt;
			&lt;br /&gt;
			 // Règle 2 — Mairie fermée en semaine ( routage vers le 800 )&lt;br /&gt;
            new RoutingRule(&lt;br /&gt;
                new Schedule(RuleHoursType.SpecificHours)&lt;br /&gt;
                {&lt;br /&gt;
					{ DayOfWeek.Monday,    new Schedule.PeriodOfDay(new TimeSpan(8,00,0), new TimeSpan(14,00,0)) },&lt;br /&gt;
     				{ DayOfWeek.Monday,    new Schedule.PeriodOfDay(new TimeSpan(17,00,0), new TimeSpan(24,00,0)) },&lt;br /&gt;
					{ DayOfWeek.Tuesday,    new Schedule.PeriodOfDay(new TimeSpan(0,00,0), new TimeSpan(14,00,0)) },&lt;br /&gt;
					{ DayOfWeek.Tuesday,    new Schedule.PeriodOfDay(new TimeSpan(17,00,0), new TimeSpan(24,00,0)) },&lt;br /&gt;
					{ DayOfWeek.Wednesday,    new Schedule.PeriodOfDay(new TimeSpan(0,00,0), new TimeSpan(09,00,0)) },&lt;br /&gt;
					{ DayOfWeek.Wednesday,    new Schedule.PeriodOfDay(new TimeSpan(12,00,0), new TimeSpan(24,00,0)) },&lt;br /&gt;
      				{ DayOfWeek.Thursday,    new Schedule.PeriodOfDay(new TimeSpan(0,00,0), new TimeSpan(09,00,0)) },&lt;br /&gt;
					{ DayOfWeek.Thursday,    new Schedule.PeriodOfDay(new TimeSpan(12,00,0), new TimeSpan(24,00,0)) },&lt;br /&gt;
      				{ DayOfWeek.Friday,    new Schedule.PeriodOfDay(new TimeSpan(0,00,0), new TimeSpan(09,00,0)) },&lt;br /&gt;
					{ DayOfWeek.Friday,    new Schedule.PeriodOfDay(new TimeSpan(12,00,0), new TimeSpan(24,00,0)) }&lt;br /&gt;
                },&lt;br /&gt;
                &amp;quot;800&amp;quot;,&lt;br /&gt;
                new[] { &amp;quot;*&amp;quot; },&lt;br /&gt;
                new[] { &amp;quot;*&amp;quot; }&lt;br /&gt;
            ),&lt;br /&gt;
			&lt;br /&gt;
			 // Règle 3 — Mairie fermée le week-end ( vendredi 16h30 au lundi ? )&lt;br /&gt;
            new RoutingRule(&lt;br /&gt;
                new Schedule(RuleHoursType.SpecificHours)&lt;br /&gt;
                {&lt;br /&gt;
					&lt;br /&gt;
					{ DayOfWeek.Friday,    new Schedule.PeriodOfDay(new TimeSpan(16,30,0), new TimeSpan(24,00,0)) },&lt;br /&gt;
					{ DayOfWeek.Saturday, new Schedule.PeriodOfDay(new TimeSpan(0,00,0), new TimeSpan(24,00,0)) },&lt;br /&gt;
					{ DayOfWeek.Sunday, new Schedule.PeriodOfDay(new TimeSpan(0,00,0), new TimeSpan(24,00,0)) }&lt;br /&gt;
      				{ DayOfWeek.Monday, new Schedule.PeriodOfDay(new TimeSpan(0,00,0), new TimeSpan(08,00,0)) }&lt;br /&gt;
                },&lt;br /&gt;
                &amp;quot;804&amp;quot;,&lt;br /&gt;
                new[] { &amp;quot;*&amp;quot; },&lt;br /&gt;
                new[] { &amp;quot;*&amp;quot; }&lt;br /&gt;
            ),&lt;br /&gt;
			&lt;br /&gt;
        };&lt;br /&gt;
&lt;br /&gt;
        // Appel de la fonction principale&lt;br /&gt;
&lt;br /&gt;
        public override async void Start()&lt;br /&gt;
        {&lt;br /&gt;
            try&lt;br /&gt;
            {&lt;br /&gt;
                await Task.Run(async () =&amp;gt;&lt;br /&gt;
                {&lt;br /&gt;
                    bool intercepted = false;&lt;br /&gt;
                    var ps = MyCall.PS as PhoneSystem;&lt;br /&gt;
&lt;br /&gt;
                    if (!(MyCall.Caller.DN is ExternalLine externalLine))&lt;br /&gt;
                    {&lt;br /&gt;
                        MyCall.Return(false);&lt;br /&gt;
                        return;&lt;br /&gt;
                    }&lt;br /&gt;
&lt;br /&gt;
                    var DIDNumber = MyCall.Caller[&amp;quot;inbound_did&amp;quot;] ?? &amp;quot;&amp;quot;;&lt;br /&gt;
                    var CallerID = MyCall.Caller.CallerID ?? &amp;quot;&amp;quot;;&lt;br /&gt;
                    var currentTime = externalLine.Now(out var utc, out var timezone, out var groupmode);&lt;br /&gt;
&lt;br /&gt;
                    MyCall.Info($&amp;quot;Incoming call | Caller: {CallerID} | DID: {DIDNumber} | Time: {currentTime}&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
                    foreach (var rule in routingRules)&lt;br /&gt;
                    {&lt;br /&gt;
                        if (!rule.Schedule.IsActiveTime(currentTime))&lt;br /&gt;
                            continue;&lt;br /&gt;
&lt;br /&gt;
                        bool didMatch = rule.DIDs.Contains(&amp;quot;*&amp;quot;) || rule.DIDs.Contains(DIDNumber);&lt;br /&gt;
                        bool callerMatch = rule.Callers.Contains(&amp;quot;*&amp;quot;) || rule.Callers.Contains(CallerID);&lt;br /&gt;
&lt;br /&gt;
                        if (!didMatch || !callerMatch)&lt;br /&gt;
                            continue;&lt;br /&gt;
&lt;br /&gt;
                        var destinationDN = ps.GetDNByNumber(rule.DestinationDN);&lt;br /&gt;
&lt;br /&gt;
                        if (destinationDN == null)&lt;br /&gt;
                        {&lt;br /&gt;
                            MyCall.Error($&amp;quot;Destination {rule.DestinationDN} not found.&amp;quot;);&lt;br /&gt;
                            continue;&lt;br /&gt;
                        }&lt;br /&gt;
&lt;br /&gt;
                        try&lt;br /&gt;
                        {&lt;br /&gt;
                            var result = await MyCall.RouteToAsync(new DestinationStruct(destinationDN));&lt;br /&gt;
                            MyCall.Info($&amp;quot;Routed to {rule.DestinationDN} | Result: {result}&amp;quot;);&lt;br /&gt;
                            intercepted = true;&lt;br /&gt;
                            break; // Stop at first matching rule&lt;br /&gt;
                        }&lt;br /&gt;
                        catch (Exception ex)&lt;br /&gt;
                        {&lt;br /&gt;
                            MyCall.Error($&amp;quot;Routing failed to {rule.DestinationDN}: {ex}&amp;quot;);&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
&lt;br /&gt;
                &lt;br /&gt;
                    // Utilisation de la route par défaut&lt;br /&gt;
                    &lt;br /&gt;
                    if (!intercepted)&lt;br /&gt;
                    {&lt;br /&gt;
                        var fallbackDN = ps.GetDNByNumber(DefaultDestinationDN);&lt;br /&gt;
                        if (fallbackDN != null)&lt;br /&gt;
                        {&lt;br /&gt;
                            try&lt;br /&gt;
                            {&lt;br /&gt;
                                var result = await MyCall.RouteToAsync(new DestinationStruct(fallbackDN));&lt;br /&gt;
                                MyCall.Info($&amp;quot;Fallback routing to {DefaultDestinationDN} | Result: {result}&amp;quot;);&lt;br /&gt;
                                intercepted = true;&lt;br /&gt;
                            }&lt;br /&gt;
                            catch (Exception ex)&lt;br /&gt;
                            {&lt;br /&gt;
                                MyCall.Error($&amp;quot;Fallback routing failed: {ex}&amp;quot;);&lt;br /&gt;
                            }&lt;br /&gt;
                        }&lt;br /&gt;
                        else&lt;br /&gt;
                        {&lt;br /&gt;
                            MyCall.Error($&amp;quot;Fallback DN {DefaultDestinationDN} not found.&amp;quot;);&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
&lt;br /&gt;
                    MyCall.Return(intercepted);&lt;br /&gt;
                });&lt;br /&gt;
            }&lt;br /&gt;
            catch (Exception ex)&lt;br /&gt;
            {&lt;br /&gt;
                MyCall.Error($&amp;quot;Script execution failed: {ex}&amp;quot;);&lt;br /&gt;
                MyCall.Return(false);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Mise en place du script===&lt;br /&gt;
&lt;br /&gt;
Connecté en admin dans 3CX :&lt;br /&gt;
 &lt;br /&gt;
 Admin / Intégrations / Scripts d&#039;appels / + Ajouter personnalisé&lt;br /&gt;
&lt;br /&gt;
# Nommer le script&lt;br /&gt;
#Choisir &#039;&#039;&#039;Quand cette SDA est composée&#039;&#039;&#039;&lt;br /&gt;
#Choisir la SDA appelée qui va déclencher le script&lt;br /&gt;
#Choisir le scope d&#039;action du script&lt;br /&gt;
#Cliquer sur OK&lt;br /&gt;
#Coller le script préparé dans la zone script&lt;br /&gt;
#Sauvegarder&lt;br /&gt;
[[Fichier:2026-05-27 15h34 23.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 &lt;br /&gt;
&lt;br /&gt;
[[Catégorie:3CX]]&lt;/div&gt;</summary>
		<author><name>Anthony</name></author>
	</entry>
	<entry>
		<id>https://indywiki.fr/index.php?title=Script_de_routage_des_appels&amp;diff=22273</id>
		<title>Script de routage des appels</title>
		<link rel="alternate" type="text/html" href="https://indywiki.fr/index.php?title=Script_de_routage_des_appels&amp;diff=22273"/>
		<updated>2026-05-27T13:36:51Z</updated>

		<summary type="html">&lt;p&gt;Anthony : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Permet en fonction du moment de la semaine de router les appels vers telle ou telle destination.&lt;br /&gt;
&#039;&#039;&#039;Nécessite de supprimer les horaires de fermeture&#039;&#039;&#039; sur le département / instance 3CX ( c&#039;est le script qui gère )&lt;br /&gt;
&lt;br /&gt;
===Le script===&lt;br /&gt;
&lt;br /&gt;
Seul les lignes en jaune requiert d&#039;être éditer. Si plus de règles sont à prévoir, dupliquer les sections.&lt;br /&gt;
&lt;br /&gt;
* Ligne 16 : si aucune règle dans le script ne permet de déterminer un chemin, alors c&#039;est cette extension la cible&lt;br /&gt;
* Ligne 44 : Pour chaque règle, il faut définir les jours et horaires. sur cet exemple, le lundi de 14 à 17h, c&#039;est la règle 1 qui s&#039;applique.&lt;br /&gt;
* Ligne 50 : C&#039;est l&#039;extension qui va être visée par la règle, peut être un utilisateur, un SVI, un groupe , une file d&#039;attente.&lt;br /&gt;
* Ligne 51 : DID : ce filtre permet de tester le &#039;&#039;&#039;numéro appelé&#039;&#039;&#039; ( SDA  actif sur le système). En pratique on ne s&#039;en sert pas ici car le filtre se fait en amont de l&#039;appel du script. Mais possible. La syntaxe &#039;&#039;&#039;*&#039;&#039;&#039; permet de tout laisser passer&lt;br /&gt;
* Ligne 52 : Callers, on peut filtrer sur le &#039;&#039;&#039;numéros de l&#039;appelant&#039;&#039;&#039;. La syntaxe &#039;&#039;&#039;*&#039;&#039;&#039; permet de tout laisser passer&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;csharp&amp;quot; line highlight=&amp;quot;16,44,50-52&amp;quot;&amp;gt;&lt;br /&gt;
#nullable disable&lt;br /&gt;
using CallFlow;&lt;br /&gt;
using System;&lt;br /&gt;
using System.Threading.Tasks;&lt;br /&gt;
using TCX.Configuration;&lt;br /&gt;
using TCX.PBXAPI;&lt;br /&gt;
using System.Collections.Generic;&lt;br /&gt;
using System.Linq;&lt;br /&gt;
using CallFlow.CFD;&lt;br /&gt;
&lt;br /&gt;
namespace interceptcall&lt;br /&gt;
{&lt;br /&gt;
    public class InterceptInboundCall : ScriptBase&amp;lt;InterceptInboundCall&amp;gt;&lt;br /&gt;
    {&lt;br /&gt;
        // Destination par Défaut, à priori jamais utilisé car ce numéro doit toujours être joignable&lt;br /&gt;
        const string DefaultDestinationDN = &amp;quot;812&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
        // Structure d&#039;une règle de routage&lt;br /&gt;
        class RoutingRule&lt;br /&gt;
        {&lt;br /&gt;
            public Schedule Schedule { get; set; }&lt;br /&gt;
            public string DestinationDN { get; set; }&lt;br /&gt;
            public string[] DIDs { get; set; }&lt;br /&gt;
            public string[] Callers { get; set; }&lt;br /&gt;
&lt;br /&gt;
            public RoutingRule(Schedule schedule, string destinationDN, string[] dids, string[] callers)&lt;br /&gt;
            {&lt;br /&gt;
                Schedule = schedule;&lt;br /&gt;
                DestinationDN = destinationDN;&lt;br /&gt;
                DIDs = dids;&lt;br /&gt;
                Callers = callers;&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
		// Règle(s) de routage &amp;quot;First Match&amp;quot; : La première règle satisfaite est éxécutée, les suivantes sont ignorées&lt;br /&gt;
&lt;br /&gt;
       static readonly List&amp;lt;RoutingRule&amp;gt; routingRules = new List&amp;lt;RoutingRule&amp;gt;&lt;br /&gt;
        {&lt;br /&gt;
            // Règle 1 - Mairie ouverte - routage vers le 801 qui route vers le 100 ( pas de changements&lt;br /&gt;
            new RoutingRule(&lt;br /&gt;
                new Schedule(RuleHoursType.SpecificHours)&lt;br /&gt;
                {&lt;br /&gt;
					{ DayOfWeek.Monday,    new Schedule.PeriodOfDay(new TimeSpan(14,00,0), new TimeSpan(17,00,0)) },&lt;br /&gt;
					{ DayOfWeek.Tuesday,    new Schedule.PeriodOfDay(new TimeSpan(14,00,0), new TimeSpan(17,00,0)) },&lt;br /&gt;
					{ DayOfWeek.Wednesday,    new Schedule.PeriodOfDay(new TimeSpan(09,00,0), new TimeSpan(12,00,0)) },&lt;br /&gt;
                    { DayOfWeek.Thursday,    new Schedule.PeriodOfDay(new TimeSpan(09,00,0), new TimeSpan(12,00,0)) },&lt;br /&gt;
					{ DayOfWeek.Friday,    new Schedule.PeriodOfDay(new TimeSpan(09,00,0), new TimeSpan(12,00,0)) }&lt;br /&gt;
                },&lt;br /&gt;
                &amp;quot;801&amp;quot;,&lt;br /&gt;
                new[] { &amp;quot;*&amp;quot; },   // Tous les DIDs&lt;br /&gt;
                new[] { &amp;quot;*&amp;quot; }    // Tous les callers&lt;br /&gt;
            ),&lt;br /&gt;
			&lt;br /&gt;
			 // Règle 2 — Mairie fermée en semaine ( routage vers le 800 )&lt;br /&gt;
            new RoutingRule(&lt;br /&gt;
                new Schedule(RuleHoursType.SpecificHours)&lt;br /&gt;
                {&lt;br /&gt;
					{ DayOfWeek.Monday,    new Schedule.PeriodOfDay(new TimeSpan(8,00,0), new TimeSpan(14,00,0)) },&lt;br /&gt;
     				{ DayOfWeek.Monday,    new Schedule.PeriodOfDay(new TimeSpan(17,00,0), new TimeSpan(24,00,0)) },&lt;br /&gt;
					{ DayOfWeek.Tuesday,    new Schedule.PeriodOfDay(new TimeSpan(0,00,0), new TimeSpan(14,00,0)) },&lt;br /&gt;
					{ DayOfWeek.Tuesday,    new Schedule.PeriodOfDay(new TimeSpan(17,00,0), new TimeSpan(24,00,0)) },&lt;br /&gt;
					{ DayOfWeek.Wednesday,    new Schedule.PeriodOfDay(new TimeSpan(0,00,0), new TimeSpan(09,00,0)) },&lt;br /&gt;
					{ DayOfWeek.Wednesday,    new Schedule.PeriodOfDay(new TimeSpan(12,00,0), new TimeSpan(24,00,0)) },&lt;br /&gt;
      				{ DayOfWeek.Thursday,    new Schedule.PeriodOfDay(new TimeSpan(0,00,0), new TimeSpan(09,00,0)) },&lt;br /&gt;
					{ DayOfWeek.Thursday,    new Schedule.PeriodOfDay(new TimeSpan(12,00,0), new TimeSpan(24,00,0)) },&lt;br /&gt;
      				{ DayOfWeek.Friday,    new Schedule.PeriodOfDay(new TimeSpan(0,00,0), new TimeSpan(09,00,0)) },&lt;br /&gt;
					{ DayOfWeek.Friday,    new Schedule.PeriodOfDay(new TimeSpan(12,00,0), new TimeSpan(24,00,0)) }&lt;br /&gt;
                },&lt;br /&gt;
                &amp;quot;800&amp;quot;,&lt;br /&gt;
                new[] { &amp;quot;*&amp;quot; },&lt;br /&gt;
                new[] { &amp;quot;*&amp;quot; }&lt;br /&gt;
            ),&lt;br /&gt;
			&lt;br /&gt;
			 // Règle 3 — Mairie fermée le week-end ( vendredi 16h30 au lundi ? )&lt;br /&gt;
            new RoutingRule(&lt;br /&gt;
                new Schedule(RuleHoursType.SpecificHours)&lt;br /&gt;
                {&lt;br /&gt;
					&lt;br /&gt;
					{ DayOfWeek.Friday,    new Schedule.PeriodOfDay(new TimeSpan(16,30,0), new TimeSpan(24,00,0)) },&lt;br /&gt;
					{ DayOfWeek.Saturday, new Schedule.PeriodOfDay(new TimeSpan(0,00,0), new TimeSpan(24,00,0)) },&lt;br /&gt;
					{ DayOfWeek.Sunday, new Schedule.PeriodOfDay(new TimeSpan(0,00,0), new TimeSpan(24,00,0)) }&lt;br /&gt;
      				{ DayOfWeek.Monday, new Schedule.PeriodOfDay(new TimeSpan(0,00,0), new TimeSpan(08,00,0)) }&lt;br /&gt;
                },&lt;br /&gt;
                &amp;quot;804&amp;quot;,&lt;br /&gt;
                new[] { &amp;quot;*&amp;quot; },&lt;br /&gt;
                new[] { &amp;quot;*&amp;quot; }&lt;br /&gt;
            ),&lt;br /&gt;
			&lt;br /&gt;
        };&lt;br /&gt;
&lt;br /&gt;
        // Appel de la fonction principale&lt;br /&gt;
&lt;br /&gt;
        public override async void Start()&lt;br /&gt;
        {&lt;br /&gt;
            try&lt;br /&gt;
            {&lt;br /&gt;
                await Task.Run(async () =&amp;gt;&lt;br /&gt;
                {&lt;br /&gt;
                    bool intercepted = false;&lt;br /&gt;
                    var ps = MyCall.PS as PhoneSystem;&lt;br /&gt;
&lt;br /&gt;
                    if (!(MyCall.Caller.DN is ExternalLine externalLine))&lt;br /&gt;
                    {&lt;br /&gt;
                        MyCall.Return(false);&lt;br /&gt;
                        return;&lt;br /&gt;
                    }&lt;br /&gt;
&lt;br /&gt;
                    var DIDNumber = MyCall.Caller[&amp;quot;inbound_did&amp;quot;] ?? &amp;quot;&amp;quot;;&lt;br /&gt;
                    var CallerID = MyCall.Caller.CallerID ?? &amp;quot;&amp;quot;;&lt;br /&gt;
                    var currentTime = externalLine.Now(out var utc, out var timezone, out var groupmode);&lt;br /&gt;
&lt;br /&gt;
                    MyCall.Info($&amp;quot;Incoming call | Caller: {CallerID} | DID: {DIDNumber} | Time: {currentTime}&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
                    foreach (var rule in routingRules)&lt;br /&gt;
                    {&lt;br /&gt;
                        if (!rule.Schedule.IsActiveTime(currentTime))&lt;br /&gt;
                            continue;&lt;br /&gt;
&lt;br /&gt;
                        bool didMatch = rule.DIDs.Contains(&amp;quot;*&amp;quot;) || rule.DIDs.Contains(DIDNumber);&lt;br /&gt;
                        bool callerMatch = rule.Callers.Contains(&amp;quot;*&amp;quot;) || rule.Callers.Contains(CallerID);&lt;br /&gt;
&lt;br /&gt;
                        if (!didMatch || !callerMatch)&lt;br /&gt;
                            continue;&lt;br /&gt;
&lt;br /&gt;
                        var destinationDN = ps.GetDNByNumber(rule.DestinationDN);&lt;br /&gt;
&lt;br /&gt;
                        if (destinationDN == null)&lt;br /&gt;
                        {&lt;br /&gt;
                            MyCall.Error($&amp;quot;Destination {rule.DestinationDN} not found.&amp;quot;);&lt;br /&gt;
                            continue;&lt;br /&gt;
                        }&lt;br /&gt;
&lt;br /&gt;
                        try&lt;br /&gt;
                        {&lt;br /&gt;
                            var result = await MyCall.RouteToAsync(new DestinationStruct(destinationDN));&lt;br /&gt;
                            MyCall.Info($&amp;quot;Routed to {rule.DestinationDN} | Result: {result}&amp;quot;);&lt;br /&gt;
                            intercepted = true;&lt;br /&gt;
                            break; // Stop at first matching rule&lt;br /&gt;
                        }&lt;br /&gt;
                        catch (Exception ex)&lt;br /&gt;
                        {&lt;br /&gt;
                            MyCall.Error($&amp;quot;Routing failed to {rule.DestinationDN}: {ex}&amp;quot;);&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
&lt;br /&gt;
                &lt;br /&gt;
                    // Utilisation de la route par défaut&lt;br /&gt;
                    &lt;br /&gt;
                    if (!intercepted)&lt;br /&gt;
                    {&lt;br /&gt;
                        var fallbackDN = ps.GetDNByNumber(DefaultDestinationDN);&lt;br /&gt;
                        if (fallbackDN != null)&lt;br /&gt;
                        {&lt;br /&gt;
                            try&lt;br /&gt;
                            {&lt;br /&gt;
                                var result = await MyCall.RouteToAsync(new DestinationStruct(fallbackDN));&lt;br /&gt;
                                MyCall.Info($&amp;quot;Fallback routing to {DefaultDestinationDN} | Result: {result}&amp;quot;);&lt;br /&gt;
                                intercepted = true;&lt;br /&gt;
                            }&lt;br /&gt;
                            catch (Exception ex)&lt;br /&gt;
                            {&lt;br /&gt;
                                MyCall.Error($&amp;quot;Fallback routing failed: {ex}&amp;quot;);&lt;br /&gt;
                            }&lt;br /&gt;
                        }&lt;br /&gt;
                        else&lt;br /&gt;
                        {&lt;br /&gt;
                            MyCall.Error($&amp;quot;Fallback DN {DefaultDestinationDN} not found.&amp;quot;);&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
&lt;br /&gt;
                    MyCall.Return(intercepted);&lt;br /&gt;
                });&lt;br /&gt;
            }&lt;br /&gt;
            catch (Exception ex)&lt;br /&gt;
            {&lt;br /&gt;
                MyCall.Error($&amp;quot;Script execution failed: {ex}&amp;quot;);&lt;br /&gt;
                MyCall.Return(false);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Mise en place du script===&lt;br /&gt;
&lt;br /&gt;
Connecté en admin dans 3CX :&lt;br /&gt;
 &lt;br /&gt;
 Admin / Intégrations / Scripts d&#039;appels / + Ajouter personnalisé&lt;br /&gt;
&lt;br /&gt;
# Nommer le script&lt;br /&gt;
#Choisir &#039;&#039;&#039;Quand cette SDA est composée&#039;&#039;&#039;&lt;br /&gt;
#Choisir la SDA appelée qui va déclencher le script&lt;br /&gt;
#Choisir le scope d&#039;action du script&lt;br /&gt;
&lt;br /&gt;
[[Fichier:2026-05-27 15h34 23.png|vignette]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 &lt;br /&gt;
&lt;br /&gt;
[[Catégorie:3CX]]&lt;/div&gt;</summary>
		<author><name>Anthony</name></author>
	</entry>
	<entry>
		<id>https://indywiki.fr/index.php?title=Fichier:2026-05-27_15h34_23.png&amp;diff=22272</id>
		<title>Fichier:2026-05-27 15h34 23.png</title>
		<link rel="alternate" type="text/html" href="https://indywiki.fr/index.php?title=Fichier:2026-05-27_15h34_23.png&amp;diff=22272"/>
		<updated>2026-05-27T13:35:15Z</updated>

		<summary type="html">&lt;p&gt;Anthony : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;MEP script routage 3CX&lt;/div&gt;</summary>
		<author><name>Anthony</name></author>
	</entry>
	<entry>
		<id>https://indywiki.fr/index.php?title=Script_de_routage_des_appels&amp;diff=22271</id>
		<title>Script de routage des appels</title>
		<link rel="alternate" type="text/html" href="https://indywiki.fr/index.php?title=Script_de_routage_des_appels&amp;diff=22271"/>
		<updated>2026-05-27T13:30:43Z</updated>

		<summary type="html">&lt;p&gt;Anthony : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Permet en fonction du moment de la semaine de router les appels vers telle ou telle destination.&lt;br /&gt;
&#039;&#039;&#039;Nécessite de supprimer les horaires de fermeture&#039;&#039;&#039; sur le département / instance 3CX ( c&#039;est le script qui gère )&lt;br /&gt;
&lt;br /&gt;
===Le script===&lt;br /&gt;
&lt;br /&gt;
Seul les lignes en jaune requiert d&#039;être éditer. Si plus de règles sont à prévoir, dupliquer les sections.&lt;br /&gt;
&lt;br /&gt;
* Ligne 16 : si aucune règle dans le script ne permet de déterminer un chemin, alors c&#039;est cette extension la cible&lt;br /&gt;
* Ligne 44 : Pour chaque règle, il faut définir les jours et horaires. sur cet exemple, le lundi de 14 à 17h, c&#039;est la règle 1 qui s&#039;applique.&lt;br /&gt;
* Ligne 50 : C&#039;est l&#039;extension qui va être visée par la règle, peut être un utilisateur, un SVI, un groupe , une file d&#039;attente.&lt;br /&gt;
* Ligne 51 : DID : ce filtre permet de tester le &#039;&#039;&#039;numéro appelé&#039;&#039;&#039; ( SDA  actif sur le système). En pratique on ne s&#039;en sert pas ici car le filtre se fait en amont de l&#039;appel du script. Mais possible. La syntaxe &#039;&#039;&#039;*&#039;&#039;&#039; permet de tout laisser passer&lt;br /&gt;
* Ligne 52 : Callers, on peut filtrer sur le &#039;&#039;&#039;numéros de l&#039;appelant&#039;&#039;&#039;. La syntaxe &#039;&#039;&#039;*&#039;&#039;&#039; permet de tout laisser passer&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;csharp&amp;quot; line highlight=&amp;quot;16,44,50-52&amp;quot;&amp;gt;&lt;br /&gt;
#nullable disable&lt;br /&gt;
using CallFlow;&lt;br /&gt;
using System;&lt;br /&gt;
using System.Threading.Tasks;&lt;br /&gt;
using TCX.Configuration;&lt;br /&gt;
using TCX.PBXAPI;&lt;br /&gt;
using System.Collections.Generic;&lt;br /&gt;
using System.Linq;&lt;br /&gt;
using CallFlow.CFD;&lt;br /&gt;
&lt;br /&gt;
namespace interceptcall&lt;br /&gt;
{&lt;br /&gt;
    public class InterceptInboundCall : ScriptBase&amp;lt;InterceptInboundCall&amp;gt;&lt;br /&gt;
    {&lt;br /&gt;
        // Destination par Défaut, à priori jamais utilisé car ce numéro doit toujours être joignable&lt;br /&gt;
        const string DefaultDestinationDN = &amp;quot;812&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
        // Structure d&#039;une règle de routage&lt;br /&gt;
        class RoutingRule&lt;br /&gt;
        {&lt;br /&gt;
            public Schedule Schedule { get; set; }&lt;br /&gt;
            public string DestinationDN { get; set; }&lt;br /&gt;
            public string[] DIDs { get; set; }&lt;br /&gt;
            public string[] Callers { get; set; }&lt;br /&gt;
&lt;br /&gt;
            public RoutingRule(Schedule schedule, string destinationDN, string[] dids, string[] callers)&lt;br /&gt;
            {&lt;br /&gt;
                Schedule = schedule;&lt;br /&gt;
                DestinationDN = destinationDN;&lt;br /&gt;
                DIDs = dids;&lt;br /&gt;
                Callers = callers;&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
		// Règle(s) de routage &amp;quot;First Match&amp;quot; : La première règle satisfaite est éxécutée, les suivantes sont ignorées&lt;br /&gt;
&lt;br /&gt;
       static readonly List&amp;lt;RoutingRule&amp;gt; routingRules = new List&amp;lt;RoutingRule&amp;gt;&lt;br /&gt;
        {&lt;br /&gt;
            // Règle 1 - Mairie ouverte - routage vers le 801 qui route vers le 100 ( pas de changements&lt;br /&gt;
            new RoutingRule(&lt;br /&gt;
                new Schedule(RuleHoursType.SpecificHours)&lt;br /&gt;
                {&lt;br /&gt;
					{ DayOfWeek.Monday,    new Schedule.PeriodOfDay(new TimeSpan(14,00,0), new TimeSpan(17,00,0)) },&lt;br /&gt;
					{ DayOfWeek.Tuesday,    new Schedule.PeriodOfDay(new TimeSpan(14,00,0), new TimeSpan(17,00,0)) },&lt;br /&gt;
					{ DayOfWeek.Wednesday,    new Schedule.PeriodOfDay(new TimeSpan(09,00,0), new TimeSpan(12,00,0)) },&lt;br /&gt;
                    { DayOfWeek.Thursday,    new Schedule.PeriodOfDay(new TimeSpan(09,00,0), new TimeSpan(12,00,0)) },&lt;br /&gt;
					{ DayOfWeek.Friday,    new Schedule.PeriodOfDay(new TimeSpan(09,00,0), new TimeSpan(12,00,0)) }&lt;br /&gt;
                },&lt;br /&gt;
                &amp;quot;801&amp;quot;,&lt;br /&gt;
                new[] { &amp;quot;*&amp;quot; },   // Tous les DIDs&lt;br /&gt;
                new[] { &amp;quot;*&amp;quot; }    // Tous les callers&lt;br /&gt;
            ),&lt;br /&gt;
			&lt;br /&gt;
			 // Règle 2 — Mairie fermée en semaine ( routage vers le 800 )&lt;br /&gt;
            new RoutingRule(&lt;br /&gt;
                new Schedule(RuleHoursType.SpecificHours)&lt;br /&gt;
                {&lt;br /&gt;
					{ DayOfWeek.Monday,    new Schedule.PeriodOfDay(new TimeSpan(8,00,0), new TimeSpan(14,00,0)) },&lt;br /&gt;
     				{ DayOfWeek.Monday,    new Schedule.PeriodOfDay(new TimeSpan(17,00,0), new TimeSpan(24,00,0)) },&lt;br /&gt;
					{ DayOfWeek.Tuesday,    new Schedule.PeriodOfDay(new TimeSpan(0,00,0), new TimeSpan(14,00,0)) },&lt;br /&gt;
					{ DayOfWeek.Tuesday,    new Schedule.PeriodOfDay(new TimeSpan(17,00,0), new TimeSpan(24,00,0)) },&lt;br /&gt;
					{ DayOfWeek.Wednesday,    new Schedule.PeriodOfDay(new TimeSpan(0,00,0), new TimeSpan(09,00,0)) },&lt;br /&gt;
					{ DayOfWeek.Wednesday,    new Schedule.PeriodOfDay(new TimeSpan(12,00,0), new TimeSpan(24,00,0)) },&lt;br /&gt;
      				{ DayOfWeek.Thursday,    new Schedule.PeriodOfDay(new TimeSpan(0,00,0), new TimeSpan(09,00,0)) },&lt;br /&gt;
					{ DayOfWeek.Thursday,    new Schedule.PeriodOfDay(new TimeSpan(12,00,0), new TimeSpan(24,00,0)) },&lt;br /&gt;
      				{ DayOfWeek.Friday,    new Schedule.PeriodOfDay(new TimeSpan(0,00,0), new TimeSpan(09,00,0)) },&lt;br /&gt;
					{ DayOfWeek.Friday,    new Schedule.PeriodOfDay(new TimeSpan(12,00,0), new TimeSpan(24,00,0)) }&lt;br /&gt;
                },&lt;br /&gt;
                &amp;quot;800&amp;quot;,&lt;br /&gt;
                new[] { &amp;quot;*&amp;quot; },&lt;br /&gt;
                new[] { &amp;quot;*&amp;quot; }&lt;br /&gt;
            ),&lt;br /&gt;
			&lt;br /&gt;
			 // Règle 3 — Mairie fermée le week-end ( vendredi 16h30 au lundi ? )&lt;br /&gt;
            new RoutingRule(&lt;br /&gt;
                new Schedule(RuleHoursType.SpecificHours)&lt;br /&gt;
                {&lt;br /&gt;
					&lt;br /&gt;
					{ DayOfWeek.Friday,    new Schedule.PeriodOfDay(new TimeSpan(16,30,0), new TimeSpan(24,00,0)) },&lt;br /&gt;
					{ DayOfWeek.Saturday, new Schedule.PeriodOfDay(new TimeSpan(0,00,0), new TimeSpan(24,00,0)) },&lt;br /&gt;
					{ DayOfWeek.Sunday, new Schedule.PeriodOfDay(new TimeSpan(0,00,0), new TimeSpan(24,00,0)) }&lt;br /&gt;
      				{ DayOfWeek.Monday, new Schedule.PeriodOfDay(new TimeSpan(0,00,0), new TimeSpan(08,00,0)) }&lt;br /&gt;
                },&lt;br /&gt;
                &amp;quot;804&amp;quot;,&lt;br /&gt;
                new[] { &amp;quot;*&amp;quot; },&lt;br /&gt;
                new[] { &amp;quot;*&amp;quot; }&lt;br /&gt;
            ),&lt;br /&gt;
			&lt;br /&gt;
        };&lt;br /&gt;
&lt;br /&gt;
        // Appel de la fonction principale&lt;br /&gt;
&lt;br /&gt;
        public override async void Start()&lt;br /&gt;
        {&lt;br /&gt;
            try&lt;br /&gt;
            {&lt;br /&gt;
                await Task.Run(async () =&amp;gt;&lt;br /&gt;
                {&lt;br /&gt;
                    bool intercepted = false;&lt;br /&gt;
                    var ps = MyCall.PS as PhoneSystem;&lt;br /&gt;
&lt;br /&gt;
                    if (!(MyCall.Caller.DN is ExternalLine externalLine))&lt;br /&gt;
                    {&lt;br /&gt;
                        MyCall.Return(false);&lt;br /&gt;
                        return;&lt;br /&gt;
                    }&lt;br /&gt;
&lt;br /&gt;
                    var DIDNumber = MyCall.Caller[&amp;quot;inbound_did&amp;quot;] ?? &amp;quot;&amp;quot;;&lt;br /&gt;
                    var CallerID = MyCall.Caller.CallerID ?? &amp;quot;&amp;quot;;&lt;br /&gt;
                    var currentTime = externalLine.Now(out var utc, out var timezone, out var groupmode);&lt;br /&gt;
&lt;br /&gt;
                    MyCall.Info($&amp;quot;Incoming call | Caller: {CallerID} | DID: {DIDNumber} | Time: {currentTime}&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
                    foreach (var rule in routingRules)&lt;br /&gt;
                    {&lt;br /&gt;
                        if (!rule.Schedule.IsActiveTime(currentTime))&lt;br /&gt;
                            continue;&lt;br /&gt;
&lt;br /&gt;
                        bool didMatch = rule.DIDs.Contains(&amp;quot;*&amp;quot;) || rule.DIDs.Contains(DIDNumber);&lt;br /&gt;
                        bool callerMatch = rule.Callers.Contains(&amp;quot;*&amp;quot;) || rule.Callers.Contains(CallerID);&lt;br /&gt;
&lt;br /&gt;
                        if (!didMatch || !callerMatch)&lt;br /&gt;
                            continue;&lt;br /&gt;
&lt;br /&gt;
                        var destinationDN = ps.GetDNByNumber(rule.DestinationDN);&lt;br /&gt;
&lt;br /&gt;
                        if (destinationDN == null)&lt;br /&gt;
                        {&lt;br /&gt;
                            MyCall.Error($&amp;quot;Destination {rule.DestinationDN} not found.&amp;quot;);&lt;br /&gt;
                            continue;&lt;br /&gt;
                        }&lt;br /&gt;
&lt;br /&gt;
                        try&lt;br /&gt;
                        {&lt;br /&gt;
                            var result = await MyCall.RouteToAsync(new DestinationStruct(destinationDN));&lt;br /&gt;
                            MyCall.Info($&amp;quot;Routed to {rule.DestinationDN} | Result: {result}&amp;quot;);&lt;br /&gt;
                            intercepted = true;&lt;br /&gt;
                            break; // Stop at first matching rule&lt;br /&gt;
                        }&lt;br /&gt;
                        catch (Exception ex)&lt;br /&gt;
                        {&lt;br /&gt;
                            MyCall.Error($&amp;quot;Routing failed to {rule.DestinationDN}: {ex}&amp;quot;);&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
&lt;br /&gt;
                &lt;br /&gt;
                    // Utilisation de la route par défaut&lt;br /&gt;
                    &lt;br /&gt;
                    if (!intercepted)&lt;br /&gt;
                    {&lt;br /&gt;
                        var fallbackDN = ps.GetDNByNumber(DefaultDestinationDN);&lt;br /&gt;
                        if (fallbackDN != null)&lt;br /&gt;
                        {&lt;br /&gt;
                            try&lt;br /&gt;
                            {&lt;br /&gt;
                                var result = await MyCall.RouteToAsync(new DestinationStruct(fallbackDN));&lt;br /&gt;
                                MyCall.Info($&amp;quot;Fallback routing to {DefaultDestinationDN} | Result: {result}&amp;quot;);&lt;br /&gt;
                                intercepted = true;&lt;br /&gt;
                            }&lt;br /&gt;
                            catch (Exception ex)&lt;br /&gt;
                            {&lt;br /&gt;
                                MyCall.Error($&amp;quot;Fallback routing failed: {ex}&amp;quot;);&lt;br /&gt;
                            }&lt;br /&gt;
                        }&lt;br /&gt;
                        else&lt;br /&gt;
                        {&lt;br /&gt;
                            MyCall.Error($&amp;quot;Fallback DN {DefaultDestinationDN} not found.&amp;quot;);&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
&lt;br /&gt;
                    MyCall.Return(intercepted);&lt;br /&gt;
                });&lt;br /&gt;
            }&lt;br /&gt;
            catch (Exception ex)&lt;br /&gt;
            {&lt;br /&gt;
                MyCall.Error($&amp;quot;Script execution failed: {ex}&amp;quot;);&lt;br /&gt;
                MyCall.Return(false);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Catégorie:3CX]]&lt;/div&gt;</summary>
		<author><name>Anthony</name></author>
	</entry>
	<entry>
		<id>https://indywiki.fr/index.php?title=Script_de_routage_des_appels&amp;diff=22270</id>
		<title>Script de routage des appels</title>
		<link rel="alternate" type="text/html" href="https://indywiki.fr/index.php?title=Script_de_routage_des_appels&amp;diff=22270"/>
		<updated>2026-05-27T13:22:50Z</updated>

		<summary type="html">&lt;p&gt;Anthony : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Permet en fonction du moment de la semaine de router les appels vers telle ou telle destination.&lt;br /&gt;
&#039;&#039;&#039;Nécessite de supprimer les horaires de fermeture&#039;&#039;&#039; sur le département / instance 3CX ( c&#039;est le script qui gère )&lt;br /&gt;
&lt;br /&gt;
===Le script===&lt;br /&gt;
&lt;br /&gt;
Seul les lignes en jaune requiert d&#039;être éditer. Si plus de règles sont à prévoir, dupliquer les sections.&lt;br /&gt;
&lt;br /&gt;
* Ligne 16 : si aucune règle dans le script ne permet de déterminer un chemin, alors c&#039;est cette extension la cible&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;csharp&amp;quot; line highlight=&amp;quot;16,44,50-52&amp;quot;&amp;gt;&lt;br /&gt;
#nullable disable&lt;br /&gt;
using CallFlow;&lt;br /&gt;
using System;&lt;br /&gt;
using System.Threading.Tasks;&lt;br /&gt;
using TCX.Configuration;&lt;br /&gt;
using TCX.PBXAPI;&lt;br /&gt;
using System.Collections.Generic;&lt;br /&gt;
using System.Linq;&lt;br /&gt;
using CallFlow.CFD;&lt;br /&gt;
&lt;br /&gt;
namespace interceptcall&lt;br /&gt;
{&lt;br /&gt;
    public class InterceptInboundCall : ScriptBase&amp;lt;InterceptInboundCall&amp;gt;&lt;br /&gt;
    {&lt;br /&gt;
        // Destination par Défaut, à priori jamais utilisé car ce numéro doit toujours être joignable&lt;br /&gt;
        const string DefaultDestinationDN = &amp;quot;812&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
        // Structure d&#039;une règle de routage&lt;br /&gt;
        class RoutingRule&lt;br /&gt;
        {&lt;br /&gt;
            public Schedule Schedule { get; set; }&lt;br /&gt;
            public string DestinationDN { get; set; }&lt;br /&gt;
            public string[] DIDs { get; set; }&lt;br /&gt;
            public string[] Callers { get; set; }&lt;br /&gt;
&lt;br /&gt;
            public RoutingRule(Schedule schedule, string destinationDN, string[] dids, string[] callers)&lt;br /&gt;
            {&lt;br /&gt;
                Schedule = schedule;&lt;br /&gt;
                DestinationDN = destinationDN;&lt;br /&gt;
                DIDs = dids;&lt;br /&gt;
                Callers = callers;&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
		// Règle(s) de routage &amp;quot;First Match&amp;quot; : La première règle satisfaite est éxécutée, les suivantes sont ignorées&lt;br /&gt;
&lt;br /&gt;
       static readonly List&amp;lt;RoutingRule&amp;gt; routingRules = new List&amp;lt;RoutingRule&amp;gt;&lt;br /&gt;
        {&lt;br /&gt;
            // Règle 1 - Mairie ouverte - routage vers le 801 qui route vers le 100 ( pas de changements&lt;br /&gt;
            new RoutingRule(&lt;br /&gt;
                new Schedule(RuleHoursType.SpecificHours)&lt;br /&gt;
                {&lt;br /&gt;
					{ DayOfWeek.Monday,    new Schedule.PeriodOfDay(new TimeSpan(14,00,0), new TimeSpan(17,00,0)) },&lt;br /&gt;
					{ DayOfWeek.Tuesday,    new Schedule.PeriodOfDay(new TimeSpan(14,00,0), new TimeSpan(17,00,0)) },&lt;br /&gt;
					{ DayOfWeek.Wednesday,    new Schedule.PeriodOfDay(new TimeSpan(09,00,0), new TimeSpan(12,00,0)) },&lt;br /&gt;
                    { DayOfWeek.Thursday,    new Schedule.PeriodOfDay(new TimeSpan(09,00,0), new TimeSpan(12,00,0)) },&lt;br /&gt;
					{ DayOfWeek.Friday,    new Schedule.PeriodOfDay(new TimeSpan(09,00,0), new TimeSpan(12,00,0)) }&lt;br /&gt;
                },&lt;br /&gt;
                &amp;quot;801&amp;quot;,&lt;br /&gt;
                new[] { &amp;quot;*&amp;quot; },   // Tous les DIDs&lt;br /&gt;
                new[] { &amp;quot;*&amp;quot; }    // Tous les callers&lt;br /&gt;
            ),&lt;br /&gt;
			&lt;br /&gt;
			 // Règle 2 — Mairie fermée en semaine ( routage vers le 800 )&lt;br /&gt;
            new RoutingRule(&lt;br /&gt;
                new Schedule(RuleHoursType.SpecificHours)&lt;br /&gt;
                {&lt;br /&gt;
					{ DayOfWeek.Monday,    new Schedule.PeriodOfDay(new TimeSpan(8,00,0), new TimeSpan(14,00,0)) },&lt;br /&gt;
     				{ DayOfWeek.Monday,    new Schedule.PeriodOfDay(new TimeSpan(17,00,0), new TimeSpan(24,00,0)) },&lt;br /&gt;
					{ DayOfWeek.Tuesday,    new Schedule.PeriodOfDay(new TimeSpan(0,00,0), new TimeSpan(14,00,0)) },&lt;br /&gt;
					{ DayOfWeek.Tuesday,    new Schedule.PeriodOfDay(new TimeSpan(17,00,0), new TimeSpan(24,00,0)) },&lt;br /&gt;
					{ DayOfWeek.Wednesday,    new Schedule.PeriodOfDay(new TimeSpan(0,00,0), new TimeSpan(09,00,0)) },&lt;br /&gt;
					{ DayOfWeek.Wednesday,    new Schedule.PeriodOfDay(new TimeSpan(12,00,0), new TimeSpan(24,00,0)) },&lt;br /&gt;
      				{ DayOfWeek.Thursday,    new Schedule.PeriodOfDay(new TimeSpan(0,00,0), new TimeSpan(09,00,0)) },&lt;br /&gt;
					{ DayOfWeek.Thursday,    new Schedule.PeriodOfDay(new TimeSpan(12,00,0), new TimeSpan(24,00,0)) },&lt;br /&gt;
      				{ DayOfWeek.Friday,    new Schedule.PeriodOfDay(new TimeSpan(0,00,0), new TimeSpan(09,00,0)) },&lt;br /&gt;
					{ DayOfWeek.Friday,    new Schedule.PeriodOfDay(new TimeSpan(12,00,0), new TimeSpan(24,00,0)) }&lt;br /&gt;
                },&lt;br /&gt;
                &amp;quot;800&amp;quot;,&lt;br /&gt;
                new[] { &amp;quot;*&amp;quot; },&lt;br /&gt;
                new[] { &amp;quot;*&amp;quot; }&lt;br /&gt;
            ),&lt;br /&gt;
			&lt;br /&gt;
			 // Règle 3 — Mairie fermée le week-end ( vendredi 16h30 au lundi ? )&lt;br /&gt;
            new RoutingRule(&lt;br /&gt;
                new Schedule(RuleHoursType.SpecificHours)&lt;br /&gt;
                {&lt;br /&gt;
					&lt;br /&gt;
					{ DayOfWeek.Friday,    new Schedule.PeriodOfDay(new TimeSpan(16,30,0), new TimeSpan(24,00,0)) },&lt;br /&gt;
					{ DayOfWeek.Saturday, new Schedule.PeriodOfDay(new TimeSpan(0,00,0), new TimeSpan(24,00,0)) },&lt;br /&gt;
					{ DayOfWeek.Sunday, new Schedule.PeriodOfDay(new TimeSpan(0,00,0), new TimeSpan(24,00,0)) }&lt;br /&gt;
      				{ DayOfWeek.Monday, new Schedule.PeriodOfDay(new TimeSpan(0,00,0), new TimeSpan(08,00,0)) }&lt;br /&gt;
                },&lt;br /&gt;
                &amp;quot;804&amp;quot;,&lt;br /&gt;
                new[] { &amp;quot;*&amp;quot; },&lt;br /&gt;
                new[] { &amp;quot;*&amp;quot; }&lt;br /&gt;
            ),&lt;br /&gt;
			&lt;br /&gt;
        };&lt;br /&gt;
&lt;br /&gt;
        // Appel de la fonction principale&lt;br /&gt;
&lt;br /&gt;
        public override async void Start()&lt;br /&gt;
        {&lt;br /&gt;
            try&lt;br /&gt;
            {&lt;br /&gt;
                await Task.Run(async () =&amp;gt;&lt;br /&gt;
                {&lt;br /&gt;
                    bool intercepted = false;&lt;br /&gt;
                    var ps = MyCall.PS as PhoneSystem;&lt;br /&gt;
&lt;br /&gt;
                    if (!(MyCall.Caller.DN is ExternalLine externalLine))&lt;br /&gt;
                    {&lt;br /&gt;
                        MyCall.Return(false);&lt;br /&gt;
                        return;&lt;br /&gt;
                    }&lt;br /&gt;
&lt;br /&gt;
                    var DIDNumber = MyCall.Caller[&amp;quot;inbound_did&amp;quot;] ?? &amp;quot;&amp;quot;;&lt;br /&gt;
                    var CallerID = MyCall.Caller.CallerID ?? &amp;quot;&amp;quot;;&lt;br /&gt;
                    var currentTime = externalLine.Now(out var utc, out var timezone, out var groupmode);&lt;br /&gt;
&lt;br /&gt;
                    MyCall.Info($&amp;quot;Incoming call | Caller: {CallerID} | DID: {DIDNumber} | Time: {currentTime}&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
                    foreach (var rule in routingRules)&lt;br /&gt;
                    {&lt;br /&gt;
                        if (!rule.Schedule.IsActiveTime(currentTime))&lt;br /&gt;
                            continue;&lt;br /&gt;
&lt;br /&gt;
                        bool didMatch = rule.DIDs.Contains(&amp;quot;*&amp;quot;) || rule.DIDs.Contains(DIDNumber);&lt;br /&gt;
                        bool callerMatch = rule.Callers.Contains(&amp;quot;*&amp;quot;) || rule.Callers.Contains(CallerID);&lt;br /&gt;
&lt;br /&gt;
                        if (!didMatch || !callerMatch)&lt;br /&gt;
                            continue;&lt;br /&gt;
&lt;br /&gt;
                        var destinationDN = ps.GetDNByNumber(rule.DestinationDN);&lt;br /&gt;
&lt;br /&gt;
                        if (destinationDN == null)&lt;br /&gt;
                        {&lt;br /&gt;
                            MyCall.Error($&amp;quot;Destination {rule.DestinationDN} not found.&amp;quot;);&lt;br /&gt;
                            continue;&lt;br /&gt;
                        }&lt;br /&gt;
&lt;br /&gt;
                        try&lt;br /&gt;
                        {&lt;br /&gt;
                            var result = await MyCall.RouteToAsync(new DestinationStruct(destinationDN));&lt;br /&gt;
                            MyCall.Info($&amp;quot;Routed to {rule.DestinationDN} | Result: {result}&amp;quot;);&lt;br /&gt;
                            intercepted = true;&lt;br /&gt;
                            break; // Stop at first matching rule&lt;br /&gt;
                        }&lt;br /&gt;
                        catch (Exception ex)&lt;br /&gt;
                        {&lt;br /&gt;
                            MyCall.Error($&amp;quot;Routing failed to {rule.DestinationDN}: {ex}&amp;quot;);&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
&lt;br /&gt;
                &lt;br /&gt;
                    // Utilisation de la route par défaut&lt;br /&gt;
                    &lt;br /&gt;
                    if (!intercepted)&lt;br /&gt;
                    {&lt;br /&gt;
                        var fallbackDN = ps.GetDNByNumber(DefaultDestinationDN);&lt;br /&gt;
                        if (fallbackDN != null)&lt;br /&gt;
                        {&lt;br /&gt;
                            try&lt;br /&gt;
                            {&lt;br /&gt;
                                var result = await MyCall.RouteToAsync(new DestinationStruct(fallbackDN));&lt;br /&gt;
                                MyCall.Info($&amp;quot;Fallback routing to {DefaultDestinationDN} | Result: {result}&amp;quot;);&lt;br /&gt;
                                intercepted = true;&lt;br /&gt;
                            }&lt;br /&gt;
                            catch (Exception ex)&lt;br /&gt;
                            {&lt;br /&gt;
                                MyCall.Error($&amp;quot;Fallback routing failed: {ex}&amp;quot;);&lt;br /&gt;
                            }&lt;br /&gt;
                        }&lt;br /&gt;
                        else&lt;br /&gt;
                        {&lt;br /&gt;
                            MyCall.Error($&amp;quot;Fallback DN {DefaultDestinationDN} not found.&amp;quot;);&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
&lt;br /&gt;
                    MyCall.Return(intercepted);&lt;br /&gt;
                });&lt;br /&gt;
            }&lt;br /&gt;
            catch (Exception ex)&lt;br /&gt;
            {&lt;br /&gt;
                MyCall.Error($&amp;quot;Script execution failed: {ex}&amp;quot;);&lt;br /&gt;
                MyCall.Return(false);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Catégorie:3CX]]&lt;/div&gt;</summary>
		<author><name>Anthony</name></author>
	</entry>
	<entry>
		<id>https://indywiki.fr/index.php?title=Script_de_routage_des_appels&amp;diff=22269</id>
		<title>Script de routage des appels</title>
		<link rel="alternate" type="text/html" href="https://indywiki.fr/index.php?title=Script_de_routage_des_appels&amp;diff=22269"/>
		<updated>2026-05-27T13:19:52Z</updated>

		<summary type="html">&lt;p&gt;Anthony : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Permet en fonction du moment de la semaine de router les appels vers telle ou telle destination.&lt;br /&gt;
&#039;&#039;&#039;Nécessite de supprimer les horaires de fermeture&#039;&#039;&#039; sur le département / instance 3CX ( c&#039;est le script qui gère )&lt;br /&gt;
&lt;br /&gt;
===Le script===&lt;br /&gt;
&lt;br /&gt;
* Ligne 16 : si aucune règle dans le script ne permet de déterminer un chemin, alors c&#039;est cette extension la cible&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;csharp&amp;quot; line highlight=&amp;quot;16,37,43,52-54&amp;quot;&amp;gt;&lt;br /&gt;
#nullable disable&lt;br /&gt;
using CallFlow;&lt;br /&gt;
using System;&lt;br /&gt;
using System.Threading.Tasks;&lt;br /&gt;
using TCX.Configuration;&lt;br /&gt;
using TCX.PBXAPI;&lt;br /&gt;
using System.Collections.Generic;&lt;br /&gt;
using System.Linq;&lt;br /&gt;
using CallFlow.CFD;&lt;br /&gt;
&lt;br /&gt;
namespace interceptcall&lt;br /&gt;
{&lt;br /&gt;
    public class InterceptInboundCall : ScriptBase&amp;lt;InterceptInboundCall&amp;gt;&lt;br /&gt;
    {&lt;br /&gt;
        // Destination par Défaut, à priori jamais utilisé car ce numéro doit toujours être joignable&lt;br /&gt;
        const string DefaultDestinationDN = &amp;quot;812&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
        // Structure d&#039;une règle de routage&lt;br /&gt;
        class RoutingRule&lt;br /&gt;
        {&lt;br /&gt;
            public Schedule Schedule { get; set; }&lt;br /&gt;
            public string DestinationDN { get; set; }&lt;br /&gt;
            public string[] DIDs { get; set; }&lt;br /&gt;
            public string[] Callers { get; set; }&lt;br /&gt;
&lt;br /&gt;
            public RoutingRule(Schedule schedule, string destinationDN, string[] dids, string[] callers)&lt;br /&gt;
            {&lt;br /&gt;
                Schedule = schedule;&lt;br /&gt;
                DestinationDN = destinationDN;&lt;br /&gt;
                DIDs = dids;&lt;br /&gt;
                Callers = callers;&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
		// Règle(s) de routage &amp;quot;First Match&amp;quot; : La première règle satisfaite est éxécutée, les suivantes sont ignorées&lt;br /&gt;
&lt;br /&gt;
       static readonly List&amp;lt;RoutingRule&amp;gt; routingRules = new List&amp;lt;RoutingRule&amp;gt;&lt;br /&gt;
        {&lt;br /&gt;
            // Règle 1 - Mairie ouverte - routage vers le 801 qui route vers le 100 ( pas de changements&lt;br /&gt;
            new RoutingRule(&lt;br /&gt;
                new Schedule(RuleHoursType.SpecificHours)&lt;br /&gt;
                {&lt;br /&gt;
					{ DayOfWeek.Monday,    new Schedule.PeriodOfDay(new TimeSpan(14,00,0), new TimeSpan(17,00,0)) },&lt;br /&gt;
					{ DayOfWeek.Tuesday,    new Schedule.PeriodOfDay(new TimeSpan(14,00,0), new TimeSpan(17,00,0)) },&lt;br /&gt;
					{ DayOfWeek.Wednesday,    new Schedule.PeriodOfDay(new TimeSpan(09,00,0), new TimeSpan(12,00,0)) },&lt;br /&gt;
                    { DayOfWeek.Thursday,    new Schedule.PeriodOfDay(new TimeSpan(09,00,0), new TimeSpan(12,00,0)) },&lt;br /&gt;
					{ DayOfWeek.Friday,    new Schedule.PeriodOfDay(new TimeSpan(09,00,0), new TimeSpan(12,00,0)) }&lt;br /&gt;
                },&lt;br /&gt;
                &amp;quot;801&amp;quot;,&lt;br /&gt;
                new[] { &amp;quot;*&amp;quot; },   // Tous les DIDs&lt;br /&gt;
                new[] { &amp;quot;*&amp;quot; }    // Tous les callers&lt;br /&gt;
            ),&lt;br /&gt;
			&lt;br /&gt;
			 // Règle 2 — Mairie fermée en semaine ( routage vers le 800 )&lt;br /&gt;
            new RoutingRule(&lt;br /&gt;
                new Schedule(RuleHoursType.SpecificHours)&lt;br /&gt;
                {&lt;br /&gt;
					{ DayOfWeek.Monday,    new Schedule.PeriodOfDay(new TimeSpan(8,00,0), new TimeSpan(14,00,0)) },&lt;br /&gt;
     				{ DayOfWeek.Monday,    new Schedule.PeriodOfDay(new TimeSpan(17,00,0), new TimeSpan(24,00,0)) },&lt;br /&gt;
					{ DayOfWeek.Tuesday,    new Schedule.PeriodOfDay(new TimeSpan(0,00,0), new TimeSpan(14,00,0)) },&lt;br /&gt;
					{ DayOfWeek.Tuesday,    new Schedule.PeriodOfDay(new TimeSpan(17,00,0), new TimeSpan(24,00,0)) },&lt;br /&gt;
					{ DayOfWeek.Wednesday,    new Schedule.PeriodOfDay(new TimeSpan(0,00,0), new TimeSpan(09,00,0)) },&lt;br /&gt;
					{ DayOfWeek.Wednesday,    new Schedule.PeriodOfDay(new TimeSpan(12,00,0), new TimeSpan(24,00,0)) },&lt;br /&gt;
      				{ DayOfWeek.Thursday,    new Schedule.PeriodOfDay(new TimeSpan(0,00,0), new TimeSpan(09,00,0)) },&lt;br /&gt;
					{ DayOfWeek.Thursday,    new Schedule.PeriodOfDay(new TimeSpan(12,00,0), new TimeSpan(24,00,0)) },&lt;br /&gt;
      				{ DayOfWeek.Friday,    new Schedule.PeriodOfDay(new TimeSpan(0,00,0), new TimeSpan(09,00,0)) },&lt;br /&gt;
					{ DayOfWeek.Friday,    new Schedule.PeriodOfDay(new TimeSpan(12,00,0), new TimeSpan(24,00,0)) }&lt;br /&gt;
                },&lt;br /&gt;
                &amp;quot;800&amp;quot;,&lt;br /&gt;
                new[] { &amp;quot;*&amp;quot; },&lt;br /&gt;
                new[] { &amp;quot;*&amp;quot; }&lt;br /&gt;
            ),&lt;br /&gt;
			&lt;br /&gt;
			 // Règle 3 — Mairie fermée le week-end ( vendredi 16h30 au lundi ? )&lt;br /&gt;
            new RoutingRule(&lt;br /&gt;
                new Schedule(RuleHoursType.SpecificHours)&lt;br /&gt;
                {&lt;br /&gt;
					&lt;br /&gt;
					{ DayOfWeek.Friday,    new Schedule.PeriodOfDay(new TimeSpan(16,30,0), new TimeSpan(24,00,0)) },&lt;br /&gt;
					{ DayOfWeek.Saturday, new Schedule.PeriodOfDay(new TimeSpan(0,00,0), new TimeSpan(24,00,0)) },&lt;br /&gt;
					{ DayOfWeek.Sunday, new Schedule.PeriodOfDay(new TimeSpan(0,00,0), new TimeSpan(24,00,0)) }&lt;br /&gt;
      				{ DayOfWeek.Monday, new Schedule.PeriodOfDay(new TimeSpan(0,00,0), new TimeSpan(08,00,0)) }&lt;br /&gt;
                },&lt;br /&gt;
                &amp;quot;804&amp;quot;,&lt;br /&gt;
                new[] { &amp;quot;*&amp;quot; },&lt;br /&gt;
                new[] { &amp;quot;*&amp;quot; }&lt;br /&gt;
            ),&lt;br /&gt;
			&lt;br /&gt;
        };&lt;br /&gt;
&lt;br /&gt;
        // Appel de la fonction principale&lt;br /&gt;
&lt;br /&gt;
        public override async void Start()&lt;br /&gt;
        {&lt;br /&gt;
            try&lt;br /&gt;
            {&lt;br /&gt;
                await Task.Run(async () =&amp;gt;&lt;br /&gt;
                {&lt;br /&gt;
                    bool intercepted = false;&lt;br /&gt;
                    var ps = MyCall.PS as PhoneSystem;&lt;br /&gt;
&lt;br /&gt;
                    if (!(MyCall.Caller.DN is ExternalLine externalLine))&lt;br /&gt;
                    {&lt;br /&gt;
                        MyCall.Return(false);&lt;br /&gt;
                        return;&lt;br /&gt;
                    }&lt;br /&gt;
&lt;br /&gt;
                    var DIDNumber = MyCall.Caller[&amp;quot;inbound_did&amp;quot;] ?? &amp;quot;&amp;quot;;&lt;br /&gt;
                    var CallerID = MyCall.Caller.CallerID ?? &amp;quot;&amp;quot;;&lt;br /&gt;
                    var currentTime = externalLine.Now(out var utc, out var timezone, out var groupmode);&lt;br /&gt;
&lt;br /&gt;
                    MyCall.Info($&amp;quot;Incoming call | Caller: {CallerID} | DID: {DIDNumber} | Time: {currentTime}&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
                    foreach (var rule in routingRules)&lt;br /&gt;
                    {&lt;br /&gt;
                        if (!rule.Schedule.IsActiveTime(currentTime))&lt;br /&gt;
                            continue;&lt;br /&gt;
&lt;br /&gt;
                        bool didMatch = rule.DIDs.Contains(&amp;quot;*&amp;quot;) || rule.DIDs.Contains(DIDNumber);&lt;br /&gt;
                        bool callerMatch = rule.Callers.Contains(&amp;quot;*&amp;quot;) || rule.Callers.Contains(CallerID);&lt;br /&gt;
&lt;br /&gt;
                        if (!didMatch || !callerMatch)&lt;br /&gt;
                            continue;&lt;br /&gt;
&lt;br /&gt;
                        var destinationDN = ps.GetDNByNumber(rule.DestinationDN);&lt;br /&gt;
&lt;br /&gt;
                        if (destinationDN == null)&lt;br /&gt;
                        {&lt;br /&gt;
                            MyCall.Error($&amp;quot;Destination {rule.DestinationDN} not found.&amp;quot;);&lt;br /&gt;
                            continue;&lt;br /&gt;
                        }&lt;br /&gt;
&lt;br /&gt;
                        try&lt;br /&gt;
                        {&lt;br /&gt;
                            var result = await MyCall.RouteToAsync(new DestinationStruct(destinationDN));&lt;br /&gt;
                            MyCall.Info($&amp;quot;Routed to {rule.DestinationDN} | Result: {result}&amp;quot;);&lt;br /&gt;
                            intercepted = true;&lt;br /&gt;
                            break; // Stop at first matching rule&lt;br /&gt;
                        }&lt;br /&gt;
                        catch (Exception ex)&lt;br /&gt;
                        {&lt;br /&gt;
                            MyCall.Error($&amp;quot;Routing failed to {rule.DestinationDN}: {ex}&amp;quot;);&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
&lt;br /&gt;
                &lt;br /&gt;
                    // Utilisation de la route par défaut&lt;br /&gt;
                    &lt;br /&gt;
                    if (!intercepted)&lt;br /&gt;
                    {&lt;br /&gt;
                        var fallbackDN = ps.GetDNByNumber(DefaultDestinationDN);&lt;br /&gt;
                        if (fallbackDN != null)&lt;br /&gt;
                        {&lt;br /&gt;
                            try&lt;br /&gt;
                            {&lt;br /&gt;
                                var result = await MyCall.RouteToAsync(new DestinationStruct(fallbackDN));&lt;br /&gt;
                                MyCall.Info($&amp;quot;Fallback routing to {DefaultDestinationDN} | Result: {result}&amp;quot;);&lt;br /&gt;
                                intercepted = true;&lt;br /&gt;
                            }&lt;br /&gt;
                            catch (Exception ex)&lt;br /&gt;
                            {&lt;br /&gt;
                                MyCall.Error($&amp;quot;Fallback routing failed: {ex}&amp;quot;);&lt;br /&gt;
                            }&lt;br /&gt;
                        }&lt;br /&gt;
                        else&lt;br /&gt;
                        {&lt;br /&gt;
                            MyCall.Error($&amp;quot;Fallback DN {DefaultDestinationDN} not found.&amp;quot;);&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
&lt;br /&gt;
                    MyCall.Return(intercepted);&lt;br /&gt;
                });&lt;br /&gt;
            }&lt;br /&gt;
            catch (Exception ex)&lt;br /&gt;
            {&lt;br /&gt;
                MyCall.Error($&amp;quot;Script execution failed: {ex}&amp;quot;);&lt;br /&gt;
                MyCall.Return(false);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Catégorie:3CX]]&lt;/div&gt;</summary>
		<author><name>Anthony</name></author>
	</entry>
	<entry>
		<id>https://indywiki.fr/index.php?title=Script_de_routage_des_appels&amp;diff=22268</id>
		<title>Script de routage des appels</title>
		<link rel="alternate" type="text/html" href="https://indywiki.fr/index.php?title=Script_de_routage_des_appels&amp;diff=22268"/>
		<updated>2026-05-27T13:15:38Z</updated>

		<summary type="html">&lt;p&gt;Anthony : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;syntaxhighlight lang=&amp;quot;csharp&amp;quot; line highlight=&amp;quot;16,37,43,52-54&amp;quot;&amp;gt;&lt;br /&gt;
#nullable disable&lt;br /&gt;
using CallFlow;&lt;br /&gt;
using System;&lt;br /&gt;
using System.Threading.Tasks;&lt;br /&gt;
using TCX.Configuration;&lt;br /&gt;
using TCX.PBXAPI;&lt;br /&gt;
using System.Collections.Generic;&lt;br /&gt;
using System.Linq;&lt;br /&gt;
using CallFlow.CFD;&lt;br /&gt;
&lt;br /&gt;
namespace interceptcall&lt;br /&gt;
{&lt;br /&gt;
    public class InterceptInboundCall : ScriptBase&amp;lt;InterceptInboundCall&amp;gt;&lt;br /&gt;
    {&lt;br /&gt;
        // Destination par Défaut, à priori jamais utilisé car ce numéro doit toujours être joignable&lt;br /&gt;
        const string DefaultDestinationDN = &amp;quot;812&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
        // Structure d&#039;une règle de routage&lt;br /&gt;
        class RoutingRule&lt;br /&gt;
        {&lt;br /&gt;
            public Schedule Schedule { get; set; }&lt;br /&gt;
            public string DestinationDN { get; set; }&lt;br /&gt;
            public string[] DIDs { get; set; }&lt;br /&gt;
            public string[] Callers { get; set; }&lt;br /&gt;
&lt;br /&gt;
            public RoutingRule(Schedule schedule, string destinationDN, string[] dids, string[] callers)&lt;br /&gt;
            {&lt;br /&gt;
                Schedule = schedule;&lt;br /&gt;
                DestinationDN = destinationDN;&lt;br /&gt;
                DIDs = dids;&lt;br /&gt;
                Callers = callers;&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
		// Règle(s) de routage &amp;quot;First Match&amp;quot; : La première règle satisfaite est éxécutée, les suivantes sont ignorées&lt;br /&gt;
&lt;br /&gt;
       static readonly List&amp;lt;RoutingRule&amp;gt; routingRules = new List&amp;lt;RoutingRule&amp;gt;&lt;br /&gt;
        {&lt;br /&gt;
            // Règle 1 - Mairie ouverte - routage vers le 801 qui route vers le 100 ( pas de changements&lt;br /&gt;
            new RoutingRule(&lt;br /&gt;
                new Schedule(RuleHoursType.SpecificHours)&lt;br /&gt;
                {&lt;br /&gt;
					{ DayOfWeek.Monday,    new Schedule.PeriodOfDay(new TimeSpan(14,00,0), new TimeSpan(17,00,0)) },&lt;br /&gt;
					{ DayOfWeek.Tuesday,    new Schedule.PeriodOfDay(new TimeSpan(14,00,0), new TimeSpan(17,00,0)) },&lt;br /&gt;
					{ DayOfWeek.Wednesday,    new Schedule.PeriodOfDay(new TimeSpan(09,00,0), new TimeSpan(12,00,0)) },&lt;br /&gt;
                    { DayOfWeek.Thursday,    new Schedule.PeriodOfDay(new TimeSpan(09,00,0), new TimeSpan(12,00,0)) },&lt;br /&gt;
					{ DayOfWeek.Friday,    new Schedule.PeriodOfDay(new TimeSpan(09,00,0), new TimeSpan(12,00,0)) }&lt;br /&gt;
                },&lt;br /&gt;
                &amp;quot;801&amp;quot;,&lt;br /&gt;
                new[] { &amp;quot;*&amp;quot; },   // Tous les DIDs&lt;br /&gt;
                new[] { &amp;quot;*&amp;quot; }    // Tous les callers&lt;br /&gt;
            ),&lt;br /&gt;
			&lt;br /&gt;
			 // Règle 2 — Mairie fermée en semaine ( routage vers le 800 )&lt;br /&gt;
            new RoutingRule(&lt;br /&gt;
                new Schedule(RuleHoursType.SpecificHours)&lt;br /&gt;
                {&lt;br /&gt;
					{ DayOfWeek.Monday,    new Schedule.PeriodOfDay(new TimeSpan(8,00,0), new TimeSpan(14,00,0)) },&lt;br /&gt;
     				{ DayOfWeek.Monday,    new Schedule.PeriodOfDay(new TimeSpan(17,00,0), new TimeSpan(24,00,0)) },&lt;br /&gt;
					{ DayOfWeek.Tuesday,    new Schedule.PeriodOfDay(new TimeSpan(0,00,0), new TimeSpan(14,00,0)) },&lt;br /&gt;
					{ DayOfWeek.Tuesday,    new Schedule.PeriodOfDay(new TimeSpan(17,00,0), new TimeSpan(24,00,0)) },&lt;br /&gt;
					{ DayOfWeek.Wednesday,    new Schedule.PeriodOfDay(new TimeSpan(0,00,0), new TimeSpan(09,00,0)) },&lt;br /&gt;
					{ DayOfWeek.Wednesday,    new Schedule.PeriodOfDay(new TimeSpan(12,00,0), new TimeSpan(24,00,0)) },&lt;br /&gt;
      				{ DayOfWeek.Thursday,    new Schedule.PeriodOfDay(new TimeSpan(0,00,0), new TimeSpan(09,00,0)) },&lt;br /&gt;
					{ DayOfWeek.Thursday,    new Schedule.PeriodOfDay(new TimeSpan(12,00,0), new TimeSpan(24,00,0)) },&lt;br /&gt;
      				{ DayOfWeek.Friday,    new Schedule.PeriodOfDay(new TimeSpan(0,00,0), new TimeSpan(09,00,0)) },&lt;br /&gt;
					{ DayOfWeek.Friday,    new Schedule.PeriodOfDay(new TimeSpan(12,00,0), new TimeSpan(24,00,0)) }&lt;br /&gt;
                },&lt;br /&gt;
                &amp;quot;800&amp;quot;,&lt;br /&gt;
                new[] { &amp;quot;*&amp;quot; },&lt;br /&gt;
                new[] { &amp;quot;*&amp;quot; }&lt;br /&gt;
            ),&lt;br /&gt;
			&lt;br /&gt;
			 // Règle 3 — Mairie fermée le week-end ( vendredi 16h30 au lundi ? )&lt;br /&gt;
            new RoutingRule(&lt;br /&gt;
                new Schedule(RuleHoursType.SpecificHours)&lt;br /&gt;
                {&lt;br /&gt;
					&lt;br /&gt;
					{ DayOfWeek.Friday,    new Schedule.PeriodOfDay(new TimeSpan(16,30,0), new TimeSpan(24,00,0)) },&lt;br /&gt;
					{ DayOfWeek.Saturday, new Schedule.PeriodOfDay(new TimeSpan(0,00,0), new TimeSpan(24,00,0)) },&lt;br /&gt;
					{ DayOfWeek.Sunday, new Schedule.PeriodOfDay(new TimeSpan(0,00,0), new TimeSpan(24,00,0)) }&lt;br /&gt;
      				{ DayOfWeek.Monday, new Schedule.PeriodOfDay(new TimeSpan(0,00,0), new TimeSpan(08,00,0)) }&lt;br /&gt;
                },&lt;br /&gt;
                &amp;quot;804&amp;quot;,&lt;br /&gt;
                new[] { &amp;quot;*&amp;quot; },&lt;br /&gt;
                new[] { &amp;quot;*&amp;quot; }&lt;br /&gt;
            ),&lt;br /&gt;
			&lt;br /&gt;
        };&lt;br /&gt;
&lt;br /&gt;
        // Appel de la fonction principale&lt;br /&gt;
&lt;br /&gt;
        public override async void Start()&lt;br /&gt;
        {&lt;br /&gt;
            try&lt;br /&gt;
            {&lt;br /&gt;
                await Task.Run(async () =&amp;gt;&lt;br /&gt;
                {&lt;br /&gt;
                    bool intercepted = false;&lt;br /&gt;
                    var ps = MyCall.PS as PhoneSystem;&lt;br /&gt;
&lt;br /&gt;
                    if (!(MyCall.Caller.DN is ExternalLine externalLine))&lt;br /&gt;
                    {&lt;br /&gt;
                        MyCall.Return(false);&lt;br /&gt;
                        return;&lt;br /&gt;
                    }&lt;br /&gt;
&lt;br /&gt;
                    var DIDNumber = MyCall.Caller[&amp;quot;inbound_did&amp;quot;] ?? &amp;quot;&amp;quot;;&lt;br /&gt;
                    var CallerID = MyCall.Caller.CallerID ?? &amp;quot;&amp;quot;;&lt;br /&gt;
                    var currentTime = externalLine.Now(out var utc, out var timezone, out var groupmode);&lt;br /&gt;
&lt;br /&gt;
                    MyCall.Info($&amp;quot;Incoming call | Caller: {CallerID} | DID: {DIDNumber} | Time: {currentTime}&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
                    foreach (var rule in routingRules)&lt;br /&gt;
                    {&lt;br /&gt;
                        if (!rule.Schedule.IsActiveTime(currentTime))&lt;br /&gt;
                            continue;&lt;br /&gt;
&lt;br /&gt;
                        bool didMatch = rule.DIDs.Contains(&amp;quot;*&amp;quot;) || rule.DIDs.Contains(DIDNumber);&lt;br /&gt;
                        bool callerMatch = rule.Callers.Contains(&amp;quot;*&amp;quot;) || rule.Callers.Contains(CallerID);&lt;br /&gt;
&lt;br /&gt;
                        if (!didMatch || !callerMatch)&lt;br /&gt;
                            continue;&lt;br /&gt;
&lt;br /&gt;
                        var destinationDN = ps.GetDNByNumber(rule.DestinationDN);&lt;br /&gt;
&lt;br /&gt;
                        if (destinationDN == null)&lt;br /&gt;
                        {&lt;br /&gt;
                            MyCall.Error($&amp;quot;Destination {rule.DestinationDN} not found.&amp;quot;);&lt;br /&gt;
                            continue;&lt;br /&gt;
                        }&lt;br /&gt;
&lt;br /&gt;
                        try&lt;br /&gt;
                        {&lt;br /&gt;
                            var result = await MyCall.RouteToAsync(new DestinationStruct(destinationDN));&lt;br /&gt;
                            MyCall.Info($&amp;quot;Routed to {rule.DestinationDN} | Result: {result}&amp;quot;);&lt;br /&gt;
                            intercepted = true;&lt;br /&gt;
                            break; // Stop at first matching rule&lt;br /&gt;
                        }&lt;br /&gt;
                        catch (Exception ex)&lt;br /&gt;
                        {&lt;br /&gt;
                            MyCall.Error($&amp;quot;Routing failed to {rule.DestinationDN}: {ex}&amp;quot;);&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
&lt;br /&gt;
                &lt;br /&gt;
                    // Utilisation de la route par défaut&lt;br /&gt;
                    &lt;br /&gt;
                    if (!intercepted)&lt;br /&gt;
                    {&lt;br /&gt;
                        var fallbackDN = ps.GetDNByNumber(DefaultDestinationDN);&lt;br /&gt;
                        if (fallbackDN != null)&lt;br /&gt;
                        {&lt;br /&gt;
                            try&lt;br /&gt;
                            {&lt;br /&gt;
                                var result = await MyCall.RouteToAsync(new DestinationStruct(fallbackDN));&lt;br /&gt;
                                MyCall.Info($&amp;quot;Fallback routing to {DefaultDestinationDN} | Result: {result}&amp;quot;);&lt;br /&gt;
                                intercepted = true;&lt;br /&gt;
                            }&lt;br /&gt;
                            catch (Exception ex)&lt;br /&gt;
                            {&lt;br /&gt;
                                MyCall.Error($&amp;quot;Fallback routing failed: {ex}&amp;quot;);&lt;br /&gt;
                            }&lt;br /&gt;
                        }&lt;br /&gt;
                        else&lt;br /&gt;
                        {&lt;br /&gt;
                            MyCall.Error($&amp;quot;Fallback DN {DefaultDestinationDN} not found.&amp;quot;);&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
&lt;br /&gt;
                    MyCall.Return(intercepted);&lt;br /&gt;
                });&lt;br /&gt;
            }&lt;br /&gt;
            catch (Exception ex)&lt;br /&gt;
            {&lt;br /&gt;
                MyCall.Error($&amp;quot;Script execution failed: {ex}&amp;quot;);&lt;br /&gt;
                MyCall.Return(false);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Catégorie:3CX]]&lt;/div&gt;</summary>
		<author><name>Anthony</name></author>
	</entry>
	<entry>
		<id>https://indywiki.fr/index.php?title=Discussion:Astreinte&amp;diff=22267</id>
		<title>Discussion:Astreinte</title>
		<link rel="alternate" type="text/html" href="https://indywiki.fr/index.php?title=Discussion:Astreinte&amp;diff=22267"/>
		<updated>2026-04-28T13:32:56Z</updated>

		<summary type="html">&lt;p&gt;Anthony : Page créée avec « ====Table de correspondance des profileName====  {| class=&amp;quot;wikitable&amp;quot; |- ! Dans 3CX!! Dans le script |- | Disponible|| Available |- | Absent|| Away |- | Ne pas déranger|| Out of office |- | Custom 1|| Custom 1 |- | Custom 2|| Custom 2 |} »&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;====Table de correspondance des profileName====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Dans 3CX!! Dans le script&lt;br /&gt;
|-&lt;br /&gt;
| Disponible|| Available&lt;br /&gt;
|-&lt;br /&gt;
| Absent|| Away&lt;br /&gt;
|-&lt;br /&gt;
| Ne pas déranger|| Out of office&lt;br /&gt;
|-&lt;br /&gt;
| Custom 1|| Custom 1&lt;br /&gt;
|-&lt;br /&gt;
| Custom 2|| Custom 2&lt;br /&gt;
|}&lt;/div&gt;</summary>
		<author><name>Anthony</name></author>
	</entry>
	<entry>
		<id>https://indywiki.fr/index.php?title=Astreinte&amp;diff=22266</id>
		<title>Astreinte</title>
		<link rel="alternate" type="text/html" href="https://indywiki.fr/index.php?title=Astreinte&amp;diff=22266"/>
		<updated>2026-04-28T13:32:13Z</updated>

		<summary type="html">&lt;p&gt;Anthony : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;===Principe===&lt;br /&gt;
On paramètre le statut choisi pour l&#039;astreinte en renvoi vers &#039;&#039;&#039;mon mobile&#039;&#039;&#039;. Un script viendra modifier le statut de l&#039;extension cible ainsi que son numéro de contact mobile, prénom et nom. Ce script déclenchable par l&#039;appel à un code court, paramétrable si on le souhaite sur une BLF. &lt;br /&gt;
&lt;br /&gt;
===Déclaration du script===&lt;br /&gt;
[[Fichier:2026-04-02 17h11 35.png|vignette]]&lt;br /&gt;
&lt;br /&gt;
Rendez-vous dans :&lt;br /&gt;
&lt;br /&gt;
 Admin / Intégrations / Scripts d&#039;appels / + Ajouter personnalisé&lt;br /&gt;
&lt;br /&gt;
#Donner un nom au traitement de l&#039;appel. Exemple : &#039;&#039;&#039;astreinte_weekend&#039;&#039;&#039;&lt;br /&gt;
#Créer un code de raccourci, ce qui permettra d&#039;exécuter le script simplement en appelant ce code, et in fine par une BLF. Exemple : &#039;&#039;&#039;*99&#039;&#039;&#039;&lt;br /&gt;
#OK&lt;br /&gt;
#Coller dans le champ script le script paramétré ( voir section suivante )&lt;br /&gt;
#Sauvegarder&lt;br /&gt;
#Un message doit indiquer &#039;&#039;&#039;Compilation réussie !&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Le script d&#039;astreinte===&lt;br /&gt;
&lt;br /&gt;
L&#039;éxécution du script va modifier l&#039;extension &#039;&#039;&#039;targetExtNum &#039;&#039;&#039;, il va le basculer sur le statut &#039;&#039;&#039;profileName &#039;&#039;&#039;, modifier son mobile de contact &#039;&#039;&#039;mobileElu &#039;&#039;&#039;, son nom et prénom.&lt;br /&gt;
&lt;br /&gt;
Il faut donc seulement modifier les lignes surlignés dans le code ci-dessous :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;csharp&amp;quot; line highlight=&amp;quot;14-17&amp;quot;&amp;gt;&lt;br /&gt;
using System;&lt;br /&gt;
using System.Threading.Tasks;&lt;br /&gt;
using TCX.Configuration;&lt;br /&gt;
using CallFlow;&lt;br /&gt;
using System.Linq;&lt;br /&gt;
&lt;br /&gt;
namespace dummy&lt;br /&gt;
{&lt;br /&gt;
    public class SetDynamicAstreinte : ScriptBase&amp;lt;SetDynamicAstreinte&amp;gt;&lt;br /&gt;
    {&lt;br /&gt;
        // ============================================================&lt;br /&gt;
        // CONFIGURATION — modifier uniquement ces lignes par script&lt;br /&gt;
        // ============================================================&lt;br /&gt;
        private const string TARGET_EXT   = &amp;quot;111&amp;quot;;&lt;br /&gt;
        private const string MOBILE_EXT   = &amp;quot;0612345678&amp;quot;;&lt;br /&gt;
        private const string PRENOM_EXT   = &amp;quot;Claude&amp;quot;;&lt;br /&gt;
        private const string NOM_EXT      = &amp;quot;IA&amp;quot;;&lt;br /&gt;
		 // ============================================================&lt;br /&gt;
        &lt;br /&gt;
		private const string PROFILE_NAME = &amp;quot;Away&amp;quot;;&lt;br /&gt;
       &lt;br /&gt;
        public override Task&amp;lt;bool&amp;gt; StartAsync()&lt;br /&gt;
        {&lt;br /&gt;
            try&lt;br /&gt;
            {&lt;br /&gt;
                IPhoneSystem ps = PhoneSystem.Root;&lt;br /&gt;
                Extension ext = ps.GetDNByNumber(TARGET_EXT) as Extension;&lt;br /&gt;
                if (ext == null)&lt;br /&gt;
                    return Task.FromResult(false);&lt;br /&gt;
&lt;br /&gt;
                // 1. Nom / Prénom&lt;br /&gt;
                ext.FirstName = PRENOM_EXT;&lt;br /&gt;
                ext.LastName  = NOM_EXT;&lt;br /&gt;
&lt;br /&gt;
                // 2. Numéro mobile&lt;br /&gt;
                ext.SetProperty(&amp;quot;MOBILENUMBER&amp;quot;, MOBILE_EXT);&lt;br /&gt;
&lt;br /&gt;
                // 3. Trouver le profil Away&lt;br /&gt;
                FwdProfile targetProfile = ext.FwdProfiles&lt;br /&gt;
                    .FirstOrDefault(p =&amp;gt; p.Name.Equals(&lt;br /&gt;
                        PROFILE_NAME, StringComparison.OrdinalIgnoreCase));&lt;br /&gt;
&lt;br /&gt;
                if (targetProfile != null)&lt;br /&gt;
                {&lt;br /&gt;
                    // AwayRoute, Internal, External sont read-only&lt;br /&gt;
                    // mais ce sont des références : on peut modifier&lt;br /&gt;
                    // leurs membres si ceux-ci sont accessibles en écriture&lt;br /&gt;
                    AwayRouting route = targetProfile.AwayRoute;&lt;br /&gt;
&lt;br /&gt;
                    // Capturer les HoursDestination comme variables locales&lt;br /&gt;
                    // (objets référence — la propriété est read-only,&lt;br /&gt;
                    //  mais l&#039;objet pointé est modifiable)&lt;br /&gt;
                    HoursDestination internalHours = route.Internal;&lt;br /&gt;
                    HoursDestination externalHours = route.External;&lt;br /&gt;
&lt;br /&gt;
                    // Capturer AllHours (struct) → modifier → réassigner&lt;br /&gt;
                    DestinationStruct destInternal = internalHours.AllHours;&lt;br /&gt;
                    destInternal.To               = DestinationType.Boomerang;&lt;br /&gt;
                    destInternal.External         = MOBILE_EXT;&lt;br /&gt;
                    internalHours.AllHours        = destInternal;&lt;br /&gt;
&lt;br /&gt;
                    DestinationStruct destExternal = externalHours.AllHours;&lt;br /&gt;
                    destExternal.To               = DestinationType.Boomerang;&lt;br /&gt;
                    destExternal.External         = MOBILE_EXT;&lt;br /&gt;
                    externalHours.AllHours        = destExternal;&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                // 4. Sauvegarder&lt;br /&gt;
                ext.Save();&lt;br /&gt;
&lt;br /&gt;
                // 5. Recharger et basculer le profil&lt;br /&gt;
                ext = ps.GetDNByNumber(TARGET_EXT) as Extension;&lt;br /&gt;
                if (ext == null)&lt;br /&gt;
                    return Task.FromResult(false);&lt;br /&gt;
&lt;br /&gt;
                FwdProfile profile = ext.FwdProfiles&lt;br /&gt;
                    .FirstOrDefault(p =&amp;gt; p.Name.Equals(&lt;br /&gt;
                        PROFILE_NAME, StringComparison.OrdinalIgnoreCase));&lt;br /&gt;
&lt;br /&gt;
                if (profile != null)&lt;br /&gt;
                {&lt;br /&gt;
                    ext.CurrentProfile = profile;&lt;br /&gt;
                    ext.Save();&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                return Task.FromResult(true);&lt;br /&gt;
            }&lt;br /&gt;
            catch (Exception)&lt;br /&gt;
            {&lt;br /&gt;
                return Task.FromResult(false);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Le script de retour à la normale===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;csharp&amp;quot; line highlight=&amp;quot;14-16&amp;quot;&amp;gt;&lt;br /&gt;
using System;&lt;br /&gt;
using System.Threading.Tasks;&lt;br /&gt;
using TCX.Configuration;&lt;br /&gt;
using CallFlow;&lt;br /&gt;
using System.Linq;&lt;br /&gt;
&lt;br /&gt;
namespace dummy&lt;br /&gt;
{&lt;br /&gt;
    public class ResetAstreinte : ScriptBase&amp;lt;ResetAstreinte&amp;gt;&lt;br /&gt;
    {&lt;br /&gt;
        // ============================================================&lt;br /&gt;
        // CONFIGURATION — modifier uniquement ces lignes par script&lt;br /&gt;
        // ============================================================&lt;br /&gt;
        private const string TARGET_EXT   = &amp;quot;111&amp;quot;;&lt;br /&gt;
        private const string PRENOM_EXT   = &amp;quot;Accueil&amp;quot;;&lt;br /&gt;
        private const string NOM_EXT      = &amp;quot;Mairie&amp;quot;;&lt;br /&gt;
        // ============================================================&lt;br /&gt;
&lt;br /&gt;
        public override Task&amp;lt;bool&amp;gt; StartAsync()&lt;br /&gt;
        {&lt;br /&gt;
            try&lt;br /&gt;
            {&lt;br /&gt;
                IPhoneSystem ps = PhoneSystem.Root;&lt;br /&gt;
                Extension ext = ps.GetDNByNumber(TARGET_EXT) as Extension;&lt;br /&gt;
                if (ext == null)&lt;br /&gt;
                    return Task.FromResult(false);&lt;br /&gt;
&lt;br /&gt;
                // 1. Remettre le nom générique&lt;br /&gt;
                ext.FirstName = PRENOM_EXT;&lt;br /&gt;
                ext.LastName  = NOM_EXT;&lt;br /&gt;
&lt;br /&gt;
                // 2. Vider le numéro mobile&lt;br /&gt;
                ext.SetProperty(&amp;quot;MOBILENUMBER&amp;quot;, &amp;quot;&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
                // 3. Résoudre le DN pour la messagerie vocale&lt;br /&gt;
                DN targetDN = ps.GetDNByNumber(TARGET_EXT);&lt;br /&gt;
&lt;br /&gt;
                // 4. Remettre AwayRoute → messagerie vocale&lt;br /&gt;
                FwdProfile awayProfile = ext.FwdProfiles&lt;br /&gt;
                    .FirstOrDefault(p =&amp;gt; p.Name.Equals(&lt;br /&gt;
                        &amp;quot;Away&amp;quot;, StringComparison.OrdinalIgnoreCase));&lt;br /&gt;
&lt;br /&gt;
                if (awayProfile != null)&lt;br /&gt;
                {&lt;br /&gt;
                    AwayRouting route = awayProfile.AwayRoute;&lt;br /&gt;
&lt;br /&gt;
                    HoursDestination internalHours = route.Internal;&lt;br /&gt;
                    HoursDestination externalHours = route.External;&lt;br /&gt;
&lt;br /&gt;
                    DestinationStruct destInternal = internalHours.AllHours;&lt;br /&gt;
                    destInternal.To               = DestinationType.VoiceMail;&lt;br /&gt;
                    destInternal.Internal         = targetDN;&lt;br /&gt;
                    destInternal.External         = &amp;quot;&amp;quot;;&lt;br /&gt;
                    internalHours.AllHours        = destInternal;&lt;br /&gt;
&lt;br /&gt;
                    DestinationStruct destExternal = externalHours.AllHours;&lt;br /&gt;
                    destExternal.To               = DestinationType.VoiceMail;&lt;br /&gt;
                    destExternal.Internal         = targetDN;&lt;br /&gt;
                    destExternal.External         = &amp;quot;&amp;quot;;&lt;br /&gt;
                    externalHours.AllHours        = destExternal;&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                // 5. Sauvegarder&lt;br /&gt;
                ext.Save();&lt;br /&gt;
&lt;br /&gt;
                // 6. Recharger et basculer vers Available&lt;br /&gt;
                ext = ps.GetDNByNumber(TARGET_EXT) as Extension;&lt;br /&gt;
                if (ext == null)&lt;br /&gt;
                    return Task.FromResult(false);&lt;br /&gt;
&lt;br /&gt;
                FwdProfile profile = ext.FwdProfiles&lt;br /&gt;
                    .FirstOrDefault(p =&amp;gt; p.Name.Equals(&lt;br /&gt;
                        &amp;quot;Available&amp;quot;, StringComparison.OrdinalIgnoreCase));&lt;br /&gt;
&lt;br /&gt;
                if (profile != null)&lt;br /&gt;
                {&lt;br /&gt;
                    ext.CurrentProfile = profile;&lt;br /&gt;
                    ext.Save();&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                return Task.FromResult(true);&lt;br /&gt;
            }&lt;br /&gt;
            catch (Exception)&lt;br /&gt;
            {&lt;br /&gt;
                return Task.FromResult(false);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Configuration concrète===&lt;br /&gt;
&lt;br /&gt;
On a besoin de gérer deux astreintes. Le poste Accueil reçoit les appels en temps normal&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Texte de la légende&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;Marcel Patulacci&#039;&#039;&#039; || &#039;&#039;&#039;Jean-Michel Apeuprè&#039;&#039;&#039;|| &#039;&#039;&#039;Poste accueil &#039;&#039;&#039; hors période d&#039;astreinte&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;syntaxhighlight lang=&amp;quot;csharp&amp;quot; line highlight=&amp;quot;4-7&amp;quot;&amp;gt;&lt;br /&gt;
    public class SetDynamicAstreinte : ScriptBase&amp;lt;SetDynamicAstreinte&amp;gt;&lt;br /&gt;
    {&lt;br /&gt;
        // CONFIGURATION — modifier uniquement ces lignes&lt;br /&gt;
        private const string TARGET_EXT   = &amp;quot;111&amp;quot;;&lt;br /&gt;
        private const string MOBILE_EXT   = &amp;quot;0612345678&amp;quot;;&lt;br /&gt;
        private const string PRENOM_EXT   = &amp;quot;Marcel&amp;quot;;&lt;br /&gt;
        private const string NOM_EXT      = &amp;quot;Patulacci&amp;quot;;&lt;br /&gt;
		 //&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt; || &amp;lt;syntaxhighlight lang=&amp;quot;csharp&amp;quot; line highlight=&amp;quot;4-7&amp;quot;&amp;gt;&lt;br /&gt;
    public class SetDynamicAstreinte : ScriptBase&amp;lt;SetDynamicAstreinte&amp;gt;&lt;br /&gt;
    {&lt;br /&gt;
        // CONFIGURATION — modifier uniquement ces lignes par script&lt;br /&gt;
        private const string TARGET_EXT   = &amp;quot;111&amp;quot;;&lt;br /&gt;
        private const string MOBILE_EXT   = &amp;quot;0699999999&amp;quot;;&lt;br /&gt;
        private const string PRENOM_EXT   = &amp;quot;Jean-Michel&amp;quot;;&lt;br /&gt;
        private const string NOM_EXT      = &amp;quot;Apeuprè&amp;quot;;&lt;br /&gt;
		 // &lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;|| &amp;lt;syntaxhighlight lang=&amp;quot;csharp&amp;quot; line highlight=&amp;quot;4-6&amp;quot;&amp;gt;&lt;br /&gt;
    public class ResetAstreinte : ScriptBase&amp;lt;ResetAstreinte&amp;gt;&lt;br /&gt;
    {&lt;br /&gt;
        // CONFIGURATION — modifier uniquement ces lignes par script&lt;br /&gt;
        private const string TARGET_EXT   = &amp;quot;111&amp;quot;;&lt;br /&gt;
        private const string PRENOM_EXT   = &amp;quot;Accueil&amp;quot;;&lt;br /&gt;
        private const string NOM_EXT      = &amp;quot;Mairie&amp;quot;;&lt;br /&gt;
        // &lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Une fois les 3 scripts produits, passer à l&#039;étape [[Astreinte#Déclaration_du_script|Déclaration du script]] qui va permettre d&#039;affecter un code court à chaque script.&lt;br /&gt;
Exemple : &lt;br /&gt;
* *90 pour hors période d&#039;astreinte&lt;br /&gt;
* *91 pour Jean-Michel&lt;br /&gt;
* *92 pour Marcel&lt;br /&gt;
&lt;br /&gt;
On peut communiquer les codes aux personnes habilitées à gérer le système d&#039;astreinte et aller jusqu&#039;à paramétrer des BLF pour faciliter la vie d&#039;une secrétaire par exemple.&lt;br /&gt;
&lt;br /&gt;
{{Valide|v20}}&lt;br /&gt;
[[Catégorie:3CX]]&lt;/div&gt;</summary>
		<author><name>Anthony</name></author>
	</entry>
	<entry>
		<id>https://indywiki.fr/index.php?title=Astreinte&amp;diff=22265</id>
		<title>Astreinte</title>
		<link rel="alternate" type="text/html" href="https://indywiki.fr/index.php?title=Astreinte&amp;diff=22265"/>
		<updated>2026-04-28T13:31:02Z</updated>

		<summary type="html">&lt;p&gt;Anthony : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;===Principe===&lt;br /&gt;
On paramètre le statut choisi pour l&#039;astreinte en renvoi vers &#039;&#039;&#039;mon mobile&#039;&#039;&#039;. Un script viendra modifier le statut de l&#039;extension cible ainsi que son numéro de contact mobile, prénom et nom. Ce script déclenchable par l&#039;appel à un code court, paramétrable si on le souhaite sur une BLF. &lt;br /&gt;
&lt;br /&gt;
===Déclaration du script===&lt;br /&gt;
[[Fichier:2026-04-02 17h11 35.png|vignette]]&lt;br /&gt;
&lt;br /&gt;
Rendez-vous dans :&lt;br /&gt;
&lt;br /&gt;
 Admin / Intégrations / Scripts d&#039;appels / + Ajouter personnalisé&lt;br /&gt;
&lt;br /&gt;
#Donner un nom au traitement de l&#039;appel. Exemple : &#039;&#039;&#039;astreinte_weekend&#039;&#039;&#039;&lt;br /&gt;
#Créer un code de raccourci, ce qui permettra d&#039;exécuter le script simplement en appelant ce code, et in fine par une BLF. Exemple : &#039;&#039;&#039;*99&#039;&#039;&#039;&lt;br /&gt;
#OK&lt;br /&gt;
#Coller dans le champ script le script paramétré ( voir section suivante )&lt;br /&gt;
#Sauvegarder&lt;br /&gt;
#Un message doit indiquer &#039;&#039;&#039;Compilation réussie !&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Le script d&#039;astreinte===&lt;br /&gt;
&lt;br /&gt;
L&#039;éxécution du script va modifier l&#039;extension &#039;&#039;&#039;targetExtNum &#039;&#039;&#039;, il va le basculer sur le statut &#039;&#039;&#039;profileName &#039;&#039;&#039;, modifier son mobile de contact &#039;&#039;&#039;mobileElu &#039;&#039;&#039;, son nom et prénom.&lt;br /&gt;
&lt;br /&gt;
Il faut donc seulement modifier les lignes surlignés dans le code ci-dessous :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;csharp&amp;quot; line highlight=&amp;quot;14-17&amp;quot;&amp;gt;&lt;br /&gt;
using System;&lt;br /&gt;
using System.Threading.Tasks;&lt;br /&gt;
using TCX.Configuration;&lt;br /&gt;
using CallFlow;&lt;br /&gt;
using System.Linq;&lt;br /&gt;
&lt;br /&gt;
namespace dummy&lt;br /&gt;
{&lt;br /&gt;
    public class SetDynamicAstreinte : ScriptBase&amp;lt;SetDynamicAstreinte&amp;gt;&lt;br /&gt;
    {&lt;br /&gt;
        // ============================================================&lt;br /&gt;
        // CONFIGURATION — modifier uniquement ces lignes par script&lt;br /&gt;
        // ============================================================&lt;br /&gt;
        private const string TARGET_EXT   = &amp;quot;111&amp;quot;;&lt;br /&gt;
        private const string MOBILE_EXT   = &amp;quot;0612345678&amp;quot;;&lt;br /&gt;
        private const string PRENOM_EXT   = &amp;quot;Claude&amp;quot;;&lt;br /&gt;
        private const string NOM_EXT      = &amp;quot;IA&amp;quot;;&lt;br /&gt;
		 // ============================================================&lt;br /&gt;
        &lt;br /&gt;
		private const string PROFILE_NAME = &amp;quot;Away&amp;quot;;&lt;br /&gt;
       &lt;br /&gt;
        public override Task&amp;lt;bool&amp;gt; StartAsync()&lt;br /&gt;
        {&lt;br /&gt;
            try&lt;br /&gt;
            {&lt;br /&gt;
                IPhoneSystem ps = PhoneSystem.Root;&lt;br /&gt;
                Extension ext = ps.GetDNByNumber(TARGET_EXT) as Extension;&lt;br /&gt;
                if (ext == null)&lt;br /&gt;
                    return Task.FromResult(false);&lt;br /&gt;
&lt;br /&gt;
                // 1. Nom / Prénom&lt;br /&gt;
                ext.FirstName = PRENOM_EXT;&lt;br /&gt;
                ext.LastName  = NOM_EXT;&lt;br /&gt;
&lt;br /&gt;
                // 2. Numéro mobile&lt;br /&gt;
                ext.SetProperty(&amp;quot;MOBILENUMBER&amp;quot;, MOBILE_EXT);&lt;br /&gt;
&lt;br /&gt;
                // 3. Trouver le profil Away&lt;br /&gt;
                FwdProfile targetProfile = ext.FwdProfiles&lt;br /&gt;
                    .FirstOrDefault(p =&amp;gt; p.Name.Equals(&lt;br /&gt;
                        PROFILE_NAME, StringComparison.OrdinalIgnoreCase));&lt;br /&gt;
&lt;br /&gt;
                if (targetProfile != null)&lt;br /&gt;
                {&lt;br /&gt;
                    // AwayRoute, Internal, External sont read-only&lt;br /&gt;
                    // mais ce sont des références : on peut modifier&lt;br /&gt;
                    // leurs membres si ceux-ci sont accessibles en écriture&lt;br /&gt;
                    AwayRouting route = targetProfile.AwayRoute;&lt;br /&gt;
&lt;br /&gt;
                    // Capturer les HoursDestination comme variables locales&lt;br /&gt;
                    // (objets référence — la propriété est read-only,&lt;br /&gt;
                    //  mais l&#039;objet pointé est modifiable)&lt;br /&gt;
                    HoursDestination internalHours = route.Internal;&lt;br /&gt;
                    HoursDestination externalHours = route.External;&lt;br /&gt;
&lt;br /&gt;
                    // Capturer AllHours (struct) → modifier → réassigner&lt;br /&gt;
                    DestinationStruct destInternal = internalHours.AllHours;&lt;br /&gt;
                    destInternal.To               = DestinationType.Boomerang;&lt;br /&gt;
                    destInternal.External         = MOBILE_EXT;&lt;br /&gt;
                    internalHours.AllHours        = destInternal;&lt;br /&gt;
&lt;br /&gt;
                    DestinationStruct destExternal = externalHours.AllHours;&lt;br /&gt;
                    destExternal.To               = DestinationType.Boomerang;&lt;br /&gt;
                    destExternal.External         = MOBILE_EXT;&lt;br /&gt;
                    externalHours.AllHours        = destExternal;&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                // 4. Sauvegarder&lt;br /&gt;
                ext.Save();&lt;br /&gt;
&lt;br /&gt;
                // 5. Recharger et basculer le profil&lt;br /&gt;
                ext = ps.GetDNByNumber(TARGET_EXT) as Extension;&lt;br /&gt;
                if (ext == null)&lt;br /&gt;
                    return Task.FromResult(false);&lt;br /&gt;
&lt;br /&gt;
                FwdProfile profile = ext.FwdProfiles&lt;br /&gt;
                    .FirstOrDefault(p =&amp;gt; p.Name.Equals(&lt;br /&gt;
                        PROFILE_NAME, StringComparison.OrdinalIgnoreCase));&lt;br /&gt;
&lt;br /&gt;
                if (profile != null)&lt;br /&gt;
                {&lt;br /&gt;
                    ext.CurrentProfile = profile;&lt;br /&gt;
                    ext.Save();&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                return Task.FromResult(true);&lt;br /&gt;
            }&lt;br /&gt;
            catch (Exception)&lt;br /&gt;
            {&lt;br /&gt;
                return Task.FromResult(false);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Le script de retour à la normale===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;csharp&amp;quot; line highlight=&amp;quot;14-16&amp;quot;&amp;gt;&lt;br /&gt;
using System;&lt;br /&gt;
using System.Threading.Tasks;&lt;br /&gt;
using TCX.Configuration;&lt;br /&gt;
using CallFlow;&lt;br /&gt;
using System.Linq;&lt;br /&gt;
&lt;br /&gt;
namespace dummy&lt;br /&gt;
{&lt;br /&gt;
    public class ResetAstreinte : ScriptBase&amp;lt;ResetAstreinte&amp;gt;&lt;br /&gt;
    {&lt;br /&gt;
        // ============================================================&lt;br /&gt;
        // CONFIGURATION — modifier uniquement ces lignes par script&lt;br /&gt;
        // ============================================================&lt;br /&gt;
        private const string TARGET_EXT   = &amp;quot;111&amp;quot;;&lt;br /&gt;
        private const string PRENOM_EXT   = &amp;quot;Accueil&amp;quot;;&lt;br /&gt;
        private const string NOM_EXT      = &amp;quot;Mairie&amp;quot;;&lt;br /&gt;
        // ============================================================&lt;br /&gt;
&lt;br /&gt;
        public override Task&amp;lt;bool&amp;gt; StartAsync()&lt;br /&gt;
        {&lt;br /&gt;
            try&lt;br /&gt;
            {&lt;br /&gt;
                IPhoneSystem ps = PhoneSystem.Root;&lt;br /&gt;
                Extension ext = ps.GetDNByNumber(TARGET_EXT) as Extension;&lt;br /&gt;
                if (ext == null)&lt;br /&gt;
                    return Task.FromResult(false);&lt;br /&gt;
&lt;br /&gt;
                // 1. Remettre le nom générique&lt;br /&gt;
                ext.FirstName = PRENOM_EXT;&lt;br /&gt;
                ext.LastName  = NOM_EXT;&lt;br /&gt;
&lt;br /&gt;
                // 2. Vider le numéro mobile&lt;br /&gt;
                ext.SetProperty(&amp;quot;MOBILENUMBER&amp;quot;, &amp;quot;&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
                // 3. Résoudre le DN pour la messagerie vocale&lt;br /&gt;
                DN targetDN = ps.GetDNByNumber(TARGET_EXT);&lt;br /&gt;
&lt;br /&gt;
                // 4. Remettre AwayRoute → messagerie vocale&lt;br /&gt;
                FwdProfile awayProfile = ext.FwdProfiles&lt;br /&gt;
                    .FirstOrDefault(p =&amp;gt; p.Name.Equals(&lt;br /&gt;
                        &amp;quot;Away&amp;quot;, StringComparison.OrdinalIgnoreCase));&lt;br /&gt;
&lt;br /&gt;
                if (awayProfile != null)&lt;br /&gt;
                {&lt;br /&gt;
                    AwayRouting route = awayProfile.AwayRoute;&lt;br /&gt;
&lt;br /&gt;
                    HoursDestination internalHours = route.Internal;&lt;br /&gt;
                    HoursDestination externalHours = route.External;&lt;br /&gt;
&lt;br /&gt;
                    DestinationStruct destInternal = internalHours.AllHours;&lt;br /&gt;
                    destInternal.To               = DestinationType.VoiceMail;&lt;br /&gt;
                    destInternal.Internal         = targetDN;&lt;br /&gt;
                    destInternal.External         = &amp;quot;&amp;quot;;&lt;br /&gt;
                    internalHours.AllHours        = destInternal;&lt;br /&gt;
&lt;br /&gt;
                    DestinationStruct destExternal = externalHours.AllHours;&lt;br /&gt;
                    destExternal.To               = DestinationType.VoiceMail;&lt;br /&gt;
                    destExternal.Internal         = targetDN;&lt;br /&gt;
                    destExternal.External         = &amp;quot;&amp;quot;;&lt;br /&gt;
                    externalHours.AllHours        = destExternal;&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                // 5. Sauvegarder&lt;br /&gt;
                ext.Save();&lt;br /&gt;
&lt;br /&gt;
                // 6. Recharger et basculer vers Available&lt;br /&gt;
                ext = ps.GetDNByNumber(TARGET_EXT) as Extension;&lt;br /&gt;
                if (ext == null)&lt;br /&gt;
                    return Task.FromResult(false);&lt;br /&gt;
&lt;br /&gt;
                FwdProfile profile = ext.FwdProfiles&lt;br /&gt;
                    .FirstOrDefault(p =&amp;gt; p.Name.Equals(&lt;br /&gt;
                        &amp;quot;Available&amp;quot;, StringComparison.OrdinalIgnoreCase));&lt;br /&gt;
&lt;br /&gt;
                if (profile != null)&lt;br /&gt;
                {&lt;br /&gt;
                    ext.CurrentProfile = profile;&lt;br /&gt;
                    ext.Save();&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                return Task.FromResult(true);&lt;br /&gt;
            }&lt;br /&gt;
            catch (Exception)&lt;br /&gt;
            {&lt;br /&gt;
                return Task.FromResult(false);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Table de correspondance des profileName====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Dans 3CX!! Dans le script&lt;br /&gt;
|-&lt;br /&gt;
| Disponible|| Available&lt;br /&gt;
|-&lt;br /&gt;
| Absent|| Away&lt;br /&gt;
|-&lt;br /&gt;
| Ne pas déranger|| Out of office&lt;br /&gt;
|-&lt;br /&gt;
| Custom 1|| Custom 1&lt;br /&gt;
|-&lt;br /&gt;
| Custom 2|| Custom 2&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===Configuration concrète===&lt;br /&gt;
&lt;br /&gt;
On a besoin de gérer deux astreintes. Le poste Accueil reçoit les appels en temps normal&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Texte de la légende&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;Marcel Patulacci&#039;&#039;&#039; || &#039;&#039;&#039;Jean-Michel Apeuprè&#039;&#039;&#039;|| &#039;&#039;&#039;Poste accueil &#039;&#039;&#039; hors période d&#039;astreinte&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;syntaxhighlight lang=&amp;quot;csharp&amp;quot; line highlight=&amp;quot;4-7&amp;quot;&amp;gt;&lt;br /&gt;
    public class SetDynamicAstreinte : ScriptBase&amp;lt;SetDynamicAstreinte&amp;gt;&lt;br /&gt;
    {&lt;br /&gt;
        // CONFIGURATION — modifier uniquement ces lignes&lt;br /&gt;
        private const string TARGET_EXT   = &amp;quot;111&amp;quot;;&lt;br /&gt;
        private const string MOBILE_EXT   = &amp;quot;0612345678&amp;quot;;&lt;br /&gt;
        private const string PRENOM_EXT   = &amp;quot;Marcel&amp;quot;;&lt;br /&gt;
        private const string NOM_EXT      = &amp;quot;Patulacci&amp;quot;;&lt;br /&gt;
		 //&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt; || &amp;lt;syntaxhighlight lang=&amp;quot;csharp&amp;quot; line highlight=&amp;quot;4-7&amp;quot;&amp;gt;&lt;br /&gt;
    public class SetDynamicAstreinte : ScriptBase&amp;lt;SetDynamicAstreinte&amp;gt;&lt;br /&gt;
    {&lt;br /&gt;
        // CONFIGURATION — modifier uniquement ces lignes par script&lt;br /&gt;
        private const string TARGET_EXT   = &amp;quot;111&amp;quot;;&lt;br /&gt;
        private const string MOBILE_EXT   = &amp;quot;0699999999&amp;quot;;&lt;br /&gt;
        private const string PRENOM_EXT   = &amp;quot;Jean-Michel&amp;quot;;&lt;br /&gt;
        private const string NOM_EXT      = &amp;quot;Apeuprè&amp;quot;;&lt;br /&gt;
		 // &lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;|| &amp;lt;syntaxhighlight lang=&amp;quot;csharp&amp;quot; line highlight=&amp;quot;4-6&amp;quot;&amp;gt;&lt;br /&gt;
    public class ResetAstreinte : ScriptBase&amp;lt;ResetAstreinte&amp;gt;&lt;br /&gt;
    {&lt;br /&gt;
        // CONFIGURATION — modifier uniquement ces lignes par script&lt;br /&gt;
        private const string TARGET_EXT   = &amp;quot;111&amp;quot;;&lt;br /&gt;
        private const string PRENOM_EXT   = &amp;quot;Accueil&amp;quot;;&lt;br /&gt;
        private const string NOM_EXT      = &amp;quot;Mairie&amp;quot;;&lt;br /&gt;
        // &lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Une fois les 3 scripts produits, passer à l&#039;étape [[Astreinte#Déclaration_du_script|Déclaration du script]] qui va permettre d&#039;affecter un code court à chaque script.&lt;br /&gt;
Exemple : &lt;br /&gt;
* *90 pour hors période d&#039;astreinte&lt;br /&gt;
* *91 pour Jean-Michel&lt;br /&gt;
* *92 pour Marcel&lt;br /&gt;
&lt;br /&gt;
On peut communiquer les codes aux personnes habilitées à gérer le système d&#039;astreinte et aller jusqu&#039;à paramétrer des BLF pour faciliter la vie d&#039;une secrétaire par exemple.&lt;br /&gt;
&lt;br /&gt;
{{Valide|v20}}&lt;br /&gt;
[[Catégorie:3CX]]&lt;/div&gt;</summary>
		<author><name>Anthony</name></author>
	</entry>
	<entry>
		<id>https://indywiki.fr/index.php?title=Astreinte&amp;diff=22264</id>
		<title>Astreinte</title>
		<link rel="alternate" type="text/html" href="https://indywiki.fr/index.php?title=Astreinte&amp;diff=22264"/>
		<updated>2026-04-28T13:05:04Z</updated>

		<summary type="html">&lt;p&gt;Anthony : /* Configuration concrète */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;===Principe===&lt;br /&gt;
On paramètre le statut choisi pour l&#039;astreinte en renvoi vers &#039;&#039;&#039;mon mobile&#039;&#039;&#039;. Un script viendra modifier le statut de l&#039;extension cible ainsi que son numéro de contact mobile, prénom et nom. Ce script déclenchable par l&#039;appel à un code court, paramétrable si on le souhaite sur une BLF. &lt;br /&gt;
===Paramétrage du statut de l&#039;extension vers &#039;&#039;&#039;mon mobile&#039;&#039;&#039;===&lt;br /&gt;
[[Fichier:2026-04-03 13h29 01.png|vignette]]&lt;br /&gt;
#Réglages&lt;br /&gt;
#Transfert d&#039;appels&lt;br /&gt;
#Choisir le statut de l&#039;extension à activer pour enclencher le renvoi vers l&#039;astreinte. Dans l&#039;exemple &#039;&#039;&#039;Absent&#039;&#039;&#039;. Pas l&#039;état &#039;&#039;&#039;Disponible&#039;&#039;&#039; évidemment.&lt;br /&gt;
#Dans &amp;quot;Transférer les appels externes à&amp;quot;, choisir &#039;&#039;&#039;Mon mobile&#039;&#039;&#039;&lt;br /&gt;
#Cocher &#039;&#039;&#039;Rebond&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
===Déclaration du script===&lt;br /&gt;
[[Fichier:2026-04-02 17h11 35.png|vignette]]&lt;br /&gt;
&lt;br /&gt;
Rendez-vous dans :&lt;br /&gt;
&lt;br /&gt;
 Admin / Intégrations / Scripts d&#039;appels / + Ajouter personnalisé&lt;br /&gt;
&lt;br /&gt;
#Donner un nom au traitement de l&#039;appel. Exemple : &#039;&#039;&#039;astreinte_weekend&#039;&#039;&#039;&lt;br /&gt;
#Créer un code de raccourci, ce qui permettra d&#039;exécuter le script simplement en appelant ce code, et in fine par une BLF. Exemple : &#039;&#039;&#039;*99&#039;&#039;&#039;&lt;br /&gt;
#OK&lt;br /&gt;
#Coller dans le champ script le script paramétré ( voir section suivante )&lt;br /&gt;
#Sauvegarder&lt;br /&gt;
#Un message doit indiquer &#039;&#039;&#039;Compilation réussie !&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Le script d&#039;astreinte===&lt;br /&gt;
&lt;br /&gt;
L&#039;éxécution du script va modifier l&#039;extension &#039;&#039;&#039;targetExtNum &#039;&#039;&#039;, il va le basculer sur le statut &#039;&#039;&#039;profileName &#039;&#039;&#039;, modifier son mobile de contact &#039;&#039;&#039;mobileElu &#039;&#039;&#039;, son nom et prénom.&lt;br /&gt;
&lt;br /&gt;
Il faut donc seulement modifier les lignes surlignés dans le code ci-dessous :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;csharp&amp;quot; line highlight=&amp;quot;14-17&amp;quot;&amp;gt;&lt;br /&gt;
using System;&lt;br /&gt;
using System.Threading.Tasks;&lt;br /&gt;
using TCX.Configuration;&lt;br /&gt;
using CallFlow;&lt;br /&gt;
using System.Linq;&lt;br /&gt;
&lt;br /&gt;
namespace dummy&lt;br /&gt;
{&lt;br /&gt;
    public class SetDynamicAstreinte : ScriptBase&amp;lt;SetDynamicAstreinte&amp;gt;&lt;br /&gt;
    {&lt;br /&gt;
        // ============================================================&lt;br /&gt;
        // CONFIGURATION — modifier uniquement ces lignes par script&lt;br /&gt;
        // ============================================================&lt;br /&gt;
        private const string TARGET_EXT   = &amp;quot;111&amp;quot;;&lt;br /&gt;
        private const string MOBILE_EXT   = &amp;quot;0612345678&amp;quot;;&lt;br /&gt;
        private const string PRENOM_EXT   = &amp;quot;Claude&amp;quot;;&lt;br /&gt;
        private const string NOM_EXT      = &amp;quot;IA&amp;quot;;&lt;br /&gt;
		 // ============================================================&lt;br /&gt;
        &lt;br /&gt;
		private const string PROFILE_NAME = &amp;quot;Away&amp;quot;;&lt;br /&gt;
       &lt;br /&gt;
        public override Task&amp;lt;bool&amp;gt; StartAsync()&lt;br /&gt;
        {&lt;br /&gt;
            try&lt;br /&gt;
            {&lt;br /&gt;
                IPhoneSystem ps = PhoneSystem.Root;&lt;br /&gt;
                Extension ext = ps.GetDNByNumber(TARGET_EXT) as Extension;&lt;br /&gt;
                if (ext == null)&lt;br /&gt;
                    return Task.FromResult(false);&lt;br /&gt;
&lt;br /&gt;
                // 1. Nom / Prénom&lt;br /&gt;
                ext.FirstName = PRENOM_EXT;&lt;br /&gt;
                ext.LastName  = NOM_EXT;&lt;br /&gt;
&lt;br /&gt;
                // 2. Numéro mobile&lt;br /&gt;
                ext.SetProperty(&amp;quot;MOBILENUMBER&amp;quot;, MOBILE_EXT);&lt;br /&gt;
&lt;br /&gt;
                // 3. Trouver le profil Away&lt;br /&gt;
                FwdProfile targetProfile = ext.FwdProfiles&lt;br /&gt;
                    .FirstOrDefault(p =&amp;gt; p.Name.Equals(&lt;br /&gt;
                        PROFILE_NAME, StringComparison.OrdinalIgnoreCase));&lt;br /&gt;
&lt;br /&gt;
                if (targetProfile != null)&lt;br /&gt;
                {&lt;br /&gt;
                    // AwayRoute, Internal, External sont read-only&lt;br /&gt;
                    // mais ce sont des références : on peut modifier&lt;br /&gt;
                    // leurs membres si ceux-ci sont accessibles en écriture&lt;br /&gt;
                    AwayRouting route = targetProfile.AwayRoute;&lt;br /&gt;
&lt;br /&gt;
                    // Capturer les HoursDestination comme variables locales&lt;br /&gt;
                    // (objets référence — la propriété est read-only,&lt;br /&gt;
                    //  mais l&#039;objet pointé est modifiable)&lt;br /&gt;
                    HoursDestination internalHours = route.Internal;&lt;br /&gt;
                    HoursDestination externalHours = route.External;&lt;br /&gt;
&lt;br /&gt;
                    // Capturer AllHours (struct) → modifier → réassigner&lt;br /&gt;
                    DestinationStruct destInternal = internalHours.AllHours;&lt;br /&gt;
                    destInternal.To               = DestinationType.Boomerang;&lt;br /&gt;
                    destInternal.External         = MOBILE_EXT;&lt;br /&gt;
                    internalHours.AllHours        = destInternal;&lt;br /&gt;
&lt;br /&gt;
                    DestinationStruct destExternal = externalHours.AllHours;&lt;br /&gt;
                    destExternal.To               = DestinationType.Boomerang;&lt;br /&gt;
                    destExternal.External         = MOBILE_EXT;&lt;br /&gt;
                    externalHours.AllHours        = destExternal;&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                // 4. Sauvegarder&lt;br /&gt;
                ext.Save();&lt;br /&gt;
&lt;br /&gt;
                // 5. Recharger et basculer le profil&lt;br /&gt;
                ext = ps.GetDNByNumber(TARGET_EXT) as Extension;&lt;br /&gt;
                if (ext == null)&lt;br /&gt;
                    return Task.FromResult(false);&lt;br /&gt;
&lt;br /&gt;
                FwdProfile profile = ext.FwdProfiles&lt;br /&gt;
                    .FirstOrDefault(p =&amp;gt; p.Name.Equals(&lt;br /&gt;
                        PROFILE_NAME, StringComparison.OrdinalIgnoreCase));&lt;br /&gt;
&lt;br /&gt;
                if (profile != null)&lt;br /&gt;
                {&lt;br /&gt;
                    ext.CurrentProfile = profile;&lt;br /&gt;
                    ext.Save();&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                return Task.FromResult(true);&lt;br /&gt;
            }&lt;br /&gt;
            catch (Exception)&lt;br /&gt;
            {&lt;br /&gt;
                return Task.FromResult(false);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Le script de retour à la normale===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;csharp&amp;quot; line highlight=&amp;quot;14-16&amp;quot;&amp;gt;&lt;br /&gt;
using System;&lt;br /&gt;
using System.Threading.Tasks;&lt;br /&gt;
using TCX.Configuration;&lt;br /&gt;
using CallFlow;&lt;br /&gt;
using System.Linq;&lt;br /&gt;
&lt;br /&gt;
namespace dummy&lt;br /&gt;
{&lt;br /&gt;
    public class ResetAstreinte : ScriptBase&amp;lt;ResetAstreinte&amp;gt;&lt;br /&gt;
    {&lt;br /&gt;
        // ============================================================&lt;br /&gt;
        // CONFIGURATION — modifier uniquement ces lignes par script&lt;br /&gt;
        // ============================================================&lt;br /&gt;
        private const string TARGET_EXT   = &amp;quot;111&amp;quot;;&lt;br /&gt;
        private const string PRENOM_EXT   = &amp;quot;Accueil&amp;quot;;&lt;br /&gt;
        private const string NOM_EXT      = &amp;quot;Mairie&amp;quot;;&lt;br /&gt;
        // ============================================================&lt;br /&gt;
&lt;br /&gt;
        public override Task&amp;lt;bool&amp;gt; StartAsync()&lt;br /&gt;
        {&lt;br /&gt;
            try&lt;br /&gt;
            {&lt;br /&gt;
                IPhoneSystem ps = PhoneSystem.Root;&lt;br /&gt;
                Extension ext = ps.GetDNByNumber(TARGET_EXT) as Extension;&lt;br /&gt;
                if (ext == null)&lt;br /&gt;
                    return Task.FromResult(false);&lt;br /&gt;
&lt;br /&gt;
                // 1. Remettre le nom générique&lt;br /&gt;
                ext.FirstName = PRENOM_EXT;&lt;br /&gt;
                ext.LastName  = NOM_EXT;&lt;br /&gt;
&lt;br /&gt;
                // 2. Vider le numéro mobile&lt;br /&gt;
                ext.SetProperty(&amp;quot;MOBILENUMBER&amp;quot;, &amp;quot;&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
                // 3. Résoudre le DN pour la messagerie vocale&lt;br /&gt;
                DN targetDN = ps.GetDNByNumber(TARGET_EXT);&lt;br /&gt;
&lt;br /&gt;
                // 4. Remettre AwayRoute → messagerie vocale&lt;br /&gt;
                FwdProfile awayProfile = ext.FwdProfiles&lt;br /&gt;
                    .FirstOrDefault(p =&amp;gt; p.Name.Equals(&lt;br /&gt;
                        &amp;quot;Away&amp;quot;, StringComparison.OrdinalIgnoreCase));&lt;br /&gt;
&lt;br /&gt;
                if (awayProfile != null)&lt;br /&gt;
                {&lt;br /&gt;
                    AwayRouting route = awayProfile.AwayRoute;&lt;br /&gt;
&lt;br /&gt;
                    HoursDestination internalHours = route.Internal;&lt;br /&gt;
                    HoursDestination externalHours = route.External;&lt;br /&gt;
&lt;br /&gt;
                    DestinationStruct destInternal = internalHours.AllHours;&lt;br /&gt;
                    destInternal.To               = DestinationType.VoiceMail;&lt;br /&gt;
                    destInternal.Internal         = targetDN;&lt;br /&gt;
                    destInternal.External         = &amp;quot;&amp;quot;;&lt;br /&gt;
                    internalHours.AllHours        = destInternal;&lt;br /&gt;
&lt;br /&gt;
                    DestinationStruct destExternal = externalHours.AllHours;&lt;br /&gt;
                    destExternal.To               = DestinationType.VoiceMail;&lt;br /&gt;
                    destExternal.Internal         = targetDN;&lt;br /&gt;
                    destExternal.External         = &amp;quot;&amp;quot;;&lt;br /&gt;
                    externalHours.AllHours        = destExternal;&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                // 5. Sauvegarder&lt;br /&gt;
                ext.Save();&lt;br /&gt;
&lt;br /&gt;
                // 6. Recharger et basculer vers Available&lt;br /&gt;
                ext = ps.GetDNByNumber(TARGET_EXT) as Extension;&lt;br /&gt;
                if (ext == null)&lt;br /&gt;
                    return Task.FromResult(false);&lt;br /&gt;
&lt;br /&gt;
                FwdProfile profile = ext.FwdProfiles&lt;br /&gt;
                    .FirstOrDefault(p =&amp;gt; p.Name.Equals(&lt;br /&gt;
                        &amp;quot;Available&amp;quot;, StringComparison.OrdinalIgnoreCase));&lt;br /&gt;
&lt;br /&gt;
                if (profile != null)&lt;br /&gt;
                {&lt;br /&gt;
                    ext.CurrentProfile = profile;&lt;br /&gt;
                    ext.Save();&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                return Task.FromResult(true);&lt;br /&gt;
            }&lt;br /&gt;
            catch (Exception)&lt;br /&gt;
            {&lt;br /&gt;
                return Task.FromResult(false);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Table de correspondance des profileName====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Dans 3CX!! Dans le script&lt;br /&gt;
|-&lt;br /&gt;
| Disponible|| Available&lt;br /&gt;
|-&lt;br /&gt;
| Absent|| Away&lt;br /&gt;
|-&lt;br /&gt;
| Ne pas déranger|| Out of office&lt;br /&gt;
|-&lt;br /&gt;
| Custom 1|| Custom 1&lt;br /&gt;
|-&lt;br /&gt;
| Custom 2|| Custom 2&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===Configuration concrète===&lt;br /&gt;
&lt;br /&gt;
On a besoin de gérer deux astreintes. Le poste Accueil reçoit les appels en temps normal&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Texte de la légende&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;Marcel Patulacci&#039;&#039;&#039; || &#039;&#039;&#039;Jean-Michel Apeuprè&#039;&#039;&#039;|| &#039;&#039;&#039;Poste accueil &#039;&#039;&#039; hors période d&#039;astreinte&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;syntaxhighlight lang=&amp;quot;csharp&amp;quot; line highlight=&amp;quot;4-7&amp;quot;&amp;gt;&lt;br /&gt;
    public class SetDynamicAstreinte : ScriptBase&amp;lt;SetDynamicAstreinte&amp;gt;&lt;br /&gt;
    {&lt;br /&gt;
        // CONFIGURATION — modifier uniquement ces lignes&lt;br /&gt;
        private const string TARGET_EXT   = &amp;quot;111&amp;quot;;&lt;br /&gt;
        private const string MOBILE_EXT   = &amp;quot;0612345678&amp;quot;;&lt;br /&gt;
        private const string PRENOM_EXT   = &amp;quot;Marcel&amp;quot;;&lt;br /&gt;
        private const string NOM_EXT      = &amp;quot;Patulacci&amp;quot;;&lt;br /&gt;
		 //&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt; || &amp;lt;syntaxhighlight lang=&amp;quot;csharp&amp;quot; line highlight=&amp;quot;4-7&amp;quot;&amp;gt;&lt;br /&gt;
    public class SetDynamicAstreinte : ScriptBase&amp;lt;SetDynamicAstreinte&amp;gt;&lt;br /&gt;
    {&lt;br /&gt;
        // CONFIGURATION — modifier uniquement ces lignes par script&lt;br /&gt;
        private const string TARGET_EXT   = &amp;quot;111&amp;quot;;&lt;br /&gt;
        private const string MOBILE_EXT   = &amp;quot;0699999999&amp;quot;;&lt;br /&gt;
        private const string PRENOM_EXT   = &amp;quot;Jean-Michel&amp;quot;;&lt;br /&gt;
        private const string NOM_EXT      = &amp;quot;Apeuprè&amp;quot;;&lt;br /&gt;
		 // &lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;|| &amp;lt;syntaxhighlight lang=&amp;quot;csharp&amp;quot; line highlight=&amp;quot;4-6&amp;quot;&amp;gt;&lt;br /&gt;
    public class ResetAstreinte : ScriptBase&amp;lt;ResetAstreinte&amp;gt;&lt;br /&gt;
    {&lt;br /&gt;
        // CONFIGURATION — modifier uniquement ces lignes par script&lt;br /&gt;
        private const string TARGET_EXT   = &amp;quot;111&amp;quot;;&lt;br /&gt;
        private const string PRENOM_EXT   = &amp;quot;Accueil&amp;quot;;&lt;br /&gt;
        private const string NOM_EXT      = &amp;quot;Mairie&amp;quot;;&lt;br /&gt;
        // &lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Une fois les 3 scripts produits, passer à l&#039;étape [[Astreinte#Déclaration_du_script|Déclaration du script]] qui va permettre d&#039;affecter un code court à chaque script.&lt;br /&gt;
Exemple : &lt;br /&gt;
* *90 pour hors période d&#039;astreinte&lt;br /&gt;
* *91 pour Jean-Michel&lt;br /&gt;
* *92 pour Marcel&lt;br /&gt;
&lt;br /&gt;
On peut communiquer les codes aux personnes habilitées à gérer le système d&#039;astreinte et aller jusqu&#039;à paramétrer des BLF pour faciliter la vie d&#039;une secrétaire par exemple.&lt;br /&gt;
&lt;br /&gt;
{{Valide|v20}}&lt;br /&gt;
[[Catégorie:3CX]]&lt;/div&gt;</summary>
		<author><name>Anthony</name></author>
	</entry>
	<entry>
		<id>https://indywiki.fr/index.php?title=Astreinte&amp;diff=22263</id>
		<title>Astreinte</title>
		<link rel="alternate" type="text/html" href="https://indywiki.fr/index.php?title=Astreinte&amp;diff=22263"/>
		<updated>2026-04-28T13:04:22Z</updated>

		<summary type="html">&lt;p&gt;Anthony : /* Configuration concrète */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;===Principe===&lt;br /&gt;
On paramètre le statut choisi pour l&#039;astreinte en renvoi vers &#039;&#039;&#039;mon mobile&#039;&#039;&#039;. Un script viendra modifier le statut de l&#039;extension cible ainsi que son numéro de contact mobile, prénom et nom. Ce script déclenchable par l&#039;appel à un code court, paramétrable si on le souhaite sur une BLF. &lt;br /&gt;
===Paramétrage du statut de l&#039;extension vers &#039;&#039;&#039;mon mobile&#039;&#039;&#039;===&lt;br /&gt;
[[Fichier:2026-04-03 13h29 01.png|vignette]]&lt;br /&gt;
#Réglages&lt;br /&gt;
#Transfert d&#039;appels&lt;br /&gt;
#Choisir le statut de l&#039;extension à activer pour enclencher le renvoi vers l&#039;astreinte. Dans l&#039;exemple &#039;&#039;&#039;Absent&#039;&#039;&#039;. Pas l&#039;état &#039;&#039;&#039;Disponible&#039;&#039;&#039; évidemment.&lt;br /&gt;
#Dans &amp;quot;Transférer les appels externes à&amp;quot;, choisir &#039;&#039;&#039;Mon mobile&#039;&#039;&#039;&lt;br /&gt;
#Cocher &#039;&#039;&#039;Rebond&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
===Déclaration du script===&lt;br /&gt;
[[Fichier:2026-04-02 17h11 35.png|vignette]]&lt;br /&gt;
&lt;br /&gt;
Rendez-vous dans :&lt;br /&gt;
&lt;br /&gt;
 Admin / Intégrations / Scripts d&#039;appels / + Ajouter personnalisé&lt;br /&gt;
&lt;br /&gt;
#Donner un nom au traitement de l&#039;appel. Exemple : &#039;&#039;&#039;astreinte_weekend&#039;&#039;&#039;&lt;br /&gt;
#Créer un code de raccourci, ce qui permettra d&#039;exécuter le script simplement en appelant ce code, et in fine par une BLF. Exemple : &#039;&#039;&#039;*99&#039;&#039;&#039;&lt;br /&gt;
#OK&lt;br /&gt;
#Coller dans le champ script le script paramétré ( voir section suivante )&lt;br /&gt;
#Sauvegarder&lt;br /&gt;
#Un message doit indiquer &#039;&#039;&#039;Compilation réussie !&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Le script d&#039;astreinte===&lt;br /&gt;
&lt;br /&gt;
L&#039;éxécution du script va modifier l&#039;extension &#039;&#039;&#039;targetExtNum &#039;&#039;&#039;, il va le basculer sur le statut &#039;&#039;&#039;profileName &#039;&#039;&#039;, modifier son mobile de contact &#039;&#039;&#039;mobileElu &#039;&#039;&#039;, son nom et prénom.&lt;br /&gt;
&lt;br /&gt;
Il faut donc seulement modifier les lignes surlignés dans le code ci-dessous :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;csharp&amp;quot; line highlight=&amp;quot;14-17&amp;quot;&amp;gt;&lt;br /&gt;
using System;&lt;br /&gt;
using System.Threading.Tasks;&lt;br /&gt;
using TCX.Configuration;&lt;br /&gt;
using CallFlow;&lt;br /&gt;
using System.Linq;&lt;br /&gt;
&lt;br /&gt;
namespace dummy&lt;br /&gt;
{&lt;br /&gt;
    public class SetDynamicAstreinte : ScriptBase&amp;lt;SetDynamicAstreinte&amp;gt;&lt;br /&gt;
    {&lt;br /&gt;
        // ============================================================&lt;br /&gt;
        // CONFIGURATION — modifier uniquement ces lignes par script&lt;br /&gt;
        // ============================================================&lt;br /&gt;
        private const string TARGET_EXT   = &amp;quot;111&amp;quot;;&lt;br /&gt;
        private const string MOBILE_EXT   = &amp;quot;0612345678&amp;quot;;&lt;br /&gt;
        private const string PRENOM_EXT   = &amp;quot;Claude&amp;quot;;&lt;br /&gt;
        private const string NOM_EXT      = &amp;quot;IA&amp;quot;;&lt;br /&gt;
		 // ============================================================&lt;br /&gt;
        &lt;br /&gt;
		private const string PROFILE_NAME = &amp;quot;Away&amp;quot;;&lt;br /&gt;
       &lt;br /&gt;
        public override Task&amp;lt;bool&amp;gt; StartAsync()&lt;br /&gt;
        {&lt;br /&gt;
            try&lt;br /&gt;
            {&lt;br /&gt;
                IPhoneSystem ps = PhoneSystem.Root;&lt;br /&gt;
                Extension ext = ps.GetDNByNumber(TARGET_EXT) as Extension;&lt;br /&gt;
                if (ext == null)&lt;br /&gt;
                    return Task.FromResult(false);&lt;br /&gt;
&lt;br /&gt;
                // 1. Nom / Prénom&lt;br /&gt;
                ext.FirstName = PRENOM_EXT;&lt;br /&gt;
                ext.LastName  = NOM_EXT;&lt;br /&gt;
&lt;br /&gt;
                // 2. Numéro mobile&lt;br /&gt;
                ext.SetProperty(&amp;quot;MOBILENUMBER&amp;quot;, MOBILE_EXT);&lt;br /&gt;
&lt;br /&gt;
                // 3. Trouver le profil Away&lt;br /&gt;
                FwdProfile targetProfile = ext.FwdProfiles&lt;br /&gt;
                    .FirstOrDefault(p =&amp;gt; p.Name.Equals(&lt;br /&gt;
                        PROFILE_NAME, StringComparison.OrdinalIgnoreCase));&lt;br /&gt;
&lt;br /&gt;
                if (targetProfile != null)&lt;br /&gt;
                {&lt;br /&gt;
                    // AwayRoute, Internal, External sont read-only&lt;br /&gt;
                    // mais ce sont des références : on peut modifier&lt;br /&gt;
                    // leurs membres si ceux-ci sont accessibles en écriture&lt;br /&gt;
                    AwayRouting route = targetProfile.AwayRoute;&lt;br /&gt;
&lt;br /&gt;
                    // Capturer les HoursDestination comme variables locales&lt;br /&gt;
                    // (objets référence — la propriété est read-only,&lt;br /&gt;
                    //  mais l&#039;objet pointé est modifiable)&lt;br /&gt;
                    HoursDestination internalHours = route.Internal;&lt;br /&gt;
                    HoursDestination externalHours = route.External;&lt;br /&gt;
&lt;br /&gt;
                    // Capturer AllHours (struct) → modifier → réassigner&lt;br /&gt;
                    DestinationStruct destInternal = internalHours.AllHours;&lt;br /&gt;
                    destInternal.To               = DestinationType.Boomerang;&lt;br /&gt;
                    destInternal.External         = MOBILE_EXT;&lt;br /&gt;
                    internalHours.AllHours        = destInternal;&lt;br /&gt;
&lt;br /&gt;
                    DestinationStruct destExternal = externalHours.AllHours;&lt;br /&gt;
                    destExternal.To               = DestinationType.Boomerang;&lt;br /&gt;
                    destExternal.External         = MOBILE_EXT;&lt;br /&gt;
                    externalHours.AllHours        = destExternal;&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                // 4. Sauvegarder&lt;br /&gt;
                ext.Save();&lt;br /&gt;
&lt;br /&gt;
                // 5. Recharger et basculer le profil&lt;br /&gt;
                ext = ps.GetDNByNumber(TARGET_EXT) as Extension;&lt;br /&gt;
                if (ext == null)&lt;br /&gt;
                    return Task.FromResult(false);&lt;br /&gt;
&lt;br /&gt;
                FwdProfile profile = ext.FwdProfiles&lt;br /&gt;
                    .FirstOrDefault(p =&amp;gt; p.Name.Equals(&lt;br /&gt;
                        PROFILE_NAME, StringComparison.OrdinalIgnoreCase));&lt;br /&gt;
&lt;br /&gt;
                if (profile != null)&lt;br /&gt;
                {&lt;br /&gt;
                    ext.CurrentProfile = profile;&lt;br /&gt;
                    ext.Save();&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                return Task.FromResult(true);&lt;br /&gt;
            }&lt;br /&gt;
            catch (Exception)&lt;br /&gt;
            {&lt;br /&gt;
                return Task.FromResult(false);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Le script de retour à la normale===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;csharp&amp;quot; line highlight=&amp;quot;14-16&amp;quot;&amp;gt;&lt;br /&gt;
using System;&lt;br /&gt;
using System.Threading.Tasks;&lt;br /&gt;
using TCX.Configuration;&lt;br /&gt;
using CallFlow;&lt;br /&gt;
using System.Linq;&lt;br /&gt;
&lt;br /&gt;
namespace dummy&lt;br /&gt;
{&lt;br /&gt;
    public class ResetAstreinte : ScriptBase&amp;lt;ResetAstreinte&amp;gt;&lt;br /&gt;
    {&lt;br /&gt;
        // ============================================================&lt;br /&gt;
        // CONFIGURATION — modifier uniquement ces lignes par script&lt;br /&gt;
        // ============================================================&lt;br /&gt;
        private const string TARGET_EXT   = &amp;quot;111&amp;quot;;&lt;br /&gt;
        private const string PRENOM_EXT   = &amp;quot;Accueil&amp;quot;;&lt;br /&gt;
        private const string NOM_EXT      = &amp;quot;Mairie&amp;quot;;&lt;br /&gt;
        // ============================================================&lt;br /&gt;
&lt;br /&gt;
        public override Task&amp;lt;bool&amp;gt; StartAsync()&lt;br /&gt;
        {&lt;br /&gt;
            try&lt;br /&gt;
            {&lt;br /&gt;
                IPhoneSystem ps = PhoneSystem.Root;&lt;br /&gt;
                Extension ext = ps.GetDNByNumber(TARGET_EXT) as Extension;&lt;br /&gt;
                if (ext == null)&lt;br /&gt;
                    return Task.FromResult(false);&lt;br /&gt;
&lt;br /&gt;
                // 1. Remettre le nom générique&lt;br /&gt;
                ext.FirstName = PRENOM_EXT;&lt;br /&gt;
                ext.LastName  = NOM_EXT;&lt;br /&gt;
&lt;br /&gt;
                // 2. Vider le numéro mobile&lt;br /&gt;
                ext.SetProperty(&amp;quot;MOBILENUMBER&amp;quot;, &amp;quot;&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
                // 3. Résoudre le DN pour la messagerie vocale&lt;br /&gt;
                DN targetDN = ps.GetDNByNumber(TARGET_EXT);&lt;br /&gt;
&lt;br /&gt;
                // 4. Remettre AwayRoute → messagerie vocale&lt;br /&gt;
                FwdProfile awayProfile = ext.FwdProfiles&lt;br /&gt;
                    .FirstOrDefault(p =&amp;gt; p.Name.Equals(&lt;br /&gt;
                        &amp;quot;Away&amp;quot;, StringComparison.OrdinalIgnoreCase));&lt;br /&gt;
&lt;br /&gt;
                if (awayProfile != null)&lt;br /&gt;
                {&lt;br /&gt;
                    AwayRouting route = awayProfile.AwayRoute;&lt;br /&gt;
&lt;br /&gt;
                    HoursDestination internalHours = route.Internal;&lt;br /&gt;
                    HoursDestination externalHours = route.External;&lt;br /&gt;
&lt;br /&gt;
                    DestinationStruct destInternal = internalHours.AllHours;&lt;br /&gt;
                    destInternal.To               = DestinationType.VoiceMail;&lt;br /&gt;
                    destInternal.Internal         = targetDN;&lt;br /&gt;
                    destInternal.External         = &amp;quot;&amp;quot;;&lt;br /&gt;
                    internalHours.AllHours        = destInternal;&lt;br /&gt;
&lt;br /&gt;
                    DestinationStruct destExternal = externalHours.AllHours;&lt;br /&gt;
                    destExternal.To               = DestinationType.VoiceMail;&lt;br /&gt;
                    destExternal.Internal         = targetDN;&lt;br /&gt;
                    destExternal.External         = &amp;quot;&amp;quot;;&lt;br /&gt;
                    externalHours.AllHours        = destExternal;&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                // 5. Sauvegarder&lt;br /&gt;
                ext.Save();&lt;br /&gt;
&lt;br /&gt;
                // 6. Recharger et basculer vers Available&lt;br /&gt;
                ext = ps.GetDNByNumber(TARGET_EXT) as Extension;&lt;br /&gt;
                if (ext == null)&lt;br /&gt;
                    return Task.FromResult(false);&lt;br /&gt;
&lt;br /&gt;
                FwdProfile profile = ext.FwdProfiles&lt;br /&gt;
                    .FirstOrDefault(p =&amp;gt; p.Name.Equals(&lt;br /&gt;
                        &amp;quot;Available&amp;quot;, StringComparison.OrdinalIgnoreCase));&lt;br /&gt;
&lt;br /&gt;
                if (profile != null)&lt;br /&gt;
                {&lt;br /&gt;
                    ext.CurrentProfile = profile;&lt;br /&gt;
                    ext.Save();&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                return Task.FromResult(true);&lt;br /&gt;
            }&lt;br /&gt;
            catch (Exception)&lt;br /&gt;
            {&lt;br /&gt;
                return Task.FromResult(false);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Table de correspondance des profileName====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Dans 3CX!! Dans le script&lt;br /&gt;
|-&lt;br /&gt;
| Disponible|| Available&lt;br /&gt;
|-&lt;br /&gt;
| Absent|| Away&lt;br /&gt;
|-&lt;br /&gt;
| Ne pas déranger|| Out of office&lt;br /&gt;
|-&lt;br /&gt;
| Custom 1|| Custom 1&lt;br /&gt;
|-&lt;br /&gt;
| Custom 2|| Custom 2&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===Configuration concrète===&lt;br /&gt;
&lt;br /&gt;
On a besoin de gérer deux astreintes. Le poste Accueil reçoit les appels en temps normal&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Texte de la légende&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;Marcel Patulacci&#039;&#039;&#039; || &#039;&#039;&#039;Jean-Michel Apeuprè&#039;&#039;&#039;|| &#039;&#039;&#039;Poste accueil &#039;&#039;&#039; hors période d&#039;astreinte&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;syntaxhighlight lang=&amp;quot;csharp&amp;quot; line highlight=&amp;quot;4-7&amp;quot;&amp;gt;&lt;br /&gt;
    public class SetDynamicAstreinte : ScriptBase&amp;lt;SetDynamicAstreinte&amp;gt;&lt;br /&gt;
    {&lt;br /&gt;
        // CONFIGURATION — modifier uniquement ces lignes&lt;br /&gt;
        private const string TARGET_EXT   = &amp;quot;111&amp;quot;;&lt;br /&gt;
        private const string MOBILE_EXT   = &amp;quot;0612345678&amp;quot;;&lt;br /&gt;
        private const string PRENOM_EXT   = &amp;quot;Marcel&amp;quot;;&lt;br /&gt;
        private const string NOM_EXT      = &amp;quot;Patulacci&amp;quot;;&lt;br /&gt;
		 //&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt; || &amp;lt;syntaxhighlight lang=&amp;quot;csharp&amp;quot; line highlight=&amp;quot;4-7&amp;quot;&amp;gt;&lt;br /&gt;
    public class SetDynamicAstreinte : ScriptBase&amp;lt;SetDynamicAstreinte&amp;gt;&lt;br /&gt;
    {&lt;br /&gt;
        // CONFIGURATION — modifier uniquement ces lignes par script&lt;br /&gt;
        private const string TARGET_EXT   = &amp;quot;111&amp;quot;;&lt;br /&gt;
        private const string MOBILE_EXT   = &amp;quot;0699999999&amp;quot;;&lt;br /&gt;
        private const string PRENOM_EXT   = &amp;quot;Jean-Michel&amp;quot;;&lt;br /&gt;
        private const string NOM_EXT      = &amp;quot;Apeuprè&amp;quot;;&lt;br /&gt;
		 // &lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;|| &amp;lt;syntaxhighlight lang=&amp;quot;csharp&amp;quot; line highlight=&amp;quot;4-6&amp;quot;&amp;gt;&lt;br /&gt;
    public class ResetAstreinte : ScriptBase&amp;lt;ResetAstreinte&amp;gt;&lt;br /&gt;
    {&lt;br /&gt;
        // CONFIGURATION — modifier uniquement ces lignes par script&lt;br /&gt;
        private const string TARGET_EXT   = &amp;quot;111&amp;quot;;&lt;br /&gt;
        private const string PRENOM_EXT   = &amp;quot;Accueil&amp;quot;;&lt;br /&gt;
        private const string NOM_EXT      = &amp;quot;Mairie&amp;quot;;&lt;br /&gt;
        // ============================================================&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Une fois les 3 scripts produits, passer à l&#039;étape [[Astreinte#Déclaration_du_script|Déclaration du script]] qui va permettre d&#039;affecter un code court à chaque script.&lt;br /&gt;
Exemple : &lt;br /&gt;
* *90 pour hors période d&#039;astreinte&lt;br /&gt;
* *91 pour Jean-Michel&lt;br /&gt;
* *92 pour Marcel&lt;br /&gt;
&lt;br /&gt;
On peut communiquer les codes aux personnes habilitées à gérer le système d&#039;astreinte et aller jusqu&#039;à paramétrer des BLF pour faciliter la vie d&#039;une secrétaire par exemple.&lt;br /&gt;
&lt;br /&gt;
{{Valide|v20}}&lt;br /&gt;
[[Catégorie:3CX]]&lt;/div&gt;</summary>
		<author><name>Anthony</name></author>
	</entry>
	<entry>
		<id>https://indywiki.fr/index.php?title=Astreinte&amp;diff=22262</id>
		<title>Astreinte</title>
		<link rel="alternate" type="text/html" href="https://indywiki.fr/index.php?title=Astreinte&amp;diff=22262"/>
		<updated>2026-04-28T12:59:49Z</updated>

		<summary type="html">&lt;p&gt;Anthony : /* Configuration concrète */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;===Principe===&lt;br /&gt;
On paramètre le statut choisi pour l&#039;astreinte en renvoi vers &#039;&#039;&#039;mon mobile&#039;&#039;&#039;. Un script viendra modifier le statut de l&#039;extension cible ainsi que son numéro de contact mobile, prénom et nom. Ce script déclenchable par l&#039;appel à un code court, paramétrable si on le souhaite sur une BLF. &lt;br /&gt;
===Paramétrage du statut de l&#039;extension vers &#039;&#039;&#039;mon mobile&#039;&#039;&#039;===&lt;br /&gt;
[[Fichier:2026-04-03 13h29 01.png|vignette]]&lt;br /&gt;
#Réglages&lt;br /&gt;
#Transfert d&#039;appels&lt;br /&gt;
#Choisir le statut de l&#039;extension à activer pour enclencher le renvoi vers l&#039;astreinte. Dans l&#039;exemple &#039;&#039;&#039;Absent&#039;&#039;&#039;. Pas l&#039;état &#039;&#039;&#039;Disponible&#039;&#039;&#039; évidemment.&lt;br /&gt;
#Dans &amp;quot;Transférer les appels externes à&amp;quot;, choisir &#039;&#039;&#039;Mon mobile&#039;&#039;&#039;&lt;br /&gt;
#Cocher &#039;&#039;&#039;Rebond&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
===Déclaration du script===&lt;br /&gt;
[[Fichier:2026-04-02 17h11 35.png|vignette]]&lt;br /&gt;
&lt;br /&gt;
Rendez-vous dans :&lt;br /&gt;
&lt;br /&gt;
 Admin / Intégrations / Scripts d&#039;appels / + Ajouter personnalisé&lt;br /&gt;
&lt;br /&gt;
#Donner un nom au traitement de l&#039;appel. Exemple : &#039;&#039;&#039;astreinte_weekend&#039;&#039;&#039;&lt;br /&gt;
#Créer un code de raccourci, ce qui permettra d&#039;exécuter le script simplement en appelant ce code, et in fine par une BLF. Exemple : &#039;&#039;&#039;*99&#039;&#039;&#039;&lt;br /&gt;
#OK&lt;br /&gt;
#Coller dans le champ script le script paramétré ( voir section suivante )&lt;br /&gt;
#Sauvegarder&lt;br /&gt;
#Un message doit indiquer &#039;&#039;&#039;Compilation réussie !&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Le script d&#039;astreinte===&lt;br /&gt;
&lt;br /&gt;
L&#039;éxécution du script va modifier l&#039;extension &#039;&#039;&#039;targetExtNum &#039;&#039;&#039;, il va le basculer sur le statut &#039;&#039;&#039;profileName &#039;&#039;&#039;, modifier son mobile de contact &#039;&#039;&#039;mobileElu &#039;&#039;&#039;, son nom et prénom.&lt;br /&gt;
&lt;br /&gt;
Il faut donc seulement modifier les lignes surlignés dans le code ci-dessous :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;csharp&amp;quot; line highlight=&amp;quot;14-17&amp;quot;&amp;gt;&lt;br /&gt;
using System;&lt;br /&gt;
using System.Threading.Tasks;&lt;br /&gt;
using TCX.Configuration;&lt;br /&gt;
using CallFlow;&lt;br /&gt;
using System.Linq;&lt;br /&gt;
&lt;br /&gt;
namespace dummy&lt;br /&gt;
{&lt;br /&gt;
    public class SetDynamicAstreinte : ScriptBase&amp;lt;SetDynamicAstreinte&amp;gt;&lt;br /&gt;
    {&lt;br /&gt;
        // ============================================================&lt;br /&gt;
        // CONFIGURATION — modifier uniquement ces lignes par script&lt;br /&gt;
        // ============================================================&lt;br /&gt;
        private const string TARGET_EXT   = &amp;quot;111&amp;quot;;&lt;br /&gt;
        private const string MOBILE_EXT   = &amp;quot;0612345678&amp;quot;;&lt;br /&gt;
        private const string PRENOM_EXT   = &amp;quot;Claude&amp;quot;;&lt;br /&gt;
        private const string NOM_EXT      = &amp;quot;IA&amp;quot;;&lt;br /&gt;
		 // ============================================================&lt;br /&gt;
        &lt;br /&gt;
		private const string PROFILE_NAME = &amp;quot;Away&amp;quot;;&lt;br /&gt;
       &lt;br /&gt;
        public override Task&amp;lt;bool&amp;gt; StartAsync()&lt;br /&gt;
        {&lt;br /&gt;
            try&lt;br /&gt;
            {&lt;br /&gt;
                IPhoneSystem ps = PhoneSystem.Root;&lt;br /&gt;
                Extension ext = ps.GetDNByNumber(TARGET_EXT) as Extension;&lt;br /&gt;
                if (ext == null)&lt;br /&gt;
                    return Task.FromResult(false);&lt;br /&gt;
&lt;br /&gt;
                // 1. Nom / Prénom&lt;br /&gt;
                ext.FirstName = PRENOM_EXT;&lt;br /&gt;
                ext.LastName  = NOM_EXT;&lt;br /&gt;
&lt;br /&gt;
                // 2. Numéro mobile&lt;br /&gt;
                ext.SetProperty(&amp;quot;MOBILENUMBER&amp;quot;, MOBILE_EXT);&lt;br /&gt;
&lt;br /&gt;
                // 3. Trouver le profil Away&lt;br /&gt;
                FwdProfile targetProfile = ext.FwdProfiles&lt;br /&gt;
                    .FirstOrDefault(p =&amp;gt; p.Name.Equals(&lt;br /&gt;
                        PROFILE_NAME, StringComparison.OrdinalIgnoreCase));&lt;br /&gt;
&lt;br /&gt;
                if (targetProfile != null)&lt;br /&gt;
                {&lt;br /&gt;
                    // AwayRoute, Internal, External sont read-only&lt;br /&gt;
                    // mais ce sont des références : on peut modifier&lt;br /&gt;
                    // leurs membres si ceux-ci sont accessibles en écriture&lt;br /&gt;
                    AwayRouting route = targetProfile.AwayRoute;&lt;br /&gt;
&lt;br /&gt;
                    // Capturer les HoursDestination comme variables locales&lt;br /&gt;
                    // (objets référence — la propriété est read-only,&lt;br /&gt;
                    //  mais l&#039;objet pointé est modifiable)&lt;br /&gt;
                    HoursDestination internalHours = route.Internal;&lt;br /&gt;
                    HoursDestination externalHours = route.External;&lt;br /&gt;
&lt;br /&gt;
                    // Capturer AllHours (struct) → modifier → réassigner&lt;br /&gt;
                    DestinationStruct destInternal = internalHours.AllHours;&lt;br /&gt;
                    destInternal.To               = DestinationType.Boomerang;&lt;br /&gt;
                    destInternal.External         = MOBILE_EXT;&lt;br /&gt;
                    internalHours.AllHours        = destInternal;&lt;br /&gt;
&lt;br /&gt;
                    DestinationStruct destExternal = externalHours.AllHours;&lt;br /&gt;
                    destExternal.To               = DestinationType.Boomerang;&lt;br /&gt;
                    destExternal.External         = MOBILE_EXT;&lt;br /&gt;
                    externalHours.AllHours        = destExternal;&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                // 4. Sauvegarder&lt;br /&gt;
                ext.Save();&lt;br /&gt;
&lt;br /&gt;
                // 5. Recharger et basculer le profil&lt;br /&gt;
                ext = ps.GetDNByNumber(TARGET_EXT) as Extension;&lt;br /&gt;
                if (ext == null)&lt;br /&gt;
                    return Task.FromResult(false);&lt;br /&gt;
&lt;br /&gt;
                FwdProfile profile = ext.FwdProfiles&lt;br /&gt;
                    .FirstOrDefault(p =&amp;gt; p.Name.Equals(&lt;br /&gt;
                        PROFILE_NAME, StringComparison.OrdinalIgnoreCase));&lt;br /&gt;
&lt;br /&gt;
                if (profile != null)&lt;br /&gt;
                {&lt;br /&gt;
                    ext.CurrentProfile = profile;&lt;br /&gt;
                    ext.Save();&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                return Task.FromResult(true);&lt;br /&gt;
            }&lt;br /&gt;
            catch (Exception)&lt;br /&gt;
            {&lt;br /&gt;
                return Task.FromResult(false);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Le script de retour à la normale===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;csharp&amp;quot; line highlight=&amp;quot;14-16&amp;quot;&amp;gt;&lt;br /&gt;
using System;&lt;br /&gt;
using System.Threading.Tasks;&lt;br /&gt;
using TCX.Configuration;&lt;br /&gt;
using CallFlow;&lt;br /&gt;
using System.Linq;&lt;br /&gt;
&lt;br /&gt;
namespace dummy&lt;br /&gt;
{&lt;br /&gt;
    public class ResetAstreinte : ScriptBase&amp;lt;ResetAstreinte&amp;gt;&lt;br /&gt;
    {&lt;br /&gt;
        // ============================================================&lt;br /&gt;
        // CONFIGURATION — modifier uniquement ces lignes par script&lt;br /&gt;
        // ============================================================&lt;br /&gt;
        private const string TARGET_EXT   = &amp;quot;111&amp;quot;;&lt;br /&gt;
        private const string PRENOM_EXT   = &amp;quot;Accueil&amp;quot;;&lt;br /&gt;
        private const string NOM_EXT      = &amp;quot;Mairie&amp;quot;;&lt;br /&gt;
        // ============================================================&lt;br /&gt;
&lt;br /&gt;
        public override Task&amp;lt;bool&amp;gt; StartAsync()&lt;br /&gt;
        {&lt;br /&gt;
            try&lt;br /&gt;
            {&lt;br /&gt;
                IPhoneSystem ps = PhoneSystem.Root;&lt;br /&gt;
                Extension ext = ps.GetDNByNumber(TARGET_EXT) as Extension;&lt;br /&gt;
                if (ext == null)&lt;br /&gt;
                    return Task.FromResult(false);&lt;br /&gt;
&lt;br /&gt;
                // 1. Remettre le nom générique&lt;br /&gt;
                ext.FirstName = PRENOM_EXT;&lt;br /&gt;
                ext.LastName  = NOM_EXT;&lt;br /&gt;
&lt;br /&gt;
                // 2. Vider le numéro mobile&lt;br /&gt;
                ext.SetProperty(&amp;quot;MOBILENUMBER&amp;quot;, &amp;quot;&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
                // 3. Résoudre le DN pour la messagerie vocale&lt;br /&gt;
                DN targetDN = ps.GetDNByNumber(TARGET_EXT);&lt;br /&gt;
&lt;br /&gt;
                // 4. Remettre AwayRoute → messagerie vocale&lt;br /&gt;
                FwdProfile awayProfile = ext.FwdProfiles&lt;br /&gt;
                    .FirstOrDefault(p =&amp;gt; p.Name.Equals(&lt;br /&gt;
                        &amp;quot;Away&amp;quot;, StringComparison.OrdinalIgnoreCase));&lt;br /&gt;
&lt;br /&gt;
                if (awayProfile != null)&lt;br /&gt;
                {&lt;br /&gt;
                    AwayRouting route = awayProfile.AwayRoute;&lt;br /&gt;
&lt;br /&gt;
                    HoursDestination internalHours = route.Internal;&lt;br /&gt;
                    HoursDestination externalHours = route.External;&lt;br /&gt;
&lt;br /&gt;
                    DestinationStruct destInternal = internalHours.AllHours;&lt;br /&gt;
                    destInternal.To               = DestinationType.VoiceMail;&lt;br /&gt;
                    destInternal.Internal         = targetDN;&lt;br /&gt;
                    destInternal.External         = &amp;quot;&amp;quot;;&lt;br /&gt;
                    internalHours.AllHours        = destInternal;&lt;br /&gt;
&lt;br /&gt;
                    DestinationStruct destExternal = externalHours.AllHours;&lt;br /&gt;
                    destExternal.To               = DestinationType.VoiceMail;&lt;br /&gt;
                    destExternal.Internal         = targetDN;&lt;br /&gt;
                    destExternal.External         = &amp;quot;&amp;quot;;&lt;br /&gt;
                    externalHours.AllHours        = destExternal;&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                // 5. Sauvegarder&lt;br /&gt;
                ext.Save();&lt;br /&gt;
&lt;br /&gt;
                // 6. Recharger et basculer vers Available&lt;br /&gt;
                ext = ps.GetDNByNumber(TARGET_EXT) as Extension;&lt;br /&gt;
                if (ext == null)&lt;br /&gt;
                    return Task.FromResult(false);&lt;br /&gt;
&lt;br /&gt;
                FwdProfile profile = ext.FwdProfiles&lt;br /&gt;
                    .FirstOrDefault(p =&amp;gt; p.Name.Equals(&lt;br /&gt;
                        &amp;quot;Available&amp;quot;, StringComparison.OrdinalIgnoreCase));&lt;br /&gt;
&lt;br /&gt;
                if (profile != null)&lt;br /&gt;
                {&lt;br /&gt;
                    ext.CurrentProfile = profile;&lt;br /&gt;
                    ext.Save();&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                return Task.FromResult(true);&lt;br /&gt;
            }&lt;br /&gt;
            catch (Exception)&lt;br /&gt;
            {&lt;br /&gt;
                return Task.FromResult(false);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Table de correspondance des profileName====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Dans 3CX!! Dans le script&lt;br /&gt;
|-&lt;br /&gt;
| Disponible|| Available&lt;br /&gt;
|-&lt;br /&gt;
| Absent|| Away&lt;br /&gt;
|-&lt;br /&gt;
| Ne pas déranger|| Out of office&lt;br /&gt;
|-&lt;br /&gt;
| Custom 1|| Custom 1&lt;br /&gt;
|-&lt;br /&gt;
| Custom 2|| Custom 2&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===Configuration concrète===&lt;br /&gt;
&lt;br /&gt;
On a besoin de gérer deux astreintes. Le poste Accueil reçoit les appels en temps normal&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Texte de la légende&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;Marcel Patulacci&#039;&#039;&#039; || &#039;&#039;&#039;Jean-Michel Apeuprè&#039;&#039;&#039;|| &#039;&#039;&#039;Poste accueil &#039;&#039;&#039; hors période d&#039;astreinte&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;syntaxhighlight lang=&amp;quot;csharp&amp;quot; line highlight=&amp;quot;3-5,8-9&amp;quot;&amp;gt;&lt;br /&gt;
    public class SetDynamicAstreinte : ScriptBase&amp;lt;SetDynamicAstreinte&amp;gt;&lt;br /&gt;
    {&lt;br /&gt;
        // ============================================================&lt;br /&gt;
        // CONFIGURATION — modifier uniquement ces lignes par script&lt;br /&gt;
        // ============================================================&lt;br /&gt;
        private const string TARGET_EXT   = &amp;quot;111&amp;quot;;&lt;br /&gt;
        private const string MOBILE_EXT   = &amp;quot;0612345678&amp;quot;;&lt;br /&gt;
        private const string PRENOM_EXT   = &amp;quot;Marcel&amp;quot;;&lt;br /&gt;
        private const string NOM_EXT      = &amp;quot;Patulacci&amp;quot;;&lt;br /&gt;
		 // ============================================================&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt; || &amp;lt;syntaxhighlight lang=&amp;quot;csharp&amp;quot; line highlight=&amp;quot;3-5,8-9&amp;quot;&amp;gt;&lt;br /&gt;
    public class SetDynamicAstreinte : ScriptBase&amp;lt;SetDynamicAstreinte&amp;gt;&lt;br /&gt;
    {&lt;br /&gt;
        // ============================================================&lt;br /&gt;
        // CONFIGURATION — modifier uniquement ces lignes par script&lt;br /&gt;
        // ============================================================&lt;br /&gt;
        private const string TARGET_EXT   = &amp;quot;111&amp;quot;;&lt;br /&gt;
        private const string MOBILE_EXT   = &amp;quot;0699999999&amp;quot;;&lt;br /&gt;
        private const string PRENOM_EXT   = &amp;quot;Jean-Michel&amp;quot;;&lt;br /&gt;
        private const string NOM_EXT      = &amp;quot;Apeuprè&amp;quot;;&lt;br /&gt;
		 // ============================================================&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;|| &amp;lt;syntaxhighlight lang=&amp;quot;csharp&amp;quot; line highlight=&amp;quot;6-8&amp;quot;&amp;gt;&lt;br /&gt;
    public class ResetAstreinte : ScriptBase&amp;lt;ResetAstreinte&amp;gt;&lt;br /&gt;
    {&lt;br /&gt;
        // ============================================================&lt;br /&gt;
        // CONFIGURATION — modifier uniquement ces lignes par script&lt;br /&gt;
        // ============================================================&lt;br /&gt;
        private const string TARGET_EXT   = &amp;quot;111&amp;quot;;&lt;br /&gt;
        private const string PRENOM_EXT   = &amp;quot;Accueil&amp;quot;;&lt;br /&gt;
        private const string NOM_EXT      = &amp;quot;Mairie&amp;quot;;&lt;br /&gt;
        // ============================================================&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Une fois les 3 scripts produits, passer à l&#039;étape [[Astreinte#Déclaration_du_script|Déclaration du script]] qui va permettre d&#039;affecter un code court à chaque script.&lt;br /&gt;
Exemple : &lt;br /&gt;
* *90 pour hors période d&#039;astreinte&lt;br /&gt;
* *91 pour Jean-Michel&lt;br /&gt;
* *92 pour Marcel&lt;br /&gt;
&lt;br /&gt;
On peut communiquer les codes aux personnes habilitées à gérer le système d&#039;astreinte et aller jusqu&#039;à paramétrer des BLF pour faciliter la vie d&#039;une secrétaire par exemple.&lt;br /&gt;
&lt;br /&gt;
{{Valide|v20}}&lt;br /&gt;
[[Catégorie:3CX]]&lt;/div&gt;</summary>
		<author><name>Anthony</name></author>
	</entry>
	<entry>
		<id>https://indywiki.fr/index.php?title=Astreinte&amp;diff=22261</id>
		<title>Astreinte</title>
		<link rel="alternate" type="text/html" href="https://indywiki.fr/index.php?title=Astreinte&amp;diff=22261"/>
		<updated>2026-04-28T12:51:06Z</updated>

		<summary type="html">&lt;p&gt;Anthony : /* Le script de retour à la normale */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;===Principe===&lt;br /&gt;
On paramètre le statut choisi pour l&#039;astreinte en renvoi vers &#039;&#039;&#039;mon mobile&#039;&#039;&#039;. Un script viendra modifier le statut de l&#039;extension cible ainsi que son numéro de contact mobile, prénom et nom. Ce script déclenchable par l&#039;appel à un code court, paramétrable si on le souhaite sur une BLF. &lt;br /&gt;
===Paramétrage du statut de l&#039;extension vers &#039;&#039;&#039;mon mobile&#039;&#039;&#039;===&lt;br /&gt;
[[Fichier:2026-04-03 13h29 01.png|vignette]]&lt;br /&gt;
#Réglages&lt;br /&gt;
#Transfert d&#039;appels&lt;br /&gt;
#Choisir le statut de l&#039;extension à activer pour enclencher le renvoi vers l&#039;astreinte. Dans l&#039;exemple &#039;&#039;&#039;Absent&#039;&#039;&#039;. Pas l&#039;état &#039;&#039;&#039;Disponible&#039;&#039;&#039; évidemment.&lt;br /&gt;
#Dans &amp;quot;Transférer les appels externes à&amp;quot;, choisir &#039;&#039;&#039;Mon mobile&#039;&#039;&#039;&lt;br /&gt;
#Cocher &#039;&#039;&#039;Rebond&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
===Déclaration du script===&lt;br /&gt;
[[Fichier:2026-04-02 17h11 35.png|vignette]]&lt;br /&gt;
&lt;br /&gt;
Rendez-vous dans :&lt;br /&gt;
&lt;br /&gt;
 Admin / Intégrations / Scripts d&#039;appels / + Ajouter personnalisé&lt;br /&gt;
&lt;br /&gt;
#Donner un nom au traitement de l&#039;appel. Exemple : &#039;&#039;&#039;astreinte_weekend&#039;&#039;&#039;&lt;br /&gt;
#Créer un code de raccourci, ce qui permettra d&#039;exécuter le script simplement en appelant ce code, et in fine par une BLF. Exemple : &#039;&#039;&#039;*99&#039;&#039;&#039;&lt;br /&gt;
#OK&lt;br /&gt;
#Coller dans le champ script le script paramétré ( voir section suivante )&lt;br /&gt;
#Sauvegarder&lt;br /&gt;
#Un message doit indiquer &#039;&#039;&#039;Compilation réussie !&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Le script d&#039;astreinte===&lt;br /&gt;
&lt;br /&gt;
L&#039;éxécution du script va modifier l&#039;extension &#039;&#039;&#039;targetExtNum &#039;&#039;&#039;, il va le basculer sur le statut &#039;&#039;&#039;profileName &#039;&#039;&#039;, modifier son mobile de contact &#039;&#039;&#039;mobileElu &#039;&#039;&#039;, son nom et prénom.&lt;br /&gt;
&lt;br /&gt;
Il faut donc seulement modifier les lignes surlignés dans le code ci-dessous :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;csharp&amp;quot; line highlight=&amp;quot;14-17&amp;quot;&amp;gt;&lt;br /&gt;
using System;&lt;br /&gt;
using System.Threading.Tasks;&lt;br /&gt;
using TCX.Configuration;&lt;br /&gt;
using CallFlow;&lt;br /&gt;
using System.Linq;&lt;br /&gt;
&lt;br /&gt;
namespace dummy&lt;br /&gt;
{&lt;br /&gt;
    public class SetDynamicAstreinte : ScriptBase&amp;lt;SetDynamicAstreinte&amp;gt;&lt;br /&gt;
    {&lt;br /&gt;
        // ============================================================&lt;br /&gt;
        // CONFIGURATION — modifier uniquement ces lignes par script&lt;br /&gt;
        // ============================================================&lt;br /&gt;
        private const string TARGET_EXT   = &amp;quot;111&amp;quot;;&lt;br /&gt;
        private const string MOBILE_EXT   = &amp;quot;0612345678&amp;quot;;&lt;br /&gt;
        private const string PRENOM_EXT   = &amp;quot;Claude&amp;quot;;&lt;br /&gt;
        private const string NOM_EXT      = &amp;quot;IA&amp;quot;;&lt;br /&gt;
		 // ============================================================&lt;br /&gt;
        &lt;br /&gt;
		private const string PROFILE_NAME = &amp;quot;Away&amp;quot;;&lt;br /&gt;
       &lt;br /&gt;
        public override Task&amp;lt;bool&amp;gt; StartAsync()&lt;br /&gt;
        {&lt;br /&gt;
            try&lt;br /&gt;
            {&lt;br /&gt;
                IPhoneSystem ps = PhoneSystem.Root;&lt;br /&gt;
                Extension ext = ps.GetDNByNumber(TARGET_EXT) as Extension;&lt;br /&gt;
                if (ext == null)&lt;br /&gt;
                    return Task.FromResult(false);&lt;br /&gt;
&lt;br /&gt;
                // 1. Nom / Prénom&lt;br /&gt;
                ext.FirstName = PRENOM_EXT;&lt;br /&gt;
                ext.LastName  = NOM_EXT;&lt;br /&gt;
&lt;br /&gt;
                // 2. Numéro mobile&lt;br /&gt;
                ext.SetProperty(&amp;quot;MOBILENUMBER&amp;quot;, MOBILE_EXT);&lt;br /&gt;
&lt;br /&gt;
                // 3. Trouver le profil Away&lt;br /&gt;
                FwdProfile targetProfile = ext.FwdProfiles&lt;br /&gt;
                    .FirstOrDefault(p =&amp;gt; p.Name.Equals(&lt;br /&gt;
                        PROFILE_NAME, StringComparison.OrdinalIgnoreCase));&lt;br /&gt;
&lt;br /&gt;
                if (targetProfile != null)&lt;br /&gt;
                {&lt;br /&gt;
                    // AwayRoute, Internal, External sont read-only&lt;br /&gt;
                    // mais ce sont des références : on peut modifier&lt;br /&gt;
                    // leurs membres si ceux-ci sont accessibles en écriture&lt;br /&gt;
                    AwayRouting route = targetProfile.AwayRoute;&lt;br /&gt;
&lt;br /&gt;
                    // Capturer les HoursDestination comme variables locales&lt;br /&gt;
                    // (objets référence — la propriété est read-only,&lt;br /&gt;
                    //  mais l&#039;objet pointé est modifiable)&lt;br /&gt;
                    HoursDestination internalHours = route.Internal;&lt;br /&gt;
                    HoursDestination externalHours = route.External;&lt;br /&gt;
&lt;br /&gt;
                    // Capturer AllHours (struct) → modifier → réassigner&lt;br /&gt;
                    DestinationStruct destInternal = internalHours.AllHours;&lt;br /&gt;
                    destInternal.To               = DestinationType.Boomerang;&lt;br /&gt;
                    destInternal.External         = MOBILE_EXT;&lt;br /&gt;
                    internalHours.AllHours        = destInternal;&lt;br /&gt;
&lt;br /&gt;
                    DestinationStruct destExternal = externalHours.AllHours;&lt;br /&gt;
                    destExternal.To               = DestinationType.Boomerang;&lt;br /&gt;
                    destExternal.External         = MOBILE_EXT;&lt;br /&gt;
                    externalHours.AllHours        = destExternal;&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                // 4. Sauvegarder&lt;br /&gt;
                ext.Save();&lt;br /&gt;
&lt;br /&gt;
                // 5. Recharger et basculer le profil&lt;br /&gt;
                ext = ps.GetDNByNumber(TARGET_EXT) as Extension;&lt;br /&gt;
                if (ext == null)&lt;br /&gt;
                    return Task.FromResult(false);&lt;br /&gt;
&lt;br /&gt;
                FwdProfile profile = ext.FwdProfiles&lt;br /&gt;
                    .FirstOrDefault(p =&amp;gt; p.Name.Equals(&lt;br /&gt;
                        PROFILE_NAME, StringComparison.OrdinalIgnoreCase));&lt;br /&gt;
&lt;br /&gt;
                if (profile != null)&lt;br /&gt;
                {&lt;br /&gt;
                    ext.CurrentProfile = profile;&lt;br /&gt;
                    ext.Save();&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                return Task.FromResult(true);&lt;br /&gt;
            }&lt;br /&gt;
            catch (Exception)&lt;br /&gt;
            {&lt;br /&gt;
                return Task.FromResult(false);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Le script de retour à la normale===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;csharp&amp;quot; line highlight=&amp;quot;14-16&amp;quot;&amp;gt;&lt;br /&gt;
using System;&lt;br /&gt;
using System.Threading.Tasks;&lt;br /&gt;
using TCX.Configuration;&lt;br /&gt;
using CallFlow;&lt;br /&gt;
using System.Linq;&lt;br /&gt;
&lt;br /&gt;
namespace dummy&lt;br /&gt;
{&lt;br /&gt;
    public class ResetAstreinte : ScriptBase&amp;lt;ResetAstreinte&amp;gt;&lt;br /&gt;
    {&lt;br /&gt;
        // ============================================================&lt;br /&gt;
        // CONFIGURATION — modifier uniquement ces lignes par script&lt;br /&gt;
        // ============================================================&lt;br /&gt;
        private const string TARGET_EXT   = &amp;quot;111&amp;quot;;&lt;br /&gt;
        private const string PRENOM_EXT   = &amp;quot;Accueil&amp;quot;;&lt;br /&gt;
        private const string NOM_EXT      = &amp;quot;Mairie&amp;quot;;&lt;br /&gt;
        // ============================================================&lt;br /&gt;
&lt;br /&gt;
        public override Task&amp;lt;bool&amp;gt; StartAsync()&lt;br /&gt;
        {&lt;br /&gt;
            try&lt;br /&gt;
            {&lt;br /&gt;
                IPhoneSystem ps = PhoneSystem.Root;&lt;br /&gt;
                Extension ext = ps.GetDNByNumber(TARGET_EXT) as Extension;&lt;br /&gt;
                if (ext == null)&lt;br /&gt;
                    return Task.FromResult(false);&lt;br /&gt;
&lt;br /&gt;
                // 1. Remettre le nom générique&lt;br /&gt;
                ext.FirstName = PRENOM_EXT;&lt;br /&gt;
                ext.LastName  = NOM_EXT;&lt;br /&gt;
&lt;br /&gt;
                // 2. Vider le numéro mobile&lt;br /&gt;
                ext.SetProperty(&amp;quot;MOBILENUMBER&amp;quot;, &amp;quot;&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
                // 3. Résoudre le DN pour la messagerie vocale&lt;br /&gt;
                DN targetDN = ps.GetDNByNumber(TARGET_EXT);&lt;br /&gt;
&lt;br /&gt;
                // 4. Remettre AwayRoute → messagerie vocale&lt;br /&gt;
                FwdProfile awayProfile = ext.FwdProfiles&lt;br /&gt;
                    .FirstOrDefault(p =&amp;gt; p.Name.Equals(&lt;br /&gt;
                        &amp;quot;Away&amp;quot;, StringComparison.OrdinalIgnoreCase));&lt;br /&gt;
&lt;br /&gt;
                if (awayProfile != null)&lt;br /&gt;
                {&lt;br /&gt;
                    AwayRouting route = awayProfile.AwayRoute;&lt;br /&gt;
&lt;br /&gt;
                    HoursDestination internalHours = route.Internal;&lt;br /&gt;
                    HoursDestination externalHours = route.External;&lt;br /&gt;
&lt;br /&gt;
                    DestinationStruct destInternal = internalHours.AllHours;&lt;br /&gt;
                    destInternal.To               = DestinationType.VoiceMail;&lt;br /&gt;
                    destInternal.Internal         = targetDN;&lt;br /&gt;
                    destInternal.External         = &amp;quot;&amp;quot;;&lt;br /&gt;
                    internalHours.AllHours        = destInternal;&lt;br /&gt;
&lt;br /&gt;
                    DestinationStruct destExternal = externalHours.AllHours;&lt;br /&gt;
                    destExternal.To               = DestinationType.VoiceMail;&lt;br /&gt;
                    destExternal.Internal         = targetDN;&lt;br /&gt;
                    destExternal.External         = &amp;quot;&amp;quot;;&lt;br /&gt;
                    externalHours.AllHours        = destExternal;&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                // 5. Sauvegarder&lt;br /&gt;
                ext.Save();&lt;br /&gt;
&lt;br /&gt;
                // 6. Recharger et basculer vers Available&lt;br /&gt;
                ext = ps.GetDNByNumber(TARGET_EXT) as Extension;&lt;br /&gt;
                if (ext == null)&lt;br /&gt;
                    return Task.FromResult(false);&lt;br /&gt;
&lt;br /&gt;
                FwdProfile profile = ext.FwdProfiles&lt;br /&gt;
                    .FirstOrDefault(p =&amp;gt; p.Name.Equals(&lt;br /&gt;
                        &amp;quot;Available&amp;quot;, StringComparison.OrdinalIgnoreCase));&lt;br /&gt;
&lt;br /&gt;
                if (profile != null)&lt;br /&gt;
                {&lt;br /&gt;
                    ext.CurrentProfile = profile;&lt;br /&gt;
                    ext.Save();&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                return Task.FromResult(true);&lt;br /&gt;
            }&lt;br /&gt;
            catch (Exception)&lt;br /&gt;
            {&lt;br /&gt;
                return Task.FromResult(false);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Table de correspondance des profileName====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Dans 3CX!! Dans le script&lt;br /&gt;
|-&lt;br /&gt;
| Disponible|| Available&lt;br /&gt;
|-&lt;br /&gt;
| Absent|| Away&lt;br /&gt;
|-&lt;br /&gt;
| Ne pas déranger|| Out of office&lt;br /&gt;
|-&lt;br /&gt;
| Custom 1|| Custom 1&lt;br /&gt;
|-&lt;br /&gt;
| Custom 2|| Custom 2&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===Configuration concrète===&lt;br /&gt;
&lt;br /&gt;
Il faut choisir un statut autre que &amp;quot;Disponible&amp;quot; qui sera activé pour l&#039;astreinte, &amp;quot;Away&amp;quot; pour cet exemple&lt;br /&gt;
&lt;br /&gt;
On a besoin de gérer deux astreintes. Le poste Accueil reçoit les appels en temps normal&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Texte de la légende&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;Marcel Patulacci&#039;&#039;&#039; || &#039;&#039;&#039;Jean-Michel Apeuprè&#039;&#039;&#039;|| &#039;&#039;&#039;Poste accueil &#039;&#039;&#039; hors période d&#039;astreinte&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;syntaxhighlight lang=&amp;quot;csharp&amp;quot; line highlight=&amp;quot;3-5,8-9&amp;quot;&amp;gt;&lt;br /&gt;
public override Task&amp;lt;bool&amp;gt; StartAsync()&lt;br /&gt;
        {&lt;br /&gt;
            string targetExtNum = &amp;quot;100&amp;quot;; &lt;br /&gt;
            string mobileElu = &amp;quot;0699999999&amp;quot;;&lt;br /&gt;
            string profileName = &amp;quot;Away&amp;quot;; &lt;br /&gt;
&lt;br /&gt;
            // Nommage de l&#039;astreinte&lt;br /&gt;
            string prenomElu = &amp;quot;Marcel&amp;quot;; &lt;br /&gt;
            string nomElu = &amp;quot;Patulacci&amp;quot;; &lt;br /&gt;
&lt;br /&gt;
            try&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt; || &amp;lt;syntaxhighlight lang=&amp;quot;csharp&amp;quot; line highlight=&amp;quot;3-5,8-9&amp;quot;&amp;gt;&lt;br /&gt;
public override Task&amp;lt;bool&amp;gt; StartAsync()&lt;br /&gt;
        {&lt;br /&gt;
            string targetExtNum = &amp;quot;100&amp;quot;; &lt;br /&gt;
            string mobileElu = &amp;quot;0688888888&amp;quot;;&lt;br /&gt;
            string profileName = &amp;quot;Away&amp;quot;; &lt;br /&gt;
&lt;br /&gt;
            // Nommage de l&#039;astreinte&lt;br /&gt;
            string prenomElu = &amp;quot;Jean-Michel&amp;quot;; &lt;br /&gt;
            string nomElu = &amp;quot;Apeuprè&amp;quot;; &lt;br /&gt;
&lt;br /&gt;
            try&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;|| &amp;lt;syntaxhighlight lang=&amp;quot;csharp&amp;quot; line highlight=&amp;quot;3-5,8-9&amp;quot;&amp;gt;&lt;br /&gt;
public override Task&amp;lt;bool&amp;gt; StartAsync()&lt;br /&gt;
        {&lt;br /&gt;
            string targetExtNum = &amp;quot;100&amp;quot;; &lt;br /&gt;
            string mobileElu = &amp;quot;&amp;quot;;&lt;br /&gt;
            string profileName = &amp;quot;Available&amp;quot;; &lt;br /&gt;
&lt;br /&gt;
            // Nommage de l&#039;astreinte&lt;br /&gt;
            string prenomElu = &amp;quot;Accueil&amp;quot;; &lt;br /&gt;
            string nomElu = &amp;quot;&amp;quot;; &lt;br /&gt;
&lt;br /&gt;
            try&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Une fois les 3 scripts produits, passer à l&#039;étape [[Astreinte#Déclaration_du_script|Déclaration du script]] qui va permettre d&#039;affecter un code court à chaque script.&lt;br /&gt;
Exemple : &lt;br /&gt;
* *90 pour hors période d&#039;astreinte&lt;br /&gt;
* *91 pour Jean-Michel&lt;br /&gt;
* *92 pour Marcel&lt;br /&gt;
&lt;br /&gt;
On peut communiquer les codes aux personnes habilitées à gérer le système d&#039;astreinte et aller jusqu&#039;à paramétrer des BLF pour faciliter la vie d&#039;une secrétaire par exemple.&lt;br /&gt;
&lt;br /&gt;
{{Valide|v20}}&lt;br /&gt;
[[Catégorie:3CX]]&lt;/div&gt;</summary>
		<author><name>Anthony</name></author>
	</entry>
	<entry>
		<id>https://indywiki.fr/index.php?title=Astreinte&amp;diff=22260</id>
		<title>Astreinte</title>
		<link rel="alternate" type="text/html" href="https://indywiki.fr/index.php?title=Astreinte&amp;diff=22260"/>
		<updated>2026-04-28T12:49:10Z</updated>

		<summary type="html">&lt;p&gt;Anthony : /* Le script d&amp;#039;astreinte */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;===Principe===&lt;br /&gt;
On paramètre le statut choisi pour l&#039;astreinte en renvoi vers &#039;&#039;&#039;mon mobile&#039;&#039;&#039;. Un script viendra modifier le statut de l&#039;extension cible ainsi que son numéro de contact mobile, prénom et nom. Ce script déclenchable par l&#039;appel à un code court, paramétrable si on le souhaite sur une BLF. &lt;br /&gt;
===Paramétrage du statut de l&#039;extension vers &#039;&#039;&#039;mon mobile&#039;&#039;&#039;===&lt;br /&gt;
[[Fichier:2026-04-03 13h29 01.png|vignette]]&lt;br /&gt;
#Réglages&lt;br /&gt;
#Transfert d&#039;appels&lt;br /&gt;
#Choisir le statut de l&#039;extension à activer pour enclencher le renvoi vers l&#039;astreinte. Dans l&#039;exemple &#039;&#039;&#039;Absent&#039;&#039;&#039;. Pas l&#039;état &#039;&#039;&#039;Disponible&#039;&#039;&#039; évidemment.&lt;br /&gt;
#Dans &amp;quot;Transférer les appels externes à&amp;quot;, choisir &#039;&#039;&#039;Mon mobile&#039;&#039;&#039;&lt;br /&gt;
#Cocher &#039;&#039;&#039;Rebond&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
===Déclaration du script===&lt;br /&gt;
[[Fichier:2026-04-02 17h11 35.png|vignette]]&lt;br /&gt;
&lt;br /&gt;
Rendez-vous dans :&lt;br /&gt;
&lt;br /&gt;
 Admin / Intégrations / Scripts d&#039;appels / + Ajouter personnalisé&lt;br /&gt;
&lt;br /&gt;
#Donner un nom au traitement de l&#039;appel. Exemple : &#039;&#039;&#039;astreinte_weekend&#039;&#039;&#039;&lt;br /&gt;
#Créer un code de raccourci, ce qui permettra d&#039;exécuter le script simplement en appelant ce code, et in fine par une BLF. Exemple : &#039;&#039;&#039;*99&#039;&#039;&#039;&lt;br /&gt;
#OK&lt;br /&gt;
#Coller dans le champ script le script paramétré ( voir section suivante )&lt;br /&gt;
#Sauvegarder&lt;br /&gt;
#Un message doit indiquer &#039;&#039;&#039;Compilation réussie !&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Le script d&#039;astreinte===&lt;br /&gt;
&lt;br /&gt;
L&#039;éxécution du script va modifier l&#039;extension &#039;&#039;&#039;targetExtNum &#039;&#039;&#039;, il va le basculer sur le statut &#039;&#039;&#039;profileName &#039;&#039;&#039;, modifier son mobile de contact &#039;&#039;&#039;mobileElu &#039;&#039;&#039;, son nom et prénom.&lt;br /&gt;
&lt;br /&gt;
Il faut donc seulement modifier les lignes surlignés dans le code ci-dessous :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;csharp&amp;quot; line highlight=&amp;quot;14-17&amp;quot;&amp;gt;&lt;br /&gt;
using System;&lt;br /&gt;
using System.Threading.Tasks;&lt;br /&gt;
using TCX.Configuration;&lt;br /&gt;
using CallFlow;&lt;br /&gt;
using System.Linq;&lt;br /&gt;
&lt;br /&gt;
namespace dummy&lt;br /&gt;
{&lt;br /&gt;
    public class SetDynamicAstreinte : ScriptBase&amp;lt;SetDynamicAstreinte&amp;gt;&lt;br /&gt;
    {&lt;br /&gt;
        // ============================================================&lt;br /&gt;
        // CONFIGURATION — modifier uniquement ces lignes par script&lt;br /&gt;
        // ============================================================&lt;br /&gt;
        private const string TARGET_EXT   = &amp;quot;111&amp;quot;;&lt;br /&gt;
        private const string MOBILE_EXT   = &amp;quot;0612345678&amp;quot;;&lt;br /&gt;
        private const string PRENOM_EXT   = &amp;quot;Claude&amp;quot;;&lt;br /&gt;
        private const string NOM_EXT      = &amp;quot;IA&amp;quot;;&lt;br /&gt;
		 // ============================================================&lt;br /&gt;
        &lt;br /&gt;
		private const string PROFILE_NAME = &amp;quot;Away&amp;quot;;&lt;br /&gt;
       &lt;br /&gt;
        public override Task&amp;lt;bool&amp;gt; StartAsync()&lt;br /&gt;
        {&lt;br /&gt;
            try&lt;br /&gt;
            {&lt;br /&gt;
                IPhoneSystem ps = PhoneSystem.Root;&lt;br /&gt;
                Extension ext = ps.GetDNByNumber(TARGET_EXT) as Extension;&lt;br /&gt;
                if (ext == null)&lt;br /&gt;
                    return Task.FromResult(false);&lt;br /&gt;
&lt;br /&gt;
                // 1. Nom / Prénom&lt;br /&gt;
                ext.FirstName = PRENOM_EXT;&lt;br /&gt;
                ext.LastName  = NOM_EXT;&lt;br /&gt;
&lt;br /&gt;
                // 2. Numéro mobile&lt;br /&gt;
                ext.SetProperty(&amp;quot;MOBILENUMBER&amp;quot;, MOBILE_EXT);&lt;br /&gt;
&lt;br /&gt;
                // 3. Trouver le profil Away&lt;br /&gt;
                FwdProfile targetProfile = ext.FwdProfiles&lt;br /&gt;
                    .FirstOrDefault(p =&amp;gt; p.Name.Equals(&lt;br /&gt;
                        PROFILE_NAME, StringComparison.OrdinalIgnoreCase));&lt;br /&gt;
&lt;br /&gt;
                if (targetProfile != null)&lt;br /&gt;
                {&lt;br /&gt;
                    // AwayRoute, Internal, External sont read-only&lt;br /&gt;
                    // mais ce sont des références : on peut modifier&lt;br /&gt;
                    // leurs membres si ceux-ci sont accessibles en écriture&lt;br /&gt;
                    AwayRouting route = targetProfile.AwayRoute;&lt;br /&gt;
&lt;br /&gt;
                    // Capturer les HoursDestination comme variables locales&lt;br /&gt;
                    // (objets référence — la propriété est read-only,&lt;br /&gt;
                    //  mais l&#039;objet pointé est modifiable)&lt;br /&gt;
                    HoursDestination internalHours = route.Internal;&lt;br /&gt;
                    HoursDestination externalHours = route.External;&lt;br /&gt;
&lt;br /&gt;
                    // Capturer AllHours (struct) → modifier → réassigner&lt;br /&gt;
                    DestinationStruct destInternal = internalHours.AllHours;&lt;br /&gt;
                    destInternal.To               = DestinationType.Boomerang;&lt;br /&gt;
                    destInternal.External         = MOBILE_EXT;&lt;br /&gt;
                    internalHours.AllHours        = destInternal;&lt;br /&gt;
&lt;br /&gt;
                    DestinationStruct destExternal = externalHours.AllHours;&lt;br /&gt;
                    destExternal.To               = DestinationType.Boomerang;&lt;br /&gt;
                    destExternal.External         = MOBILE_EXT;&lt;br /&gt;
                    externalHours.AllHours        = destExternal;&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                // 4. Sauvegarder&lt;br /&gt;
                ext.Save();&lt;br /&gt;
&lt;br /&gt;
                // 5. Recharger et basculer le profil&lt;br /&gt;
                ext = ps.GetDNByNumber(TARGET_EXT) as Extension;&lt;br /&gt;
                if (ext == null)&lt;br /&gt;
                    return Task.FromResult(false);&lt;br /&gt;
&lt;br /&gt;
                FwdProfile profile = ext.FwdProfiles&lt;br /&gt;
                    .FirstOrDefault(p =&amp;gt; p.Name.Equals(&lt;br /&gt;
                        PROFILE_NAME, StringComparison.OrdinalIgnoreCase));&lt;br /&gt;
&lt;br /&gt;
                if (profile != null)&lt;br /&gt;
                {&lt;br /&gt;
                    ext.CurrentProfile = profile;&lt;br /&gt;
                    ext.Save();&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                return Task.FromResult(true);&lt;br /&gt;
            }&lt;br /&gt;
            catch (Exception)&lt;br /&gt;
            {&lt;br /&gt;
                return Task.FromResult(false);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Le script de retour à la normale===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;csharp&amp;quot; line highlight=&amp;quot;14-16&amp;quot;&amp;gt;&lt;br /&gt;
using System;&lt;br /&gt;
using System.Threading.Tasks;&lt;br /&gt;
using TCX.Configuration;&lt;br /&gt;
using CallFlow;&lt;br /&gt;
using System.Linq;&lt;br /&gt;
&lt;br /&gt;
namespace dummy&lt;br /&gt;
{&lt;br /&gt;
    public class ResetAstreinte : ScriptBase&amp;lt;ResetAstreinte&amp;gt;&lt;br /&gt;
    {&lt;br /&gt;
        // ============================================================&lt;br /&gt;
        // CONFIGURATION&lt;br /&gt;
        // ============================================================&lt;br /&gt;
        private const string TARGET_EXT   = &amp;quot;111&amp;quot;;&lt;br /&gt;
        private const string PRENOM_ELU   = &amp;quot;Accueil&amp;quot;;&lt;br /&gt;
        private const string NOM_ELU      = &amp;quot;Mairie&amp;quot;;&lt;br /&gt;
        // ============================================================&lt;br /&gt;
&lt;br /&gt;
        public override Task&amp;lt;bool&amp;gt; StartAsync()&lt;br /&gt;
        {&lt;br /&gt;
            try&lt;br /&gt;
            {&lt;br /&gt;
                IPhoneSystem ps = PhoneSystem.Root;&lt;br /&gt;
                Extension ext = ps.GetDNByNumber(TARGET_EXT) as Extension;&lt;br /&gt;
                if (ext == null)&lt;br /&gt;
                    return Task.FromResult(false);&lt;br /&gt;
&lt;br /&gt;
                // 1. Remettre le nom générique&lt;br /&gt;
                ext.FirstName = PRENOM_ELU;&lt;br /&gt;
                ext.LastName  = NOM_ELU;&lt;br /&gt;
&lt;br /&gt;
                // 2. Vider le numéro mobile&lt;br /&gt;
                ext.SetProperty(&amp;quot;MOBILENUMBER&amp;quot;, &amp;quot;&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
                // 3. Résoudre le DN pour la messagerie vocale&lt;br /&gt;
                DN targetDN = ps.GetDNByNumber(TARGET_EXT);&lt;br /&gt;
&lt;br /&gt;
                // 4. Remettre AwayRoute → messagerie vocale&lt;br /&gt;
                FwdProfile awayProfile = ext.FwdProfiles&lt;br /&gt;
                    .FirstOrDefault(p =&amp;gt; p.Name.Equals(&lt;br /&gt;
                        &amp;quot;Away&amp;quot;, StringComparison.OrdinalIgnoreCase));&lt;br /&gt;
&lt;br /&gt;
                if (awayProfile != null)&lt;br /&gt;
                {&lt;br /&gt;
                    AwayRouting route = awayProfile.AwayRoute;&lt;br /&gt;
&lt;br /&gt;
                    HoursDestination internalHours = route.Internal;&lt;br /&gt;
                    HoursDestination externalHours = route.External;&lt;br /&gt;
&lt;br /&gt;
                    DestinationStruct destInternal = internalHours.AllHours;&lt;br /&gt;
                    destInternal.To               = DestinationType.VoiceMail;&lt;br /&gt;
                    destInternal.Internal         = targetDN;&lt;br /&gt;
                    destInternal.External         = &amp;quot;&amp;quot;;&lt;br /&gt;
                    internalHours.AllHours        = destInternal;&lt;br /&gt;
&lt;br /&gt;
                    DestinationStruct destExternal = externalHours.AllHours;&lt;br /&gt;
                    destExternal.To               = DestinationType.VoiceMail;&lt;br /&gt;
                    destExternal.Internal         = targetDN;&lt;br /&gt;
                    destExternal.External         = &amp;quot;&amp;quot;;&lt;br /&gt;
                    externalHours.AllHours        = destExternal;&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                // 5. Sauvegarder&lt;br /&gt;
                ext.Save();&lt;br /&gt;
&lt;br /&gt;
                // 6. Recharger et basculer vers Available&lt;br /&gt;
                ext = ps.GetDNByNumber(TARGET_EXT) as Extension;&lt;br /&gt;
                if (ext == null)&lt;br /&gt;
                    return Task.FromResult(false);&lt;br /&gt;
&lt;br /&gt;
                FwdProfile profile = ext.FwdProfiles&lt;br /&gt;
                    .FirstOrDefault(p =&amp;gt; p.Name.Equals(&lt;br /&gt;
                        &amp;quot;Available&amp;quot;, StringComparison.OrdinalIgnoreCase));&lt;br /&gt;
&lt;br /&gt;
                if (profile != null)&lt;br /&gt;
                {&lt;br /&gt;
                    ext.CurrentProfile = profile;&lt;br /&gt;
                    ext.Save();&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                return Task.FromResult(true);&lt;br /&gt;
            }&lt;br /&gt;
            catch (Exception)&lt;br /&gt;
            {&lt;br /&gt;
                return Task.FromResult(false);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Table de correspondance des profileName====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Dans 3CX!! Dans le script&lt;br /&gt;
|-&lt;br /&gt;
| Disponible|| Available&lt;br /&gt;
|-&lt;br /&gt;
| Absent|| Away&lt;br /&gt;
|-&lt;br /&gt;
| Ne pas déranger|| Out of office&lt;br /&gt;
|-&lt;br /&gt;
| Custom 1|| Custom 1&lt;br /&gt;
|-&lt;br /&gt;
| Custom 2|| Custom 2&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===Configuration concrète===&lt;br /&gt;
&lt;br /&gt;
Il faut choisir un statut autre que &amp;quot;Disponible&amp;quot; qui sera activé pour l&#039;astreinte, &amp;quot;Away&amp;quot; pour cet exemple&lt;br /&gt;
&lt;br /&gt;
On a besoin de gérer deux astreintes. Le poste Accueil reçoit les appels en temps normal&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Texte de la légende&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;Marcel Patulacci&#039;&#039;&#039; || &#039;&#039;&#039;Jean-Michel Apeuprè&#039;&#039;&#039;|| &#039;&#039;&#039;Poste accueil &#039;&#039;&#039; hors période d&#039;astreinte&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;syntaxhighlight lang=&amp;quot;csharp&amp;quot; line highlight=&amp;quot;3-5,8-9&amp;quot;&amp;gt;&lt;br /&gt;
public override Task&amp;lt;bool&amp;gt; StartAsync()&lt;br /&gt;
        {&lt;br /&gt;
            string targetExtNum = &amp;quot;100&amp;quot;; &lt;br /&gt;
            string mobileElu = &amp;quot;0699999999&amp;quot;;&lt;br /&gt;
            string profileName = &amp;quot;Away&amp;quot;; &lt;br /&gt;
&lt;br /&gt;
            // Nommage de l&#039;astreinte&lt;br /&gt;
            string prenomElu = &amp;quot;Marcel&amp;quot;; &lt;br /&gt;
            string nomElu = &amp;quot;Patulacci&amp;quot;; &lt;br /&gt;
&lt;br /&gt;
            try&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt; || &amp;lt;syntaxhighlight lang=&amp;quot;csharp&amp;quot; line highlight=&amp;quot;3-5,8-9&amp;quot;&amp;gt;&lt;br /&gt;
public override Task&amp;lt;bool&amp;gt; StartAsync()&lt;br /&gt;
        {&lt;br /&gt;
            string targetExtNum = &amp;quot;100&amp;quot;; &lt;br /&gt;
            string mobileElu = &amp;quot;0688888888&amp;quot;;&lt;br /&gt;
            string profileName = &amp;quot;Away&amp;quot;; &lt;br /&gt;
&lt;br /&gt;
            // Nommage de l&#039;astreinte&lt;br /&gt;
            string prenomElu = &amp;quot;Jean-Michel&amp;quot;; &lt;br /&gt;
            string nomElu = &amp;quot;Apeuprè&amp;quot;; &lt;br /&gt;
&lt;br /&gt;
            try&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;|| &amp;lt;syntaxhighlight lang=&amp;quot;csharp&amp;quot; line highlight=&amp;quot;3-5,8-9&amp;quot;&amp;gt;&lt;br /&gt;
public override Task&amp;lt;bool&amp;gt; StartAsync()&lt;br /&gt;
        {&lt;br /&gt;
            string targetExtNum = &amp;quot;100&amp;quot;; &lt;br /&gt;
            string mobileElu = &amp;quot;&amp;quot;;&lt;br /&gt;
            string profileName = &amp;quot;Available&amp;quot;; &lt;br /&gt;
&lt;br /&gt;
            // Nommage de l&#039;astreinte&lt;br /&gt;
            string prenomElu = &amp;quot;Accueil&amp;quot;; &lt;br /&gt;
            string nomElu = &amp;quot;&amp;quot;; &lt;br /&gt;
&lt;br /&gt;
            try&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Une fois les 3 scripts produits, passer à l&#039;étape [[Astreinte#Déclaration_du_script|Déclaration du script]] qui va permettre d&#039;affecter un code court à chaque script.&lt;br /&gt;
Exemple : &lt;br /&gt;
* *90 pour hors période d&#039;astreinte&lt;br /&gt;
* *91 pour Jean-Michel&lt;br /&gt;
* *92 pour Marcel&lt;br /&gt;
&lt;br /&gt;
On peut communiquer les codes aux personnes habilitées à gérer le système d&#039;astreinte et aller jusqu&#039;à paramétrer des BLF pour faciliter la vie d&#039;une secrétaire par exemple.&lt;br /&gt;
&lt;br /&gt;
{{Valide|v20}}&lt;br /&gt;
[[Catégorie:3CX]]&lt;/div&gt;</summary>
		<author><name>Anthony</name></author>
	</entry>
	<entry>
		<id>https://indywiki.fr/index.php?title=Astreinte&amp;diff=22259</id>
		<title>Astreinte</title>
		<link rel="alternate" type="text/html" href="https://indywiki.fr/index.php?title=Astreinte&amp;diff=22259"/>
		<updated>2026-04-28T12:44:28Z</updated>

		<summary type="html">&lt;p&gt;Anthony : /* Le script de retour à la normale */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;===Principe===&lt;br /&gt;
On paramètre le statut choisi pour l&#039;astreinte en renvoi vers &#039;&#039;&#039;mon mobile&#039;&#039;&#039;. Un script viendra modifier le statut de l&#039;extension cible ainsi que son numéro de contact mobile, prénom et nom. Ce script déclenchable par l&#039;appel à un code court, paramétrable si on le souhaite sur une BLF. &lt;br /&gt;
===Paramétrage du statut de l&#039;extension vers &#039;&#039;&#039;mon mobile&#039;&#039;&#039;===&lt;br /&gt;
[[Fichier:2026-04-03 13h29 01.png|vignette]]&lt;br /&gt;
#Réglages&lt;br /&gt;
#Transfert d&#039;appels&lt;br /&gt;
#Choisir le statut de l&#039;extension à activer pour enclencher le renvoi vers l&#039;astreinte. Dans l&#039;exemple &#039;&#039;&#039;Absent&#039;&#039;&#039;. Pas l&#039;état &#039;&#039;&#039;Disponible&#039;&#039;&#039; évidemment.&lt;br /&gt;
#Dans &amp;quot;Transférer les appels externes à&amp;quot;, choisir &#039;&#039;&#039;Mon mobile&#039;&#039;&#039;&lt;br /&gt;
#Cocher &#039;&#039;&#039;Rebond&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
===Déclaration du script===&lt;br /&gt;
[[Fichier:2026-04-02 17h11 35.png|vignette]]&lt;br /&gt;
&lt;br /&gt;
Rendez-vous dans :&lt;br /&gt;
&lt;br /&gt;
 Admin / Intégrations / Scripts d&#039;appels / + Ajouter personnalisé&lt;br /&gt;
&lt;br /&gt;
#Donner un nom au traitement de l&#039;appel. Exemple : &#039;&#039;&#039;astreinte_weekend&#039;&#039;&#039;&lt;br /&gt;
#Créer un code de raccourci, ce qui permettra d&#039;exécuter le script simplement en appelant ce code, et in fine par une BLF. Exemple : &#039;&#039;&#039;*99&#039;&#039;&#039;&lt;br /&gt;
#OK&lt;br /&gt;
#Coller dans le champ script le script paramétré ( voir section suivante )&lt;br /&gt;
#Sauvegarder&lt;br /&gt;
#Un message doit indiquer &#039;&#039;&#039;Compilation réussie !&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Le script d&#039;astreinte===&lt;br /&gt;
&lt;br /&gt;
L&#039;éxécution du script va modifier l&#039;extension &#039;&#039;&#039;targetExtNum &#039;&#039;&#039;, il va le basculer sur le statut &#039;&#039;&#039;profileName &#039;&#039;&#039;, modifier son mobile de contact &#039;&#039;&#039;mobileElu &#039;&#039;&#039;, son nom et prénom.&lt;br /&gt;
&lt;br /&gt;
Il faut donc seulement modifier les lignes surlignés dans le code ci-dessous :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;csharp&amp;quot; line highlight=&amp;quot;14-17&amp;quot;&amp;gt;&lt;br /&gt;
using System;&lt;br /&gt;
using System.Threading.Tasks;&lt;br /&gt;
using TCX.Configuration;&lt;br /&gt;
using CallFlow;&lt;br /&gt;
using System.Linq;&lt;br /&gt;
&lt;br /&gt;
namespace dummy&lt;br /&gt;
{&lt;br /&gt;
    public class SetDynamicAstreinte : ScriptBase&amp;lt;SetDynamicAstreinte&amp;gt;&lt;br /&gt;
    {&lt;br /&gt;
        // ============================================================&lt;br /&gt;
        // CONFIGURATION — modifier uniquement ces lignes par script&lt;br /&gt;
        // ============================================================&lt;br /&gt;
        private const string TARGET_EXT   = &amp;quot;111&amp;quot;;&lt;br /&gt;
        private const string MOBILE_ELU   = &amp;quot;0612345678&amp;quot;;&lt;br /&gt;
        private const string PRENOM_ELU   = &amp;quot;Claude&amp;quot;;&lt;br /&gt;
        private const string NOM_ELU      = &amp;quot;IA&amp;quot;;&lt;br /&gt;
        private const string PROFILE_NAME = &amp;quot;Away&amp;quot;;&lt;br /&gt;
        // ============================================================&lt;br /&gt;
&lt;br /&gt;
        public override Task&amp;lt;bool&amp;gt; StartAsync()&lt;br /&gt;
        {&lt;br /&gt;
            try&lt;br /&gt;
            {&lt;br /&gt;
                IPhoneSystem ps = PhoneSystem.Root;&lt;br /&gt;
                Extension ext = ps.GetDNByNumber(TARGET_EXT) as Extension;&lt;br /&gt;
                if (ext == null)&lt;br /&gt;
                    return Task.FromResult(false);&lt;br /&gt;
&lt;br /&gt;
                // 1. Nom / Prénom&lt;br /&gt;
                ext.FirstName = PRENOM_ELU;&lt;br /&gt;
                ext.LastName  = NOM_ELU;&lt;br /&gt;
&lt;br /&gt;
                // 2. Numéro mobile&lt;br /&gt;
                ext.SetProperty(&amp;quot;MOBILENUMBER&amp;quot;, MOBILE_ELU);&lt;br /&gt;
&lt;br /&gt;
                // 3. Trouver le profil Away&lt;br /&gt;
                FwdProfile targetProfile = ext.FwdProfiles&lt;br /&gt;
                    .FirstOrDefault(p =&amp;gt; p.Name.Equals(&lt;br /&gt;
                        PROFILE_NAME, StringComparison.OrdinalIgnoreCase));&lt;br /&gt;
&lt;br /&gt;
                if (targetProfile != null)&lt;br /&gt;
                {&lt;br /&gt;
                    // AwayRoute, Internal, External sont read-only&lt;br /&gt;
                    // mais ce sont des références : on peut modifier&lt;br /&gt;
                    // leurs membres si ceux-ci sont accessibles en écriture&lt;br /&gt;
                    AwayRouting route = targetProfile.AwayRoute;&lt;br /&gt;
&lt;br /&gt;
                    // Capturer les HoursDestination comme variables locales&lt;br /&gt;
                    // (objets référence — la propriété est read-only,&lt;br /&gt;
                    //  mais l&#039;objet pointé est modifiable)&lt;br /&gt;
                    HoursDestination internalHours = route.Internal;&lt;br /&gt;
                    HoursDestination externalHours = route.External;&lt;br /&gt;
&lt;br /&gt;
                    // Capturer AllHours (struct) → modifier → réassigner&lt;br /&gt;
                    DestinationStruct destInternal = internalHours.AllHours;&lt;br /&gt;
                    destInternal.To               = DestinationType.Boomerang;&lt;br /&gt;
                    destInternal.External         = MOBILE_ELU;&lt;br /&gt;
                    internalHours.AllHours        = destInternal;&lt;br /&gt;
&lt;br /&gt;
                    DestinationStruct destExternal = externalHours.AllHours;&lt;br /&gt;
                    destExternal.To               = DestinationType.Boomerang;&lt;br /&gt;
                    destExternal.External         = MOBILE_ELU;&lt;br /&gt;
                    externalHours.AllHours        = destExternal;&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                // 4. Sauvegarder&lt;br /&gt;
                ext.Save();&lt;br /&gt;
&lt;br /&gt;
                // 5. Recharger et basculer le profil&lt;br /&gt;
                ext = ps.GetDNByNumber(TARGET_EXT) as Extension;&lt;br /&gt;
                if (ext == null)&lt;br /&gt;
                    return Task.FromResult(false);&lt;br /&gt;
&lt;br /&gt;
                FwdProfile profile = ext.FwdProfiles&lt;br /&gt;
                    .FirstOrDefault(p =&amp;gt; p.Name.Equals(&lt;br /&gt;
                        PROFILE_NAME, StringComparison.OrdinalIgnoreCase));&lt;br /&gt;
&lt;br /&gt;
                if (profile != null)&lt;br /&gt;
                {&lt;br /&gt;
                    ext.CurrentProfile = profile;&lt;br /&gt;
                    ext.Save();&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                return Task.FromResult(true);&lt;br /&gt;
            }&lt;br /&gt;
            catch (Exception)&lt;br /&gt;
            {&lt;br /&gt;
                return Task.FromResult(false);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Le script de retour à la normale===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;csharp&amp;quot; line highlight=&amp;quot;14-16&amp;quot;&amp;gt;&lt;br /&gt;
using System;&lt;br /&gt;
using System.Threading.Tasks;&lt;br /&gt;
using TCX.Configuration;&lt;br /&gt;
using CallFlow;&lt;br /&gt;
using System.Linq;&lt;br /&gt;
&lt;br /&gt;
namespace dummy&lt;br /&gt;
{&lt;br /&gt;
    public class ResetAstreinte : ScriptBase&amp;lt;ResetAstreinte&amp;gt;&lt;br /&gt;
    {&lt;br /&gt;
        // ============================================================&lt;br /&gt;
        // CONFIGURATION&lt;br /&gt;
        // ============================================================&lt;br /&gt;
        private const string TARGET_EXT   = &amp;quot;111&amp;quot;;&lt;br /&gt;
        private const string PRENOM_ELU   = &amp;quot;Accueil&amp;quot;;&lt;br /&gt;
        private const string NOM_ELU      = &amp;quot;Mairie&amp;quot;;&lt;br /&gt;
        // ============================================================&lt;br /&gt;
&lt;br /&gt;
        public override Task&amp;lt;bool&amp;gt; StartAsync()&lt;br /&gt;
        {&lt;br /&gt;
            try&lt;br /&gt;
            {&lt;br /&gt;
                IPhoneSystem ps = PhoneSystem.Root;&lt;br /&gt;
                Extension ext = ps.GetDNByNumber(TARGET_EXT) as Extension;&lt;br /&gt;
                if (ext == null)&lt;br /&gt;
                    return Task.FromResult(false);&lt;br /&gt;
&lt;br /&gt;
                // 1. Remettre le nom générique&lt;br /&gt;
                ext.FirstName = PRENOM_ELU;&lt;br /&gt;
                ext.LastName  = NOM_ELU;&lt;br /&gt;
&lt;br /&gt;
                // 2. Vider le numéro mobile&lt;br /&gt;
                ext.SetProperty(&amp;quot;MOBILENUMBER&amp;quot;, &amp;quot;&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
                // 3. Résoudre le DN pour la messagerie vocale&lt;br /&gt;
                DN targetDN = ps.GetDNByNumber(TARGET_EXT);&lt;br /&gt;
&lt;br /&gt;
                // 4. Remettre AwayRoute → messagerie vocale&lt;br /&gt;
                FwdProfile awayProfile = ext.FwdProfiles&lt;br /&gt;
                    .FirstOrDefault(p =&amp;gt; p.Name.Equals(&lt;br /&gt;
                        &amp;quot;Away&amp;quot;, StringComparison.OrdinalIgnoreCase));&lt;br /&gt;
&lt;br /&gt;
                if (awayProfile != null)&lt;br /&gt;
                {&lt;br /&gt;
                    AwayRouting route = awayProfile.AwayRoute;&lt;br /&gt;
&lt;br /&gt;
                    HoursDestination internalHours = route.Internal;&lt;br /&gt;
                    HoursDestination externalHours = route.External;&lt;br /&gt;
&lt;br /&gt;
                    DestinationStruct destInternal = internalHours.AllHours;&lt;br /&gt;
                    destInternal.To               = DestinationType.VoiceMail;&lt;br /&gt;
                    destInternal.Internal         = targetDN;&lt;br /&gt;
                    destInternal.External         = &amp;quot;&amp;quot;;&lt;br /&gt;
                    internalHours.AllHours        = destInternal;&lt;br /&gt;
&lt;br /&gt;
                    DestinationStruct destExternal = externalHours.AllHours;&lt;br /&gt;
                    destExternal.To               = DestinationType.VoiceMail;&lt;br /&gt;
                    destExternal.Internal         = targetDN;&lt;br /&gt;
                    destExternal.External         = &amp;quot;&amp;quot;;&lt;br /&gt;
                    externalHours.AllHours        = destExternal;&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                // 5. Sauvegarder&lt;br /&gt;
                ext.Save();&lt;br /&gt;
&lt;br /&gt;
                // 6. Recharger et basculer vers Available&lt;br /&gt;
                ext = ps.GetDNByNumber(TARGET_EXT) as Extension;&lt;br /&gt;
                if (ext == null)&lt;br /&gt;
                    return Task.FromResult(false);&lt;br /&gt;
&lt;br /&gt;
                FwdProfile profile = ext.FwdProfiles&lt;br /&gt;
                    .FirstOrDefault(p =&amp;gt; p.Name.Equals(&lt;br /&gt;
                        &amp;quot;Available&amp;quot;, StringComparison.OrdinalIgnoreCase));&lt;br /&gt;
&lt;br /&gt;
                if (profile != null)&lt;br /&gt;
                {&lt;br /&gt;
                    ext.CurrentProfile = profile;&lt;br /&gt;
                    ext.Save();&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                return Task.FromResult(true);&lt;br /&gt;
            }&lt;br /&gt;
            catch (Exception)&lt;br /&gt;
            {&lt;br /&gt;
                return Task.FromResult(false);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Table de correspondance des profileName====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Dans 3CX!! Dans le script&lt;br /&gt;
|-&lt;br /&gt;
| Disponible|| Available&lt;br /&gt;
|-&lt;br /&gt;
| Absent|| Away&lt;br /&gt;
|-&lt;br /&gt;
| Ne pas déranger|| Out of office&lt;br /&gt;
|-&lt;br /&gt;
| Custom 1|| Custom 1&lt;br /&gt;
|-&lt;br /&gt;
| Custom 2|| Custom 2&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===Configuration concrète===&lt;br /&gt;
&lt;br /&gt;
Il faut choisir un statut autre que &amp;quot;Disponible&amp;quot; qui sera activé pour l&#039;astreinte, &amp;quot;Away&amp;quot; pour cet exemple&lt;br /&gt;
&lt;br /&gt;
On a besoin de gérer deux astreintes. Le poste Accueil reçoit les appels en temps normal&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Texte de la légende&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;Marcel Patulacci&#039;&#039;&#039; || &#039;&#039;&#039;Jean-Michel Apeuprè&#039;&#039;&#039;|| &#039;&#039;&#039;Poste accueil &#039;&#039;&#039; hors période d&#039;astreinte&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;syntaxhighlight lang=&amp;quot;csharp&amp;quot; line highlight=&amp;quot;3-5,8-9&amp;quot;&amp;gt;&lt;br /&gt;
public override Task&amp;lt;bool&amp;gt; StartAsync()&lt;br /&gt;
        {&lt;br /&gt;
            string targetExtNum = &amp;quot;100&amp;quot;; &lt;br /&gt;
            string mobileElu = &amp;quot;0699999999&amp;quot;;&lt;br /&gt;
            string profileName = &amp;quot;Away&amp;quot;; &lt;br /&gt;
&lt;br /&gt;
            // Nommage de l&#039;astreinte&lt;br /&gt;
            string prenomElu = &amp;quot;Marcel&amp;quot;; &lt;br /&gt;
            string nomElu = &amp;quot;Patulacci&amp;quot;; &lt;br /&gt;
&lt;br /&gt;
            try&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt; || &amp;lt;syntaxhighlight lang=&amp;quot;csharp&amp;quot; line highlight=&amp;quot;3-5,8-9&amp;quot;&amp;gt;&lt;br /&gt;
public override Task&amp;lt;bool&amp;gt; StartAsync()&lt;br /&gt;
        {&lt;br /&gt;
            string targetExtNum = &amp;quot;100&amp;quot;; &lt;br /&gt;
            string mobileElu = &amp;quot;0688888888&amp;quot;;&lt;br /&gt;
            string profileName = &amp;quot;Away&amp;quot;; &lt;br /&gt;
&lt;br /&gt;
            // Nommage de l&#039;astreinte&lt;br /&gt;
            string prenomElu = &amp;quot;Jean-Michel&amp;quot;; &lt;br /&gt;
            string nomElu = &amp;quot;Apeuprè&amp;quot;; &lt;br /&gt;
&lt;br /&gt;
            try&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;|| &amp;lt;syntaxhighlight lang=&amp;quot;csharp&amp;quot; line highlight=&amp;quot;3-5,8-9&amp;quot;&amp;gt;&lt;br /&gt;
public override Task&amp;lt;bool&amp;gt; StartAsync()&lt;br /&gt;
        {&lt;br /&gt;
            string targetExtNum = &amp;quot;100&amp;quot;; &lt;br /&gt;
            string mobileElu = &amp;quot;&amp;quot;;&lt;br /&gt;
            string profileName = &amp;quot;Available&amp;quot;; &lt;br /&gt;
&lt;br /&gt;
            // Nommage de l&#039;astreinte&lt;br /&gt;
            string prenomElu = &amp;quot;Accueil&amp;quot;; &lt;br /&gt;
            string nomElu = &amp;quot;&amp;quot;; &lt;br /&gt;
&lt;br /&gt;
            try&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Une fois les 3 scripts produits, passer à l&#039;étape [[Astreinte#Déclaration_du_script|Déclaration du script]] qui va permettre d&#039;affecter un code court à chaque script.&lt;br /&gt;
Exemple : &lt;br /&gt;
* *90 pour hors période d&#039;astreinte&lt;br /&gt;
* *91 pour Jean-Michel&lt;br /&gt;
* *92 pour Marcel&lt;br /&gt;
&lt;br /&gt;
On peut communiquer les codes aux personnes habilitées à gérer le système d&#039;astreinte et aller jusqu&#039;à paramétrer des BLF pour faciliter la vie d&#039;une secrétaire par exemple.&lt;br /&gt;
&lt;br /&gt;
{{Valide|v20}}&lt;br /&gt;
[[Catégorie:3CX]]&lt;/div&gt;</summary>
		<author><name>Anthony</name></author>
	</entry>
	<entry>
		<id>https://indywiki.fr/index.php?title=Astreinte&amp;diff=22258</id>
		<title>Astreinte</title>
		<link rel="alternate" type="text/html" href="https://indywiki.fr/index.php?title=Astreinte&amp;diff=22258"/>
		<updated>2026-04-28T12:16:08Z</updated>

		<summary type="html">&lt;p&gt;Anthony : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;===Principe===&lt;br /&gt;
On paramètre le statut choisi pour l&#039;astreinte en renvoi vers &#039;&#039;&#039;mon mobile&#039;&#039;&#039;. Un script viendra modifier le statut de l&#039;extension cible ainsi que son numéro de contact mobile, prénom et nom. Ce script déclenchable par l&#039;appel à un code court, paramétrable si on le souhaite sur une BLF. &lt;br /&gt;
===Paramétrage du statut de l&#039;extension vers &#039;&#039;&#039;mon mobile&#039;&#039;&#039;===&lt;br /&gt;
[[Fichier:2026-04-03 13h29 01.png|vignette]]&lt;br /&gt;
#Réglages&lt;br /&gt;
#Transfert d&#039;appels&lt;br /&gt;
#Choisir le statut de l&#039;extension à activer pour enclencher le renvoi vers l&#039;astreinte. Dans l&#039;exemple &#039;&#039;&#039;Absent&#039;&#039;&#039;. Pas l&#039;état &#039;&#039;&#039;Disponible&#039;&#039;&#039; évidemment.&lt;br /&gt;
#Dans &amp;quot;Transférer les appels externes à&amp;quot;, choisir &#039;&#039;&#039;Mon mobile&#039;&#039;&#039;&lt;br /&gt;
#Cocher &#039;&#039;&#039;Rebond&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
===Déclaration du script===&lt;br /&gt;
[[Fichier:2026-04-02 17h11 35.png|vignette]]&lt;br /&gt;
&lt;br /&gt;
Rendez-vous dans :&lt;br /&gt;
&lt;br /&gt;
 Admin / Intégrations / Scripts d&#039;appels / + Ajouter personnalisé&lt;br /&gt;
&lt;br /&gt;
#Donner un nom au traitement de l&#039;appel. Exemple : &#039;&#039;&#039;astreinte_weekend&#039;&#039;&#039;&lt;br /&gt;
#Créer un code de raccourci, ce qui permettra d&#039;exécuter le script simplement en appelant ce code, et in fine par une BLF. Exemple : &#039;&#039;&#039;*99&#039;&#039;&#039;&lt;br /&gt;
#OK&lt;br /&gt;
#Coller dans le champ script le script paramétré ( voir section suivante )&lt;br /&gt;
#Sauvegarder&lt;br /&gt;
#Un message doit indiquer &#039;&#039;&#039;Compilation réussie !&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Le script d&#039;astreinte===&lt;br /&gt;
&lt;br /&gt;
L&#039;éxécution du script va modifier l&#039;extension &#039;&#039;&#039;targetExtNum &#039;&#039;&#039;, il va le basculer sur le statut &#039;&#039;&#039;profileName &#039;&#039;&#039;, modifier son mobile de contact &#039;&#039;&#039;mobileElu &#039;&#039;&#039;, son nom et prénom.&lt;br /&gt;
&lt;br /&gt;
Il faut donc seulement modifier les lignes surlignés dans le code ci-dessous :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;csharp&amp;quot; line highlight=&amp;quot;14-17&amp;quot;&amp;gt;&lt;br /&gt;
using System;&lt;br /&gt;
using System.Threading.Tasks;&lt;br /&gt;
using TCX.Configuration;&lt;br /&gt;
using CallFlow;&lt;br /&gt;
using System.Linq;&lt;br /&gt;
&lt;br /&gt;
namespace dummy&lt;br /&gt;
{&lt;br /&gt;
    public class SetDynamicAstreinte : ScriptBase&amp;lt;SetDynamicAstreinte&amp;gt;&lt;br /&gt;
    {&lt;br /&gt;
        // ============================================================&lt;br /&gt;
        // CONFIGURATION — modifier uniquement ces lignes par script&lt;br /&gt;
        // ============================================================&lt;br /&gt;
        private const string TARGET_EXT   = &amp;quot;111&amp;quot;;&lt;br /&gt;
        private const string MOBILE_ELU   = &amp;quot;0612345678&amp;quot;;&lt;br /&gt;
        private const string PRENOM_ELU   = &amp;quot;Claude&amp;quot;;&lt;br /&gt;
        private const string NOM_ELU      = &amp;quot;IA&amp;quot;;&lt;br /&gt;
        private const string PROFILE_NAME = &amp;quot;Away&amp;quot;;&lt;br /&gt;
        // ============================================================&lt;br /&gt;
&lt;br /&gt;
        public override Task&amp;lt;bool&amp;gt; StartAsync()&lt;br /&gt;
        {&lt;br /&gt;
            try&lt;br /&gt;
            {&lt;br /&gt;
                IPhoneSystem ps = PhoneSystem.Root;&lt;br /&gt;
                Extension ext = ps.GetDNByNumber(TARGET_EXT) as Extension;&lt;br /&gt;
                if (ext == null)&lt;br /&gt;
                    return Task.FromResult(false);&lt;br /&gt;
&lt;br /&gt;
                // 1. Nom / Prénom&lt;br /&gt;
                ext.FirstName = PRENOM_ELU;&lt;br /&gt;
                ext.LastName  = NOM_ELU;&lt;br /&gt;
&lt;br /&gt;
                // 2. Numéro mobile&lt;br /&gt;
                ext.SetProperty(&amp;quot;MOBILENUMBER&amp;quot;, MOBILE_ELU);&lt;br /&gt;
&lt;br /&gt;
                // 3. Trouver le profil Away&lt;br /&gt;
                FwdProfile targetProfile = ext.FwdProfiles&lt;br /&gt;
                    .FirstOrDefault(p =&amp;gt; p.Name.Equals(&lt;br /&gt;
                        PROFILE_NAME, StringComparison.OrdinalIgnoreCase));&lt;br /&gt;
&lt;br /&gt;
                if (targetProfile != null)&lt;br /&gt;
                {&lt;br /&gt;
                    // AwayRoute, Internal, External sont read-only&lt;br /&gt;
                    // mais ce sont des références : on peut modifier&lt;br /&gt;
                    // leurs membres si ceux-ci sont accessibles en écriture&lt;br /&gt;
                    AwayRouting route = targetProfile.AwayRoute;&lt;br /&gt;
&lt;br /&gt;
                    // Capturer les HoursDestination comme variables locales&lt;br /&gt;
                    // (objets référence — la propriété est read-only,&lt;br /&gt;
                    //  mais l&#039;objet pointé est modifiable)&lt;br /&gt;
                    HoursDestination internalHours = route.Internal;&lt;br /&gt;
                    HoursDestination externalHours = route.External;&lt;br /&gt;
&lt;br /&gt;
                    // Capturer AllHours (struct) → modifier → réassigner&lt;br /&gt;
                    DestinationStruct destInternal = internalHours.AllHours;&lt;br /&gt;
                    destInternal.To               = DestinationType.Boomerang;&lt;br /&gt;
                    destInternal.External         = MOBILE_ELU;&lt;br /&gt;
                    internalHours.AllHours        = destInternal;&lt;br /&gt;
&lt;br /&gt;
                    DestinationStruct destExternal = externalHours.AllHours;&lt;br /&gt;
                    destExternal.To               = DestinationType.Boomerang;&lt;br /&gt;
                    destExternal.External         = MOBILE_ELU;&lt;br /&gt;
                    externalHours.AllHours        = destExternal;&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                // 4. Sauvegarder&lt;br /&gt;
                ext.Save();&lt;br /&gt;
&lt;br /&gt;
                // 5. Recharger et basculer le profil&lt;br /&gt;
                ext = ps.GetDNByNumber(TARGET_EXT) as Extension;&lt;br /&gt;
                if (ext == null)&lt;br /&gt;
                    return Task.FromResult(false);&lt;br /&gt;
&lt;br /&gt;
                FwdProfile profile = ext.FwdProfiles&lt;br /&gt;
                    .FirstOrDefault(p =&amp;gt; p.Name.Equals(&lt;br /&gt;
                        PROFILE_NAME, StringComparison.OrdinalIgnoreCase));&lt;br /&gt;
&lt;br /&gt;
                if (profile != null)&lt;br /&gt;
                {&lt;br /&gt;
                    ext.CurrentProfile = profile;&lt;br /&gt;
                    ext.Save();&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                return Task.FromResult(true);&lt;br /&gt;
            }&lt;br /&gt;
            catch (Exception)&lt;br /&gt;
            {&lt;br /&gt;
                return Task.FromResult(false);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Le script de retour à la normale===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;csharp&amp;quot; line highlight=&amp;quot;14-17&amp;quot;&amp;gt;&lt;br /&gt;
using System;&lt;br /&gt;
using System.Threading.Tasks;&lt;br /&gt;
using TCX.Configuration;&lt;br /&gt;
using CallFlow;&lt;br /&gt;
using System.Linq;&lt;br /&gt;
&lt;br /&gt;
namespace dummy&lt;br /&gt;
{&lt;br /&gt;
    public class ResetAstreinte : ScriptBase&amp;lt;ResetAstreinte&amp;gt;&lt;br /&gt;
    {&lt;br /&gt;
        // ============================================================&lt;br /&gt;
        // CONFIGURATION — valeurs par défaut quand personne n&#039;est d&#039;astreinte&lt;br /&gt;
        // ============================================================&lt;br /&gt;
        private const string TARGET_EXT   = &amp;quot;111&amp;quot;;&lt;br /&gt;
        private const string PRENOM_EXT   = &amp;quot;Anthony&amp;quot;;&lt;br /&gt;
        private const string NOM_EXT      = &amp;quot;&amp;quot;;&lt;br /&gt;
        // ============================================================&lt;br /&gt;
&lt;br /&gt;
        public override Task&amp;lt;bool&amp;gt; StartAsync()&lt;br /&gt;
        {&lt;br /&gt;
            try&lt;br /&gt;
            {&lt;br /&gt;
                IPhoneSystem ps = PhoneSystem.Root;&lt;br /&gt;
                Extension ext = ps.GetDNByNumber(TARGET_EXT) as Extension;&lt;br /&gt;
                if (ext == null)&lt;br /&gt;
                    return Task.FromResult(false);&lt;br /&gt;
&lt;br /&gt;
                // 1. Remettre le nom générique&lt;br /&gt;
                ext.FirstName = PRENOM_EXT;&lt;br /&gt;
                ext.LastName  = NOM_EXT;&lt;br /&gt;
&lt;br /&gt;
                // 2. Vider le numéro mobile&lt;br /&gt;
                ext.SetProperty(&amp;quot;MOBILENUMBER&amp;quot;, &amp;quot;&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
                // 3. Sauvegarder&lt;br /&gt;
                ext.Save();&lt;br /&gt;
&lt;br /&gt;
                // 4. Recharger et basculer vers Available&lt;br /&gt;
                ext = ps.GetDNByNumber(TARGET_EXT) as Extension;&lt;br /&gt;
                if (ext == null)&lt;br /&gt;
                    return Task.FromResult(false);&lt;br /&gt;
&lt;br /&gt;
                FwdProfile profile = ext.FwdProfiles&lt;br /&gt;
                    .FirstOrDefault(p =&amp;gt; p.Name.Equals(&lt;br /&gt;
                        &amp;quot;Available&amp;quot;, StringComparison.OrdinalIgnoreCase));&lt;br /&gt;
&lt;br /&gt;
                if (profile != null)&lt;br /&gt;
                {&lt;br /&gt;
                    ext.CurrentProfile = profile;&lt;br /&gt;
                    ext.Save();&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                return Task.FromResult(true);&lt;br /&gt;
            }&lt;br /&gt;
            catch (Exception)&lt;br /&gt;
            {&lt;br /&gt;
                return Task.FromResult(false);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Table de correspondance des profileName====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Dans 3CX!! Dans le script&lt;br /&gt;
|-&lt;br /&gt;
| Disponible|| Available&lt;br /&gt;
|-&lt;br /&gt;
| Absent|| Away&lt;br /&gt;
|-&lt;br /&gt;
| Ne pas déranger|| Out of office&lt;br /&gt;
|-&lt;br /&gt;
| Custom 1|| Custom 1&lt;br /&gt;
|-&lt;br /&gt;
| Custom 2|| Custom 2&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===Configuration concrète===&lt;br /&gt;
&lt;br /&gt;
Il faut choisir un statut autre que &amp;quot;Disponible&amp;quot; qui sera activé pour l&#039;astreinte, &amp;quot;Away&amp;quot; pour cet exemple&lt;br /&gt;
&lt;br /&gt;
On a besoin de gérer deux astreintes. Le poste Accueil reçoit les appels en temps normal&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Texte de la légende&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;Marcel Patulacci&#039;&#039;&#039; || &#039;&#039;&#039;Jean-Michel Apeuprè&#039;&#039;&#039;|| &#039;&#039;&#039;Poste accueil &#039;&#039;&#039; hors période d&#039;astreinte&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;syntaxhighlight lang=&amp;quot;csharp&amp;quot; line highlight=&amp;quot;3-5,8-9&amp;quot;&amp;gt;&lt;br /&gt;
public override Task&amp;lt;bool&amp;gt; StartAsync()&lt;br /&gt;
        {&lt;br /&gt;
            string targetExtNum = &amp;quot;100&amp;quot;; &lt;br /&gt;
            string mobileElu = &amp;quot;0699999999&amp;quot;;&lt;br /&gt;
            string profileName = &amp;quot;Away&amp;quot;; &lt;br /&gt;
&lt;br /&gt;
            // Nommage de l&#039;astreinte&lt;br /&gt;
            string prenomElu = &amp;quot;Marcel&amp;quot;; &lt;br /&gt;
            string nomElu = &amp;quot;Patulacci&amp;quot;; &lt;br /&gt;
&lt;br /&gt;
            try&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt; || &amp;lt;syntaxhighlight lang=&amp;quot;csharp&amp;quot; line highlight=&amp;quot;3-5,8-9&amp;quot;&amp;gt;&lt;br /&gt;
public override Task&amp;lt;bool&amp;gt; StartAsync()&lt;br /&gt;
        {&lt;br /&gt;
            string targetExtNum = &amp;quot;100&amp;quot;; &lt;br /&gt;
            string mobileElu = &amp;quot;0688888888&amp;quot;;&lt;br /&gt;
            string profileName = &amp;quot;Away&amp;quot;; &lt;br /&gt;
&lt;br /&gt;
            // Nommage de l&#039;astreinte&lt;br /&gt;
            string prenomElu = &amp;quot;Jean-Michel&amp;quot;; &lt;br /&gt;
            string nomElu = &amp;quot;Apeuprè&amp;quot;; &lt;br /&gt;
&lt;br /&gt;
            try&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;|| &amp;lt;syntaxhighlight lang=&amp;quot;csharp&amp;quot; line highlight=&amp;quot;3-5,8-9&amp;quot;&amp;gt;&lt;br /&gt;
public override Task&amp;lt;bool&amp;gt; StartAsync()&lt;br /&gt;
        {&lt;br /&gt;
            string targetExtNum = &amp;quot;100&amp;quot;; &lt;br /&gt;
            string mobileElu = &amp;quot;&amp;quot;;&lt;br /&gt;
            string profileName = &amp;quot;Available&amp;quot;; &lt;br /&gt;
&lt;br /&gt;
            // Nommage de l&#039;astreinte&lt;br /&gt;
            string prenomElu = &amp;quot;Accueil&amp;quot;; &lt;br /&gt;
            string nomElu = &amp;quot;&amp;quot;; &lt;br /&gt;
&lt;br /&gt;
            try&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Une fois les 3 scripts produits, passer à l&#039;étape [[Astreinte#Déclaration_du_script|Déclaration du script]] qui va permettre d&#039;affecter un code court à chaque script.&lt;br /&gt;
Exemple : &lt;br /&gt;
* *90 pour hors période d&#039;astreinte&lt;br /&gt;
* *91 pour Jean-Michel&lt;br /&gt;
* *92 pour Marcel&lt;br /&gt;
&lt;br /&gt;
On peut communiquer les codes aux personnes habilitées à gérer le système d&#039;astreinte et aller jusqu&#039;à paramétrer des BLF pour faciliter la vie d&#039;une secrétaire par exemple.&lt;br /&gt;
&lt;br /&gt;
{{Valide|v20}}&lt;br /&gt;
[[Catégorie:3CX]]&lt;/div&gt;</summary>
		<author><name>Anthony</name></author>
	</entry>
	<entry>
		<id>https://indywiki.fr/index.php?title=Astreinte&amp;diff=22257</id>
		<title>Astreinte</title>
		<link rel="alternate" type="text/html" href="https://indywiki.fr/index.php?title=Astreinte&amp;diff=22257"/>
		<updated>2026-04-28T12:12:01Z</updated>

		<summary type="html">&lt;p&gt;Anthony : /* Le script d&amp;#039;astreinte */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;===Principe===&lt;br /&gt;
On paramètre le statut choisi pour l&#039;astreinte en renvoi vers &#039;&#039;&#039;mon mobile&#039;&#039;&#039;. Un script viendra modifier le statut de l&#039;extension cible ainsi que son numéro de contact mobile, prénom et nom. Ce script déclenchable par l&#039;appel à un code court, paramétrable si on le souhaite sur une BLF. &lt;br /&gt;
===Paramétrage du statut de l&#039;extension vers &#039;&#039;&#039;mon mobile&#039;&#039;&#039;===&lt;br /&gt;
[[Fichier:2026-04-03 13h29 01.png|vignette]]&lt;br /&gt;
#Réglages&lt;br /&gt;
#Transfert d&#039;appels&lt;br /&gt;
#Choisir le statut de l&#039;extension à activer pour enclencher le renvoi vers l&#039;astreinte. Dans l&#039;exemple &#039;&#039;&#039;Absent&#039;&#039;&#039;. Pas l&#039;état &#039;&#039;&#039;Disponible&#039;&#039;&#039; évidemment.&lt;br /&gt;
#Dans &amp;quot;Transférer les appels externes à&amp;quot;, choisir &#039;&#039;&#039;Mon mobile&#039;&#039;&#039;&lt;br /&gt;
#Cocher &#039;&#039;&#039;Rebond&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
===Déclaration du script===&lt;br /&gt;
[[Fichier:2026-04-02 17h11 35.png|vignette]]&lt;br /&gt;
&lt;br /&gt;
Rendez-vous dans :&lt;br /&gt;
&lt;br /&gt;
 Admin / Intégrations / Scripts d&#039;appels / + Ajouter personnalisé&lt;br /&gt;
&lt;br /&gt;
#Donner un nom au traitement de l&#039;appel. Exemple : &#039;&#039;&#039;astreinte_weekend&#039;&#039;&#039;&lt;br /&gt;
#Créer un code de raccourci, ce qui permettra d&#039;exécuter le script simplement en appelant ce code, et in fine par une BLF. Exemple : &#039;&#039;&#039;*99&#039;&#039;&#039;&lt;br /&gt;
#OK&lt;br /&gt;
#Coller dans le champ script le script paramétré ( voir section suivante )&lt;br /&gt;
#Sauvegarder&lt;br /&gt;
#Un message doit indiquer &#039;&#039;&#039;Compilation réussie !&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Le script d&#039;astreinte===&lt;br /&gt;
&lt;br /&gt;
L&#039;éxécution du script va modifier l&#039;extension &#039;&#039;&#039;targetExtNum &#039;&#039;&#039;, il va le basculer sur le statut &#039;&#039;&#039;profileName &#039;&#039;&#039;, modifier son mobile de contact &#039;&#039;&#039;mobileElu &#039;&#039;&#039;, son nom et prénom.&lt;br /&gt;
&lt;br /&gt;
Il faut donc seulement modifier les lignes surlignés dans le code ci-dessous :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;csharp&amp;quot; line highlight=&amp;quot;14-17&amp;quot;&amp;gt;&lt;br /&gt;
using System;&lt;br /&gt;
using System.Threading.Tasks;&lt;br /&gt;
using TCX.Configuration;&lt;br /&gt;
using CallFlow;&lt;br /&gt;
using System.Linq;&lt;br /&gt;
&lt;br /&gt;
namespace dummy&lt;br /&gt;
{&lt;br /&gt;
    public class SetDynamicAstreinte : ScriptBase&amp;lt;SetDynamicAstreinte&amp;gt;&lt;br /&gt;
    {&lt;br /&gt;
        // ============================================================&lt;br /&gt;
        // CONFIGURATION — modifier uniquement ces lignes par script&lt;br /&gt;
        // ============================================================&lt;br /&gt;
        private const string TARGET_EXT   = &amp;quot;111&amp;quot;;&lt;br /&gt;
        private const string MOBILE_ELU   = &amp;quot;0612345678&amp;quot;;&lt;br /&gt;
        private const string PRENOM_ELU   = &amp;quot;Claude&amp;quot;;&lt;br /&gt;
        private const string NOM_ELU      = &amp;quot;IA&amp;quot;;&lt;br /&gt;
        private const string PROFILE_NAME = &amp;quot;Away&amp;quot;;&lt;br /&gt;
        // ============================================================&lt;br /&gt;
&lt;br /&gt;
        public override Task&amp;lt;bool&amp;gt; StartAsync()&lt;br /&gt;
        {&lt;br /&gt;
            try&lt;br /&gt;
            {&lt;br /&gt;
                IPhoneSystem ps = PhoneSystem.Root;&lt;br /&gt;
                Extension ext = ps.GetDNByNumber(TARGET_EXT) as Extension;&lt;br /&gt;
                if (ext == null)&lt;br /&gt;
                    return Task.FromResult(false);&lt;br /&gt;
&lt;br /&gt;
                // 1. Nom / Prénom&lt;br /&gt;
                ext.FirstName = PRENOM_ELU;&lt;br /&gt;
                ext.LastName  = NOM_ELU;&lt;br /&gt;
&lt;br /&gt;
                // 2. Numéro mobile&lt;br /&gt;
                ext.SetProperty(&amp;quot;MOBILENUMBER&amp;quot;, MOBILE_ELU);&lt;br /&gt;
&lt;br /&gt;
                // 3. Trouver le profil Away&lt;br /&gt;
                FwdProfile targetProfile = ext.FwdProfiles&lt;br /&gt;
                    .FirstOrDefault(p =&amp;gt; p.Name.Equals(&lt;br /&gt;
                        PROFILE_NAME, StringComparison.OrdinalIgnoreCase));&lt;br /&gt;
&lt;br /&gt;
                if (targetProfile != null)&lt;br /&gt;
                {&lt;br /&gt;
                    // AwayRoute, Internal, External sont read-only&lt;br /&gt;
                    // mais ce sont des références : on peut modifier&lt;br /&gt;
                    // leurs membres si ceux-ci sont accessibles en écriture&lt;br /&gt;
                    AwayRouting route = targetProfile.AwayRoute;&lt;br /&gt;
&lt;br /&gt;
                    // Capturer les HoursDestination comme variables locales&lt;br /&gt;
                    // (objets référence — la propriété est read-only,&lt;br /&gt;
                    //  mais l&#039;objet pointé est modifiable)&lt;br /&gt;
                    HoursDestination internalHours = route.Internal;&lt;br /&gt;
                    HoursDestination externalHours = route.External;&lt;br /&gt;
&lt;br /&gt;
                    // Capturer AllHours (struct) → modifier → réassigner&lt;br /&gt;
                    DestinationStruct destInternal = internalHours.AllHours;&lt;br /&gt;
                    destInternal.To               = DestinationType.Boomerang;&lt;br /&gt;
                    destInternal.External         = MOBILE_ELU;&lt;br /&gt;
                    internalHours.AllHours        = destInternal;&lt;br /&gt;
&lt;br /&gt;
                    DestinationStruct destExternal = externalHours.AllHours;&lt;br /&gt;
                    destExternal.To               = DestinationType.Boomerang;&lt;br /&gt;
                    destExternal.External         = MOBILE_ELU;&lt;br /&gt;
                    externalHours.AllHours        = destExternal;&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                // 4. Sauvegarder&lt;br /&gt;
                ext.Save();&lt;br /&gt;
&lt;br /&gt;
                // 5. Recharger et basculer le profil&lt;br /&gt;
                ext = ps.GetDNByNumber(TARGET_EXT) as Extension;&lt;br /&gt;
                if (ext == null)&lt;br /&gt;
                    return Task.FromResult(false);&lt;br /&gt;
&lt;br /&gt;
                FwdProfile profile = ext.FwdProfiles&lt;br /&gt;
                    .FirstOrDefault(p =&amp;gt; p.Name.Equals(&lt;br /&gt;
                        PROFILE_NAME, StringComparison.OrdinalIgnoreCase));&lt;br /&gt;
&lt;br /&gt;
                if (profile != null)&lt;br /&gt;
                {&lt;br /&gt;
                    ext.CurrentProfile = profile;&lt;br /&gt;
                    ext.Save();&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                return Task.FromResult(true);&lt;br /&gt;
            }&lt;br /&gt;
            catch (Exception)&lt;br /&gt;
            {&lt;br /&gt;
                return Task.FromResult(false);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Table de correspondance des profileName====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Dans 3CX!! Dans le script&lt;br /&gt;
|-&lt;br /&gt;
| Disponible|| Available&lt;br /&gt;
|-&lt;br /&gt;
| Absent|| Away&lt;br /&gt;
|-&lt;br /&gt;
| Ne pas déranger|| Out of office&lt;br /&gt;
|-&lt;br /&gt;
| Custom 1|| Custom 1&lt;br /&gt;
|-&lt;br /&gt;
| Custom 2|| Custom 2&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===Configuration concrète===&lt;br /&gt;
&lt;br /&gt;
Il faut choisir un statut autre que &amp;quot;Disponible&amp;quot; qui sera activé pour l&#039;astreinte, &amp;quot;Away&amp;quot; pour cet exemple&lt;br /&gt;
&lt;br /&gt;
On a besoin de gérer deux astreintes. Le poste Accueil reçoit les appels en temps normal&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Texte de la légende&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;Marcel Patulacci&#039;&#039;&#039; || &#039;&#039;&#039;Jean-Michel Apeuprè&#039;&#039;&#039;|| &#039;&#039;&#039;Poste accueil &#039;&#039;&#039; hors période d&#039;astreinte&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;syntaxhighlight lang=&amp;quot;csharp&amp;quot; line highlight=&amp;quot;3-5,8-9&amp;quot;&amp;gt;&lt;br /&gt;
public override Task&amp;lt;bool&amp;gt; StartAsync()&lt;br /&gt;
        {&lt;br /&gt;
            string targetExtNum = &amp;quot;100&amp;quot;; &lt;br /&gt;
            string mobileElu = &amp;quot;0699999999&amp;quot;;&lt;br /&gt;
            string profileName = &amp;quot;Away&amp;quot;; &lt;br /&gt;
&lt;br /&gt;
            // Nommage de l&#039;astreinte&lt;br /&gt;
            string prenomElu = &amp;quot;Marcel&amp;quot;; &lt;br /&gt;
            string nomElu = &amp;quot;Patulacci&amp;quot;; &lt;br /&gt;
&lt;br /&gt;
            try&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt; || &amp;lt;syntaxhighlight lang=&amp;quot;csharp&amp;quot; line highlight=&amp;quot;3-5,8-9&amp;quot;&amp;gt;&lt;br /&gt;
public override Task&amp;lt;bool&amp;gt; StartAsync()&lt;br /&gt;
        {&lt;br /&gt;
            string targetExtNum = &amp;quot;100&amp;quot;; &lt;br /&gt;
            string mobileElu = &amp;quot;0688888888&amp;quot;;&lt;br /&gt;
            string profileName = &amp;quot;Away&amp;quot;; &lt;br /&gt;
&lt;br /&gt;
            // Nommage de l&#039;astreinte&lt;br /&gt;
            string prenomElu = &amp;quot;Jean-Michel&amp;quot;; &lt;br /&gt;
            string nomElu = &amp;quot;Apeuprè&amp;quot;; &lt;br /&gt;
&lt;br /&gt;
            try&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;|| &amp;lt;syntaxhighlight lang=&amp;quot;csharp&amp;quot; line highlight=&amp;quot;3-5,8-9&amp;quot;&amp;gt;&lt;br /&gt;
public override Task&amp;lt;bool&amp;gt; StartAsync()&lt;br /&gt;
        {&lt;br /&gt;
            string targetExtNum = &amp;quot;100&amp;quot;; &lt;br /&gt;
            string mobileElu = &amp;quot;&amp;quot;;&lt;br /&gt;
            string profileName = &amp;quot;Available&amp;quot;; &lt;br /&gt;
&lt;br /&gt;
            // Nommage de l&#039;astreinte&lt;br /&gt;
            string prenomElu = &amp;quot;Accueil&amp;quot;; &lt;br /&gt;
            string nomElu = &amp;quot;&amp;quot;; &lt;br /&gt;
&lt;br /&gt;
            try&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Une fois les 3 scripts produits, passer à l&#039;étape [[Astreinte#Déclaration_du_script|Déclaration du script]] qui va permettre d&#039;affecter un code court à chaque script.&lt;br /&gt;
Exemple : &lt;br /&gt;
* *90 pour hors période d&#039;astreinte&lt;br /&gt;
* *91 pour Jean-Michel&lt;br /&gt;
* *92 pour Marcel&lt;br /&gt;
&lt;br /&gt;
On peut communiquer les codes aux personnes habilitées à gérer le système d&#039;astreinte et aller jusqu&#039;à paramétrer des BLF pour faciliter la vie d&#039;une secrétaire par exemple.&lt;br /&gt;
&lt;br /&gt;
{{Valide|v20}}&lt;br /&gt;
[[Catégorie:3CX]]&lt;/div&gt;</summary>
		<author><name>Anthony</name></author>
	</entry>
	<entry>
		<id>https://indywiki.fr/index.php?title=Astreinte&amp;diff=22256</id>
		<title>Astreinte</title>
		<link rel="alternate" type="text/html" href="https://indywiki.fr/index.php?title=Astreinte&amp;diff=22256"/>
		<updated>2026-04-28T12:09:57Z</updated>

		<summary type="html">&lt;p&gt;Anthony : /* Le script */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;===Principe===&lt;br /&gt;
On paramètre le statut choisi pour l&#039;astreinte en renvoi vers &#039;&#039;&#039;mon mobile&#039;&#039;&#039;. Un script viendra modifier le statut de l&#039;extension cible ainsi que son numéro de contact mobile, prénom et nom. Ce script déclenchable par l&#039;appel à un code court, paramétrable si on le souhaite sur une BLF. &lt;br /&gt;
===Paramétrage du statut de l&#039;extension vers &#039;&#039;&#039;mon mobile&#039;&#039;&#039;===&lt;br /&gt;
[[Fichier:2026-04-03 13h29 01.png|vignette]]&lt;br /&gt;
#Réglages&lt;br /&gt;
#Transfert d&#039;appels&lt;br /&gt;
#Choisir le statut de l&#039;extension à activer pour enclencher le renvoi vers l&#039;astreinte. Dans l&#039;exemple &#039;&#039;&#039;Absent&#039;&#039;&#039;. Pas l&#039;état &#039;&#039;&#039;Disponible&#039;&#039;&#039; évidemment.&lt;br /&gt;
#Dans &amp;quot;Transférer les appels externes à&amp;quot;, choisir &#039;&#039;&#039;Mon mobile&#039;&#039;&#039;&lt;br /&gt;
#Cocher &#039;&#039;&#039;Rebond&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
===Déclaration du script===&lt;br /&gt;
[[Fichier:2026-04-02 17h11 35.png|vignette]]&lt;br /&gt;
&lt;br /&gt;
Rendez-vous dans :&lt;br /&gt;
&lt;br /&gt;
 Admin / Intégrations / Scripts d&#039;appels / + Ajouter personnalisé&lt;br /&gt;
&lt;br /&gt;
#Donner un nom au traitement de l&#039;appel. Exemple : &#039;&#039;&#039;astreinte_weekend&#039;&#039;&#039;&lt;br /&gt;
#Créer un code de raccourci, ce qui permettra d&#039;exécuter le script simplement en appelant ce code, et in fine par une BLF. Exemple : &#039;&#039;&#039;*99&#039;&#039;&#039;&lt;br /&gt;
#OK&lt;br /&gt;
#Coller dans le champ script le script paramétré ( voir section suivante )&lt;br /&gt;
#Sauvegarder&lt;br /&gt;
#Un message doit indiquer &#039;&#039;&#039;Compilation réussie !&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Le script d&#039;astreinte===&lt;br /&gt;
&lt;br /&gt;
L&#039;éxécution du script va modifier l&#039;extension &#039;&#039;&#039;targetExtNum &#039;&#039;&#039;, il va le basculer sur le statut &#039;&#039;&#039;profileName &#039;&#039;&#039;, modifier son mobile de contact &#039;&#039;&#039;mobileElu &#039;&#039;&#039;, son nom et prénom.&lt;br /&gt;
&lt;br /&gt;
Il faut donc seulement modifier les lignes surlignés dans le code ci-dessous :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;csharp&amp;quot; line highlight=&amp;quot;14-16,19-20&amp;quot;&amp;gt;&lt;br /&gt;
using System;&lt;br /&gt;
using System.Threading.Tasks;&lt;br /&gt;
using TCX.Configuration;&lt;br /&gt;
using CallFlow;&lt;br /&gt;
using System.Linq;&lt;br /&gt;
&lt;br /&gt;
namespace dummy&lt;br /&gt;
{&lt;br /&gt;
    public class SetDynamicAstreinte : ScriptBase&amp;lt;SetDynamicAstreinte&amp;gt;&lt;br /&gt;
    {&lt;br /&gt;
        // ============================================================&lt;br /&gt;
        // CONFIGURATION — modifier uniquement ces lignes par script&lt;br /&gt;
        // ============================================================&lt;br /&gt;
        private const string TARGET_EXT   = &amp;quot;111&amp;quot;;&lt;br /&gt;
        private const string MOBILE_ELU   = &amp;quot;0663394524&amp;quot;;&lt;br /&gt;
        private const string PRENOM_ELU   = &amp;quot;Claude&amp;quot;;&lt;br /&gt;
        private const string NOM_ELU      = &amp;quot;IA&amp;quot;;&lt;br /&gt;
        private const string PROFILE_NAME = &amp;quot;Away&amp;quot;;&lt;br /&gt;
        // ============================================================&lt;br /&gt;
&lt;br /&gt;
        public override Task&amp;lt;bool&amp;gt; StartAsync()&lt;br /&gt;
        {&lt;br /&gt;
            try&lt;br /&gt;
            {&lt;br /&gt;
                IPhoneSystem ps = PhoneSystem.Root;&lt;br /&gt;
                Extension ext = ps.GetDNByNumber(TARGET_EXT) as Extension;&lt;br /&gt;
                if (ext == null)&lt;br /&gt;
                    return Task.FromResult(false);&lt;br /&gt;
&lt;br /&gt;
                // 1. Nom / Prénom&lt;br /&gt;
                ext.FirstName = PRENOM_ELU;&lt;br /&gt;
                ext.LastName  = NOM_ELU;&lt;br /&gt;
&lt;br /&gt;
                // 2. Numéro mobile&lt;br /&gt;
                ext.SetProperty(&amp;quot;MOBILENUMBER&amp;quot;, MOBILE_ELU);&lt;br /&gt;
&lt;br /&gt;
                // 3. Trouver le profil Away&lt;br /&gt;
                FwdProfile targetProfile = ext.FwdProfiles&lt;br /&gt;
                    .FirstOrDefault(p =&amp;gt; p.Name.Equals(&lt;br /&gt;
                        PROFILE_NAME, StringComparison.OrdinalIgnoreCase));&lt;br /&gt;
&lt;br /&gt;
                if (targetProfile != null)&lt;br /&gt;
                {&lt;br /&gt;
                    // AwayRoute, Internal, External sont read-only&lt;br /&gt;
                    // mais ce sont des références : on peut modifier&lt;br /&gt;
                    // leurs membres si ceux-ci sont accessibles en écriture&lt;br /&gt;
                    AwayRouting route = targetProfile.AwayRoute;&lt;br /&gt;
&lt;br /&gt;
                    // Capturer les HoursDestination comme variables locales&lt;br /&gt;
                    // (objets référence — la propriété est read-only,&lt;br /&gt;
                    //  mais l&#039;objet pointé est modifiable)&lt;br /&gt;
                    HoursDestination internalHours = route.Internal;&lt;br /&gt;
                    HoursDestination externalHours = route.External;&lt;br /&gt;
&lt;br /&gt;
                    // Capturer AllHours (struct) → modifier → réassigner&lt;br /&gt;
                    DestinationStruct destInternal = internalHours.AllHours;&lt;br /&gt;
                    destInternal.To               = DestinationType.Boomerang;&lt;br /&gt;
                    destInternal.External         = MOBILE_ELU;&lt;br /&gt;
                    internalHours.AllHours        = destInternal;&lt;br /&gt;
&lt;br /&gt;
                    DestinationStruct destExternal = externalHours.AllHours;&lt;br /&gt;
                    destExternal.To               = DestinationType.Boomerang;&lt;br /&gt;
                    destExternal.External         = MOBILE_ELU;&lt;br /&gt;
                    externalHours.AllHours        = destExternal;&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                // 4. Sauvegarder&lt;br /&gt;
                ext.Save();&lt;br /&gt;
&lt;br /&gt;
                // 5. Recharger et basculer le profil&lt;br /&gt;
                ext = ps.GetDNByNumber(TARGET_EXT) as Extension;&lt;br /&gt;
                if (ext == null)&lt;br /&gt;
                    return Task.FromResult(false);&lt;br /&gt;
&lt;br /&gt;
                FwdProfile profile = ext.FwdProfiles&lt;br /&gt;
                    .FirstOrDefault(p =&amp;gt; p.Name.Equals(&lt;br /&gt;
                        PROFILE_NAME, StringComparison.OrdinalIgnoreCase));&lt;br /&gt;
&lt;br /&gt;
                if (profile != null)&lt;br /&gt;
                {&lt;br /&gt;
                    ext.CurrentProfile = profile;&lt;br /&gt;
                    ext.Save();&lt;br /&gt;
                }&lt;br /&gt;
&lt;br /&gt;
                return Task.FromResult(true);&lt;br /&gt;
            }&lt;br /&gt;
            catch (Exception)&lt;br /&gt;
            {&lt;br /&gt;
                return Task.FromResult(false);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Table de correspondance des profileName====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Dans 3CX!! Dans le script&lt;br /&gt;
|-&lt;br /&gt;
| Disponible|| Available&lt;br /&gt;
|-&lt;br /&gt;
| Absent|| Away&lt;br /&gt;
|-&lt;br /&gt;
| Ne pas déranger|| Out of office&lt;br /&gt;
|-&lt;br /&gt;
| Custom 1|| Custom 1&lt;br /&gt;
|-&lt;br /&gt;
| Custom 2|| Custom 2&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===Configuration concrète===&lt;br /&gt;
&lt;br /&gt;
Il faut choisir un statut autre que &amp;quot;Disponible&amp;quot; qui sera activé pour l&#039;astreinte, &amp;quot;Away&amp;quot; pour cet exemple&lt;br /&gt;
&lt;br /&gt;
On a besoin de gérer deux astreintes. Le poste Accueil reçoit les appels en temps normal&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Texte de la légende&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;Marcel Patulacci&#039;&#039;&#039; || &#039;&#039;&#039;Jean-Michel Apeuprè&#039;&#039;&#039;|| &#039;&#039;&#039;Poste accueil &#039;&#039;&#039; hors période d&#039;astreinte&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;syntaxhighlight lang=&amp;quot;csharp&amp;quot; line highlight=&amp;quot;3-5,8-9&amp;quot;&amp;gt;&lt;br /&gt;
public override Task&amp;lt;bool&amp;gt; StartAsync()&lt;br /&gt;
        {&lt;br /&gt;
            string targetExtNum = &amp;quot;100&amp;quot;; &lt;br /&gt;
            string mobileElu = &amp;quot;0699999999&amp;quot;;&lt;br /&gt;
            string profileName = &amp;quot;Away&amp;quot;; &lt;br /&gt;
&lt;br /&gt;
            // Nommage de l&#039;astreinte&lt;br /&gt;
            string prenomElu = &amp;quot;Marcel&amp;quot;; &lt;br /&gt;
            string nomElu = &amp;quot;Patulacci&amp;quot;; &lt;br /&gt;
&lt;br /&gt;
            try&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt; || &amp;lt;syntaxhighlight lang=&amp;quot;csharp&amp;quot; line highlight=&amp;quot;3-5,8-9&amp;quot;&amp;gt;&lt;br /&gt;
public override Task&amp;lt;bool&amp;gt; StartAsync()&lt;br /&gt;
        {&lt;br /&gt;
            string targetExtNum = &amp;quot;100&amp;quot;; &lt;br /&gt;
            string mobileElu = &amp;quot;0688888888&amp;quot;;&lt;br /&gt;
            string profileName = &amp;quot;Away&amp;quot;; &lt;br /&gt;
&lt;br /&gt;
            // Nommage de l&#039;astreinte&lt;br /&gt;
            string prenomElu = &amp;quot;Jean-Michel&amp;quot;; &lt;br /&gt;
            string nomElu = &amp;quot;Apeuprè&amp;quot;; &lt;br /&gt;
&lt;br /&gt;
            try&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;|| &amp;lt;syntaxhighlight lang=&amp;quot;csharp&amp;quot; line highlight=&amp;quot;3-5,8-9&amp;quot;&amp;gt;&lt;br /&gt;
public override Task&amp;lt;bool&amp;gt; StartAsync()&lt;br /&gt;
        {&lt;br /&gt;
            string targetExtNum = &amp;quot;100&amp;quot;; &lt;br /&gt;
            string mobileElu = &amp;quot;&amp;quot;;&lt;br /&gt;
            string profileName = &amp;quot;Available&amp;quot;; &lt;br /&gt;
&lt;br /&gt;
            // Nommage de l&#039;astreinte&lt;br /&gt;
            string prenomElu = &amp;quot;Accueil&amp;quot;; &lt;br /&gt;
            string nomElu = &amp;quot;&amp;quot;; &lt;br /&gt;
&lt;br /&gt;
            try&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Une fois les 3 scripts produits, passer à l&#039;étape [[Astreinte#Déclaration_du_script|Déclaration du script]] qui va permettre d&#039;affecter un code court à chaque script.&lt;br /&gt;
Exemple : &lt;br /&gt;
* *90 pour hors période d&#039;astreinte&lt;br /&gt;
* *91 pour Jean-Michel&lt;br /&gt;
* *92 pour Marcel&lt;br /&gt;
&lt;br /&gt;
On peut communiquer les codes aux personnes habilitées à gérer le système d&#039;astreinte et aller jusqu&#039;à paramétrer des BLF pour faciliter la vie d&#039;une secrétaire par exemple.&lt;br /&gt;
&lt;br /&gt;
{{Valide|v20}}&lt;br /&gt;
[[Catégorie:3CX]]&lt;/div&gt;</summary>
		<author><name>Anthony</name></author>
	</entry>
	<entry>
		<id>https://indywiki.fr/index.php?title=Astreinte&amp;diff=22255</id>
		<title>Astreinte</title>
		<link rel="alternate" type="text/html" href="https://indywiki.fr/index.php?title=Astreinte&amp;diff=22255"/>
		<updated>2026-04-28T12:05:44Z</updated>

		<summary type="html">&lt;p&gt;Anthony : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;===Principe===&lt;br /&gt;
On paramètre le statut choisi pour l&#039;astreinte en renvoi vers &#039;&#039;&#039;mon mobile&#039;&#039;&#039;. Un script viendra modifier le statut de l&#039;extension cible ainsi que son numéro de contact mobile, prénom et nom. Ce script déclenchable par l&#039;appel à un code court, paramétrable si on le souhaite sur une BLF. &lt;br /&gt;
===Paramétrage du statut de l&#039;extension vers &#039;&#039;&#039;mon mobile&#039;&#039;&#039;===&lt;br /&gt;
[[Fichier:2026-04-03 13h29 01.png|vignette]]&lt;br /&gt;
#Réglages&lt;br /&gt;
#Transfert d&#039;appels&lt;br /&gt;
#Choisir le statut de l&#039;extension à activer pour enclencher le renvoi vers l&#039;astreinte. Dans l&#039;exemple &#039;&#039;&#039;Absent&#039;&#039;&#039;. Pas l&#039;état &#039;&#039;&#039;Disponible&#039;&#039;&#039; évidemment.&lt;br /&gt;
#Dans &amp;quot;Transférer les appels externes à&amp;quot;, choisir &#039;&#039;&#039;Mon mobile&#039;&#039;&#039;&lt;br /&gt;
#Cocher &#039;&#039;&#039;Rebond&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
===Déclaration du script===&lt;br /&gt;
[[Fichier:2026-04-02 17h11 35.png|vignette]]&lt;br /&gt;
&lt;br /&gt;
Rendez-vous dans :&lt;br /&gt;
&lt;br /&gt;
 Admin / Intégrations / Scripts d&#039;appels / + Ajouter personnalisé&lt;br /&gt;
&lt;br /&gt;
#Donner un nom au traitement de l&#039;appel. Exemple : &#039;&#039;&#039;astreinte_weekend&#039;&#039;&#039;&lt;br /&gt;
#Créer un code de raccourci, ce qui permettra d&#039;exécuter le script simplement en appelant ce code, et in fine par une BLF. Exemple : &#039;&#039;&#039;*99&#039;&#039;&#039;&lt;br /&gt;
#OK&lt;br /&gt;
#Coller dans le champ script le script paramétré ( voir section suivante )&lt;br /&gt;
#Sauvegarder&lt;br /&gt;
#Un message doit indiquer &#039;&#039;&#039;Compilation réussie !&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Le script===&lt;br /&gt;
&lt;br /&gt;
L&#039;éxécution du script va modifier l&#039;extension &#039;&#039;&#039;targetExtNum &#039;&#039;&#039;, il va le basculer sur le statut &#039;&#039;&#039;profileName &#039;&#039;&#039;, modifier son mobile de contact &#039;&#039;&#039;mobileElu &#039;&#039;&#039;, son nom et prénom.&lt;br /&gt;
&lt;br /&gt;
Il faut donc seulement modifier les lignes surlignés dans le code ci-dessous :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;csharp&amp;quot; line highlight=&amp;quot;14-16,19-20&amp;quot;&amp;gt;&lt;br /&gt;
using System;&lt;br /&gt;
using System.Threading.Tasks;&lt;br /&gt;
using TCX.Configuration;&lt;br /&gt;
using CallFlow;&lt;br /&gt;
using System.Linq;&lt;br /&gt;
using System.Collections.Generic;&lt;br /&gt;
&lt;br /&gt;
namespace dummy&lt;br /&gt;
{&lt;br /&gt;
    public class SetDynamicAstreinte : ScriptBase&amp;lt;SetDynamicAstreinte&amp;gt;&lt;br /&gt;
    {&lt;br /&gt;
        public override Task&amp;lt;bool&amp;gt; StartAsync()&lt;br /&gt;
        {&lt;br /&gt;
            string targetExtNum = &amp;quot;100&amp;quot;; &lt;br /&gt;
            string mobileElu = &amp;quot;0601020304&amp;quot;;&lt;br /&gt;
            string profileName = &amp;quot;Away&amp;quot;; &lt;br /&gt;
            &lt;br /&gt;
            // Nommage de l&#039;astreinte&lt;br /&gt;
            string prenomElu = &amp;quot;ASTREINTE&amp;quot;; &lt;br /&gt;
            string nomElu = &amp;quot;ELU&amp;quot;; &lt;br /&gt;
&lt;br /&gt;
            try&lt;br /&gt;
            {&lt;br /&gt;
                IPhoneSystem ps = PhoneSystem.Root;&lt;br /&gt;
                Extension targetExt = ps.GetDNByNumber(targetExtNum) as Extension;&lt;br /&gt;
&lt;br /&gt;
                if (targetExt != null)&lt;br /&gt;
                {&lt;br /&gt;
                    // 1. Mise à jour du numéro de mobile&lt;br /&gt;
                    targetExt.SetProperty(&amp;quot;MOBILENUMBER&amp;quot;, mobileElu);&lt;br /&gt;
&lt;br /&gt;
                    // 2. MISE À JOUR DU NOM&lt;br /&gt;
                    targetExt.FirstName = prenomElu;&lt;br /&gt;
                    targetExt.LastName = nomElu;&lt;br /&gt;
&lt;br /&gt;
                    // 3. Changement du profil de statut&lt;br /&gt;
                    var profile = targetExt.FwdProfiles.FirstOrDefault(p =&amp;gt; p.Name.Equals(profileName, StringComparison.OrdinalIgnoreCase));&lt;br /&gt;
                    &lt;br /&gt;
                    if (profile != null)&lt;br /&gt;
                    {&lt;br /&gt;
                        targetExt.CurrentProfile = profile;&lt;br /&gt;
                    }&lt;br /&gt;
&lt;br /&gt;
                    // 4. Sauvegarde globale&lt;br /&gt;
                    targetExt.ResetCurrentProfileOverride();&lt;br /&gt;
                    targetExt.Save();&lt;br /&gt;
&lt;br /&gt;
                    return Task.FromResult(true);&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            catch (Exception)&lt;br /&gt;
            {&lt;br /&gt;
                // Erreur silencieuse&lt;br /&gt;
            }&lt;br /&gt;
            return Task.FromResult(false);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Table de correspondance des profileName====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Dans 3CX!! Dans le script&lt;br /&gt;
|-&lt;br /&gt;
| Disponible|| Available&lt;br /&gt;
|-&lt;br /&gt;
| Absent|| Away&lt;br /&gt;
|-&lt;br /&gt;
| Ne pas déranger|| Out of office&lt;br /&gt;
|-&lt;br /&gt;
| Custom 1|| Custom 1&lt;br /&gt;
|-&lt;br /&gt;
| Custom 2|| Custom 2&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===Configuration concrète===&lt;br /&gt;
&lt;br /&gt;
Il faut choisir un statut autre que &amp;quot;Disponible&amp;quot; qui sera activé pour l&#039;astreinte, &amp;quot;Away&amp;quot; pour cet exemple&lt;br /&gt;
&lt;br /&gt;
On a besoin de gérer deux astreintes. Le poste Accueil reçoit les appels en temps normal&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Texte de la légende&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;Marcel Patulacci&#039;&#039;&#039; || &#039;&#039;&#039;Jean-Michel Apeuprè&#039;&#039;&#039;|| &#039;&#039;&#039;Poste accueil &#039;&#039;&#039; hors période d&#039;astreinte&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;syntaxhighlight lang=&amp;quot;csharp&amp;quot; line highlight=&amp;quot;3-5,8-9&amp;quot;&amp;gt;&lt;br /&gt;
public override Task&amp;lt;bool&amp;gt; StartAsync()&lt;br /&gt;
        {&lt;br /&gt;
            string targetExtNum = &amp;quot;100&amp;quot;; &lt;br /&gt;
            string mobileElu = &amp;quot;0699999999&amp;quot;;&lt;br /&gt;
            string profileName = &amp;quot;Away&amp;quot;; &lt;br /&gt;
&lt;br /&gt;
            // Nommage de l&#039;astreinte&lt;br /&gt;
            string prenomElu = &amp;quot;Marcel&amp;quot;; &lt;br /&gt;
            string nomElu = &amp;quot;Patulacci&amp;quot;; &lt;br /&gt;
&lt;br /&gt;
            try&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt; || &amp;lt;syntaxhighlight lang=&amp;quot;csharp&amp;quot; line highlight=&amp;quot;3-5,8-9&amp;quot;&amp;gt;&lt;br /&gt;
public override Task&amp;lt;bool&amp;gt; StartAsync()&lt;br /&gt;
        {&lt;br /&gt;
            string targetExtNum = &amp;quot;100&amp;quot;; &lt;br /&gt;
            string mobileElu = &amp;quot;0688888888&amp;quot;;&lt;br /&gt;
            string profileName = &amp;quot;Away&amp;quot;; &lt;br /&gt;
&lt;br /&gt;
            // Nommage de l&#039;astreinte&lt;br /&gt;
            string prenomElu = &amp;quot;Jean-Michel&amp;quot;; &lt;br /&gt;
            string nomElu = &amp;quot;Apeuprè&amp;quot;; &lt;br /&gt;
&lt;br /&gt;
            try&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;|| &amp;lt;syntaxhighlight lang=&amp;quot;csharp&amp;quot; line highlight=&amp;quot;3-5,8-9&amp;quot;&amp;gt;&lt;br /&gt;
public override Task&amp;lt;bool&amp;gt; StartAsync()&lt;br /&gt;
        {&lt;br /&gt;
            string targetExtNum = &amp;quot;100&amp;quot;; &lt;br /&gt;
            string mobileElu = &amp;quot;&amp;quot;;&lt;br /&gt;
            string profileName = &amp;quot;Available&amp;quot;; &lt;br /&gt;
&lt;br /&gt;
            // Nommage de l&#039;astreinte&lt;br /&gt;
            string prenomElu = &amp;quot;Accueil&amp;quot;; &lt;br /&gt;
            string nomElu = &amp;quot;&amp;quot;; &lt;br /&gt;
&lt;br /&gt;
            try&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Une fois les 3 scripts produits, passer à l&#039;étape [[Astreinte#Déclaration_du_script|Déclaration du script]] qui va permettre d&#039;affecter un code court à chaque script.&lt;br /&gt;
Exemple : &lt;br /&gt;
* *90 pour hors période d&#039;astreinte&lt;br /&gt;
* *91 pour Jean-Michel&lt;br /&gt;
* *92 pour Marcel&lt;br /&gt;
&lt;br /&gt;
On peut communiquer les codes aux personnes habilitées à gérer le système d&#039;astreinte et aller jusqu&#039;à paramétrer des BLF pour faciliter la vie d&#039;une secrétaire par exemple.&lt;br /&gt;
&lt;br /&gt;
{{Valide|v20}}&lt;br /&gt;
[[Catégorie:3CX]]&lt;/div&gt;</summary>
		<author><name>Anthony</name></author>
	</entry>
	<entry>
		<id>https://indywiki.fr/index.php?title=Script_de_routage_des_appels&amp;diff=22254</id>
		<title>Script de routage des appels</title>
		<link rel="alternate" type="text/html" href="https://indywiki.fr/index.php?title=Script_de_routage_des_appels&amp;diff=22254"/>
		<updated>2026-04-03T14:58:45Z</updated>

		<summary type="html">&lt;p&gt;Anthony : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;syntaxhighlight lang=&amp;quot;csharp&amp;quot; line highlight=&amp;quot;16,37,43,52-54&amp;quot;&amp;gt;&lt;br /&gt;
#nullable disable&lt;br /&gt;
using CallFlow;&lt;br /&gt;
using System;&lt;br /&gt;
using System.Threading.Tasks;&lt;br /&gt;
using TCX.Configuration;&lt;br /&gt;
using TCX.PBXAPI;&lt;br /&gt;
using System.Collections.Generic;&lt;br /&gt;
using System.Linq;&lt;br /&gt;
using CallFlow.CFD;&lt;br /&gt;
&lt;br /&gt;
namespace interceptcall&lt;br /&gt;
{&lt;br /&gt;
    public class InterceptInboundCall : ScriptBase&amp;lt;InterceptInboundCall&amp;gt;&lt;br /&gt;
    {&lt;br /&gt;
        // Destination par Défaut&lt;br /&gt;
        const string DefaultDestinationDN = &amp;quot;600&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
        // Structure d&#039;une règle de routage&lt;br /&gt;
        class RoutingRule&lt;br /&gt;
        {&lt;br /&gt;
            public Schedule Schedule { get; set; }&lt;br /&gt;
            public string DestinationDN { get; set; }&lt;br /&gt;
            public string[] DIDs { get; set; }&lt;br /&gt;
            public string[] Callers { get; set; }&lt;br /&gt;
&lt;br /&gt;
            public RoutingRule(Schedule schedule, string destinationDN, string[] dids, string[] callers)&lt;br /&gt;
            {&lt;br /&gt;
                Schedule = schedule;&lt;br /&gt;
                DestinationDN = destinationDN;&lt;br /&gt;
                DIDs = dids;&lt;br /&gt;
                Callers = callers;&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// Règle(s) de routage. La première règle trouvée satisfaite sera la route suivie&lt;br /&gt;
       static readonly List&amp;lt;RoutingRule&amp;gt; routingRules = new List&amp;lt;RoutingRule&amp;gt;&lt;br /&gt;
        {&lt;br /&gt;
            // RULE 1 — Nuit semaine → 990&lt;br /&gt;
            new RoutingRule(&lt;br /&gt;
                new Schedule(RuleHoursType.SpecificHours)&lt;br /&gt;
                {&lt;br /&gt;
                    { DayOfWeek.Monday,    new Schedule.PeriodOfDay(TimeSpan.FromHours(17.5), TimeSpan.FromHours(24)) },&lt;br /&gt;
                    { DayOfWeek.Monday,    new Schedule.PeriodOfDay(TimeSpan.FromHours(0), TimeSpan.FromHours(7)) },&lt;br /&gt;
                    { DayOfWeek.Tuesday,   new Schedule.PeriodOfDay(TimeSpan.FromHours(17.5), TimeSpan.FromHours(24)) },&lt;br /&gt;
                    { DayOfWeek.Tuesday,   new Schedule.PeriodOfDay(TimeSpan.FromHours(0), TimeSpan.FromHours(7)) },&lt;br /&gt;
                    { DayOfWeek.Wednesday, new Schedule.PeriodOfDay(TimeSpan.FromHours(17.5), TimeSpan.FromHours(24)) },&lt;br /&gt;
                    { DayOfWeek.Wednesday, new Schedule.PeriodOfDay(TimeSpan.FromHours(0), TimeSpan.FromHours(7)) },&lt;br /&gt;
                    { DayOfWeek.Friday,    new Schedule.PeriodOfDay(TimeSpan.FromHours(17.5), TimeSpan.FromHours(24)) },&lt;br /&gt;
                    { DayOfWeek.Friday,    new Schedule.PeriodOfDay(TimeSpan.FromHours(0), TimeSpan.FromHours(7)) }&lt;br /&gt;
                },&lt;br /&gt;
                &amp;quot;600&amp;quot;,&lt;br /&gt;
                new[] { &amp;quot;*&amp;quot; },   // Tous les DIDs&lt;br /&gt;
                new[] { &amp;quot;*&amp;quot; }    // Tous les callers&lt;br /&gt;
            ),&lt;br /&gt;
&lt;br /&gt;
            // RULE 2 — Jeudi 14h-18h → 804 (DID spécifique)&lt;br /&gt;
            new RoutingRule(&lt;br /&gt;
                new Schedule(RuleHoursType.SpecificHours)&lt;br /&gt;
                {&lt;br /&gt;
                    { DayOfWeek.Thursday, new Schedule.PeriodOfDay(TimeSpan.FromHours(14), TimeSpan.FromHours(16.25)) }&lt;br /&gt;
                },&lt;br /&gt;
                &amp;quot;804&amp;quot;,&lt;br /&gt;
                new[] { &amp;quot;*&amp;quot; }, // DID spécifique&lt;br /&gt;
                new[] { &amp;quot;*&amp;quot; }&lt;br /&gt;
            ),&lt;br /&gt;
            &lt;br /&gt;
              // RULE 3 — Jeudi 14h-18h → 805&lt;br /&gt;
            new RoutingRule(&lt;br /&gt;
                new Schedule(RuleHoursType.SpecificHours)&lt;br /&gt;
                {&lt;br /&gt;
					{ DayOfWeek.Thursday, new Schedule.PeriodOfDay(new TimeSpan(17,15,0), new TimeSpan(17,30,0)) },&lt;br /&gt;
                },&lt;br /&gt;
                &amp;quot;805&amp;quot;,&lt;br /&gt;
                new[] { &amp;quot;*&amp;quot; },&lt;br /&gt;
                new[] { &amp;quot;*&amp;quot; }&lt;br /&gt;
            ),&lt;br /&gt;
&lt;br /&gt;
            // RULE 4 — Week-end complet → 992&lt;br /&gt;
            new RoutingRule(&lt;br /&gt;
                new Schedule(RuleHoursType.SpecificHours)&lt;br /&gt;
                {&lt;br /&gt;
                    { DayOfWeek.Saturday, new Schedule.PeriodOfDay(TimeSpan.FromHours(0), TimeSpan.FromHours(24)) },&lt;br /&gt;
                    { DayOfWeek.Sunday,   new Schedule.PeriodOfDay(TimeSpan.FromHours(0), TimeSpan.FromHours(24)) }&lt;br /&gt;
                },&lt;br /&gt;
                &amp;quot;992&amp;quot;,&lt;br /&gt;
                new[] { &amp;quot;*&amp;quot; },&lt;br /&gt;
                new[] { &amp;quot;*&amp;quot; }&lt;br /&gt;
            )&lt;br /&gt;
        };&lt;br /&gt;
&lt;br /&gt;
        // Appel de la fonction principale&lt;br /&gt;
&lt;br /&gt;
        public override async void Start()&lt;br /&gt;
        {&lt;br /&gt;
            try&lt;br /&gt;
            {&lt;br /&gt;
                await Task.Run(async () =&amp;gt;&lt;br /&gt;
                {&lt;br /&gt;
                    bool intercepted = false;&lt;br /&gt;
                    var ps = MyCall.PS as PhoneSystem;&lt;br /&gt;
&lt;br /&gt;
                    if (!(MyCall.Caller.DN is ExternalLine externalLine))&lt;br /&gt;
                    {&lt;br /&gt;
                        MyCall.Return(false);&lt;br /&gt;
                        return;&lt;br /&gt;
                    }&lt;br /&gt;
&lt;br /&gt;
                    var DIDNumber = MyCall.Caller[&amp;quot;inbound_did&amp;quot;] ?? &amp;quot;&amp;quot;;&lt;br /&gt;
                    var CallerID = MyCall.Caller.CallerID ?? &amp;quot;&amp;quot;;&lt;br /&gt;
                    var currentTime = externalLine.Now(out var utc, out var timezone, out var groupmode);&lt;br /&gt;
&lt;br /&gt;
                    MyCall.Info($&amp;quot;Incoming call | Caller: {CallerID} | DID: {DIDNumber} | Time: {currentTime}&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
                    foreach (var rule in routingRules)&lt;br /&gt;
                    {&lt;br /&gt;
                        if (!rule.Schedule.IsActiveTime(currentTime))&lt;br /&gt;
                            continue;&lt;br /&gt;
&lt;br /&gt;
                        bool didMatch = rule.DIDs.Contains(&amp;quot;*&amp;quot;) || rule.DIDs.Contains(DIDNumber);&lt;br /&gt;
                        bool callerMatch = rule.Callers.Contains(&amp;quot;*&amp;quot;) || rule.Callers.Contains(CallerID);&lt;br /&gt;
&lt;br /&gt;
                        if (!didMatch || !callerMatch)&lt;br /&gt;
                            continue;&lt;br /&gt;
&lt;br /&gt;
                        var destinationDN = ps.GetDNByNumber(rule.DestinationDN);&lt;br /&gt;
&lt;br /&gt;
                        if (destinationDN == null)&lt;br /&gt;
                        {&lt;br /&gt;
                            MyCall.Error($&amp;quot;Destination {rule.DestinationDN} not found.&amp;quot;);&lt;br /&gt;
                            continue;&lt;br /&gt;
                        }&lt;br /&gt;
&lt;br /&gt;
                        try&lt;br /&gt;
                        {&lt;br /&gt;
                            var result = await MyCall.RouteToAsync(new DestinationStruct(destinationDN));&lt;br /&gt;
                            MyCall.Info($&amp;quot;Routed to {rule.DestinationDN} | Result: {result}&amp;quot;);&lt;br /&gt;
                            intercepted = true;&lt;br /&gt;
                            break; // Stop at first matching rule&lt;br /&gt;
                        }&lt;br /&gt;
                        catch (Exception ex)&lt;br /&gt;
                        {&lt;br /&gt;
                            MyCall.Error($&amp;quot;Routing failed to {rule.DestinationDN}: {ex}&amp;quot;);&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
&lt;br /&gt;
                &lt;br /&gt;
                    // Utilisation de la route par défaut&lt;br /&gt;
                    &lt;br /&gt;
                    if (!intercepted)&lt;br /&gt;
                    {&lt;br /&gt;
                        var fallbackDN = ps.GetDNByNumber(DefaultDestinationDN);&lt;br /&gt;
                        if (fallbackDN != null)&lt;br /&gt;
                        {&lt;br /&gt;
                            try&lt;br /&gt;
                            {&lt;br /&gt;
                                var result = await MyCall.RouteToAsync(new DestinationStruct(fallbackDN));&lt;br /&gt;
                                MyCall.Info($&amp;quot;Fallback routing to {DefaultDestinationDN} | Result: {result}&amp;quot;);&lt;br /&gt;
                                intercepted = true;&lt;br /&gt;
                            }&lt;br /&gt;
                            catch (Exception ex)&lt;br /&gt;
                            {&lt;br /&gt;
                                MyCall.Error($&amp;quot;Fallback routing failed: {ex}&amp;quot;);&lt;br /&gt;
                            }&lt;br /&gt;
                        }&lt;br /&gt;
                        else&lt;br /&gt;
                        {&lt;br /&gt;
                            MyCall.Error($&amp;quot;Fallback DN {DefaultDestinationDN} not found.&amp;quot;);&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
&lt;br /&gt;
                    MyCall.Return(intercepted);&lt;br /&gt;
                });&lt;br /&gt;
            }&lt;br /&gt;
            catch (Exception ex)&lt;br /&gt;
            {&lt;br /&gt;
                MyCall.Error($&amp;quot;Script execution failed: {ex}&amp;quot;);&lt;br /&gt;
                MyCall.Return(false);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Catégorie:3CX]]&lt;/div&gt;</summary>
		<author><name>Anthony</name></author>
	</entry>
	<entry>
		<id>https://indywiki.fr/index.php?title=Script_de_routage_des_appels&amp;diff=22253</id>
		<title>Script de routage des appels</title>
		<link rel="alternate" type="text/html" href="https://indywiki.fr/index.php?title=Script_de_routage_des_appels&amp;diff=22253"/>
		<updated>2026-04-03T14:56:02Z</updated>

		<summary type="html">&lt;p&gt;Anthony : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;syntaxhighlight lang=&amp;quot;csharp&amp;quot; line highlight=&amp;quot;16,19-20&amp;quot;&amp;gt;&lt;br /&gt;
#nullable disable&lt;br /&gt;
using CallFlow;&lt;br /&gt;
using System;&lt;br /&gt;
using System.Threading.Tasks;&lt;br /&gt;
using TCX.Configuration;&lt;br /&gt;
using TCX.PBXAPI;&lt;br /&gt;
using System.Collections.Generic;&lt;br /&gt;
using System.Linq;&lt;br /&gt;
using CallFlow.CFD;&lt;br /&gt;
&lt;br /&gt;
namespace interceptcall&lt;br /&gt;
{&lt;br /&gt;
    public class InterceptInboundCall : ScriptBase&amp;lt;InterceptInboundCall&amp;gt;&lt;br /&gt;
    {&lt;br /&gt;
        // Destination par Défaut&lt;br /&gt;
        const string DefaultDestinationDN = &amp;quot;600&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
        // Structure d&#039;une règle de routage&lt;br /&gt;
        class RoutingRule&lt;br /&gt;
        {&lt;br /&gt;
            public Schedule Schedule { get; set; }&lt;br /&gt;
            public string DestinationDN { get; set; }&lt;br /&gt;
            public string[] DIDs { get; set; }&lt;br /&gt;
            public string[] Callers { get; set; }&lt;br /&gt;
&lt;br /&gt;
            public RoutingRule(Schedule schedule, string destinationDN, string[] dids, string[] callers)&lt;br /&gt;
            {&lt;br /&gt;
                Schedule = schedule;&lt;br /&gt;
                DestinationDN = destinationDN;&lt;br /&gt;
                DIDs = dids;&lt;br /&gt;
                Callers = callers;&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// Règle(s) de routage. La première règle trouvée satisfaite sera la route suivie&lt;br /&gt;
       static readonly List&amp;lt;RoutingRule&amp;gt; routingRules = new List&amp;lt;RoutingRule&amp;gt;&lt;br /&gt;
        {&lt;br /&gt;
            // RULE 1 — Nuit semaine → 990&lt;br /&gt;
            new RoutingRule(&lt;br /&gt;
                new Schedule(RuleHoursType.SpecificHours)&lt;br /&gt;
                {&lt;br /&gt;
                    { DayOfWeek.Monday,    new Schedule.PeriodOfDay(TimeSpan.FromHours(17.5), TimeSpan.FromHours(24)) },&lt;br /&gt;
                    { DayOfWeek.Monday,    new Schedule.PeriodOfDay(TimeSpan.FromHours(0), TimeSpan.FromHours(7)) },&lt;br /&gt;
                    { DayOfWeek.Tuesday,   new Schedule.PeriodOfDay(TimeSpan.FromHours(17.5), TimeSpan.FromHours(24)) },&lt;br /&gt;
                    { DayOfWeek.Tuesday,   new Schedule.PeriodOfDay(TimeSpan.FromHours(0), TimeSpan.FromHours(7)) },&lt;br /&gt;
                    { DayOfWeek.Wednesday, new Schedule.PeriodOfDay(TimeSpan.FromHours(17.5), TimeSpan.FromHours(24)) },&lt;br /&gt;
                    { DayOfWeek.Wednesday, new Schedule.PeriodOfDay(TimeSpan.FromHours(0), TimeSpan.FromHours(7)) },&lt;br /&gt;
                    { DayOfWeek.Friday,    new Schedule.PeriodOfDay(TimeSpan.FromHours(17.5), TimeSpan.FromHours(24)) },&lt;br /&gt;
                    { DayOfWeek.Friday,    new Schedule.PeriodOfDay(TimeSpan.FromHours(0), TimeSpan.FromHours(7)) }&lt;br /&gt;
                },&lt;br /&gt;
                &amp;quot;600&amp;quot;,&lt;br /&gt;
                new[] { &amp;quot;*&amp;quot; },   // Tous les DIDs&lt;br /&gt;
                new[] { &amp;quot;*&amp;quot; }    // Tous les callers&lt;br /&gt;
            ),&lt;br /&gt;
&lt;br /&gt;
            // RULE 2 — Jeudi 14h-18h → 804 (DID spécifique)&lt;br /&gt;
            new RoutingRule(&lt;br /&gt;
                new Schedule(RuleHoursType.SpecificHours)&lt;br /&gt;
                {&lt;br /&gt;
                    { DayOfWeek.Thursday, new Schedule.PeriodOfDay(TimeSpan.FromHours(14), TimeSpan.FromHours(16.25)) }&lt;br /&gt;
                },&lt;br /&gt;
                &amp;quot;804&amp;quot;,&lt;br /&gt;
                new[] { &amp;quot;*&amp;quot; }, // DID spécifique&lt;br /&gt;
                new[] { &amp;quot;*&amp;quot; }&lt;br /&gt;
            ),&lt;br /&gt;
            &lt;br /&gt;
              // RULE 3 — Jeudi 14h-18h → 805&lt;br /&gt;
            new RoutingRule(&lt;br /&gt;
                new Schedule(RuleHoursType.SpecificHours)&lt;br /&gt;
                {&lt;br /&gt;
					{ DayOfWeek.Thursday, new Schedule.PeriodOfDay(new TimeSpan(17,15,0), new TimeSpan(17,30,0)) },&lt;br /&gt;
                },&lt;br /&gt;
                &amp;quot;805&amp;quot;,&lt;br /&gt;
                new[] { &amp;quot;*&amp;quot; },&lt;br /&gt;
                new[] { &amp;quot;*&amp;quot; }&lt;br /&gt;
            ),&lt;br /&gt;
&lt;br /&gt;
            // RULE 4 — Week-end complet → 992&lt;br /&gt;
            new RoutingRule(&lt;br /&gt;
                new Schedule(RuleHoursType.SpecificHours)&lt;br /&gt;
                {&lt;br /&gt;
                    { DayOfWeek.Saturday, new Schedule.PeriodOfDay(TimeSpan.FromHours(0), TimeSpan.FromHours(24)) },&lt;br /&gt;
                    { DayOfWeek.Sunday,   new Schedule.PeriodOfDay(TimeSpan.FromHours(0), TimeSpan.FromHours(24)) }&lt;br /&gt;
                },&lt;br /&gt;
                &amp;quot;992&amp;quot;,&lt;br /&gt;
                new[] { &amp;quot;*&amp;quot; },&lt;br /&gt;
                new[] { &amp;quot;*&amp;quot; }&lt;br /&gt;
            )&lt;br /&gt;
        };&lt;br /&gt;
&lt;br /&gt;
        // Appel de la fonction principale&lt;br /&gt;
&lt;br /&gt;
        public override async void Start()&lt;br /&gt;
        {&lt;br /&gt;
            try&lt;br /&gt;
            {&lt;br /&gt;
                await Task.Run(async () =&amp;gt;&lt;br /&gt;
                {&lt;br /&gt;
                    bool intercepted = false;&lt;br /&gt;
                    var ps = MyCall.PS as PhoneSystem;&lt;br /&gt;
&lt;br /&gt;
                    if (!(MyCall.Caller.DN is ExternalLine externalLine))&lt;br /&gt;
                    {&lt;br /&gt;
                        MyCall.Return(false);&lt;br /&gt;
                        return;&lt;br /&gt;
                    }&lt;br /&gt;
&lt;br /&gt;
                    var DIDNumber = MyCall.Caller[&amp;quot;inbound_did&amp;quot;] ?? &amp;quot;&amp;quot;;&lt;br /&gt;
                    var CallerID = MyCall.Caller.CallerID ?? &amp;quot;&amp;quot;;&lt;br /&gt;
                    var currentTime = externalLine.Now(out var utc, out var timezone, out var groupmode);&lt;br /&gt;
&lt;br /&gt;
                    MyCall.Info($&amp;quot;Incoming call | Caller: {CallerID} | DID: {DIDNumber} | Time: {currentTime}&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
                    foreach (var rule in routingRules)&lt;br /&gt;
                    {&lt;br /&gt;
                        if (!rule.Schedule.IsActiveTime(currentTime))&lt;br /&gt;
                            continue;&lt;br /&gt;
&lt;br /&gt;
                        bool didMatch = rule.DIDs.Contains(&amp;quot;*&amp;quot;) || rule.DIDs.Contains(DIDNumber);&lt;br /&gt;
                        bool callerMatch = rule.Callers.Contains(&amp;quot;*&amp;quot;) || rule.Callers.Contains(CallerID);&lt;br /&gt;
&lt;br /&gt;
                        if (!didMatch || !callerMatch)&lt;br /&gt;
                            continue;&lt;br /&gt;
&lt;br /&gt;
                        var destinationDN = ps.GetDNByNumber(rule.DestinationDN);&lt;br /&gt;
&lt;br /&gt;
                        if (destinationDN == null)&lt;br /&gt;
                        {&lt;br /&gt;
                            MyCall.Error($&amp;quot;Destination {rule.DestinationDN} not found.&amp;quot;);&lt;br /&gt;
                            continue;&lt;br /&gt;
                        }&lt;br /&gt;
&lt;br /&gt;
                        try&lt;br /&gt;
                        {&lt;br /&gt;
                            var result = await MyCall.RouteToAsync(new DestinationStruct(destinationDN));&lt;br /&gt;
                            MyCall.Info($&amp;quot;Routed to {rule.DestinationDN} | Result: {result}&amp;quot;);&lt;br /&gt;
                            intercepted = true;&lt;br /&gt;
                            break; // Stop at first matching rule&lt;br /&gt;
                        }&lt;br /&gt;
                        catch (Exception ex)&lt;br /&gt;
                        {&lt;br /&gt;
                            MyCall.Error($&amp;quot;Routing failed to {rule.DestinationDN}: {ex}&amp;quot;);&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
&lt;br /&gt;
                &lt;br /&gt;
                    // Utilisation de la route par défaut&lt;br /&gt;
                    &lt;br /&gt;
                    if (!intercepted)&lt;br /&gt;
                    {&lt;br /&gt;
                        var fallbackDN = ps.GetDNByNumber(DefaultDestinationDN);&lt;br /&gt;
                        if (fallbackDN != null)&lt;br /&gt;
                        {&lt;br /&gt;
                            try&lt;br /&gt;
                            {&lt;br /&gt;
                                var result = await MyCall.RouteToAsync(new DestinationStruct(fallbackDN));&lt;br /&gt;
                                MyCall.Info($&amp;quot;Fallback routing to {DefaultDestinationDN} | Result: {result}&amp;quot;);&lt;br /&gt;
                                intercepted = true;&lt;br /&gt;
                            }&lt;br /&gt;
                            catch (Exception ex)&lt;br /&gt;
                            {&lt;br /&gt;
                                MyCall.Error($&amp;quot;Fallback routing failed: {ex}&amp;quot;);&lt;br /&gt;
                            }&lt;br /&gt;
                        }&lt;br /&gt;
                        else&lt;br /&gt;
                        {&lt;br /&gt;
                            MyCall.Error($&amp;quot;Fallback DN {DefaultDestinationDN} not found.&amp;quot;);&lt;br /&gt;
                        }&lt;br /&gt;
                    }&lt;br /&gt;
&lt;br /&gt;
                    MyCall.Return(intercepted);&lt;br /&gt;
                });&lt;br /&gt;
            }&lt;br /&gt;
            catch (Exception ex)&lt;br /&gt;
            {&lt;br /&gt;
                MyCall.Error($&amp;quot;Script execution failed: {ex}&amp;quot;);&lt;br /&gt;
                MyCall.Return(false);&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Catégorie:3CX]]&lt;/div&gt;</summary>
		<author><name>Anthony</name></author>
	</entry>
	<entry>
		<id>https://indywiki.fr/index.php?title=Astreinte&amp;diff=22252</id>
		<title>Astreinte</title>
		<link rel="alternate" type="text/html" href="https://indywiki.fr/index.php?title=Astreinte&amp;diff=22252"/>
		<updated>2026-04-03T11:38:54Z</updated>

		<summary type="html">&lt;p&gt;Anthony : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== par le statut ==&lt;br /&gt;
Dans les réglages de l&#039;extension qui accueille les appels :&lt;br /&gt;
[[Fichier:2026-04-02 16h03 02.png|vignette]]&lt;br /&gt;
#Réglages&lt;br /&gt;
#Transfert d&#039;appels&lt;br /&gt;
#Choisir le statut de l&#039;extension à activer pour enclencher le renvoi vers l&#039;astreinte. Dans l&#039;exemple &#039;&#039;&#039;Absent&#039;&#039;&#039;. Pas l&#039;état &#039;&#039;&#039;Disponible&#039;&#039;&#039; évidemment.&lt;br /&gt;
#Dans &amp;quot;Transférer les appels externes à&amp;quot;, choisir &#039;&#039;&#039;Numéro externe&#039;&#039;&#039;&lt;br /&gt;
#Saisir le numéro de l&#039;astreinte&lt;br /&gt;
#Cocher &#039;&#039;&#039;Rebond&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Limite / contrainte : &lt;br /&gt;
*si les astreintes tournent, avant chaque période d&#039;astreinte, il faut faire ce cheminement pour que le bon numéro de mobile soit paramétré&lt;br /&gt;
*4 profils d&#039;astreinte maximum&lt;br /&gt;
*Nécessite de manipuler l&#039;application WEB&lt;br /&gt;
&lt;br /&gt;
== Par le statut + script==&lt;br /&gt;
===Principe===&lt;br /&gt;
On paramètre le statut choisi pour l&#039;astreinte en renvoi vers &#039;&#039;&#039;mon mobile&#039;&#039;&#039;. Un script viendra modifier le statut de l&#039;extension cible ainsi que son numéro de contact mobile, prénom et nom. Ce script déclenchable par l&#039;appel à un code court, paramétrable si on le souhaite sur une BLF. &lt;br /&gt;
===Paramétrage du statut de l&#039;extension vers &#039;&#039;&#039;mon mobile&#039;&#039;&#039;===&lt;br /&gt;
[[Fichier:2026-04-03 13h29 01.png|vignette]]&lt;br /&gt;
#Réglages&lt;br /&gt;
#Transfert d&#039;appels&lt;br /&gt;
#Choisir le statut de l&#039;extension à activer pour enclencher le renvoi vers l&#039;astreinte. Dans l&#039;exemple &#039;&#039;&#039;Absent&#039;&#039;&#039;. Pas l&#039;état &#039;&#039;&#039;Disponible&#039;&#039;&#039; évidemment.&lt;br /&gt;
#Dans &amp;quot;Transférer les appels externes à&amp;quot;, choisir &#039;&#039;&#039;Mon mobile&#039;&#039;&#039;&lt;br /&gt;
#Cocher &#039;&#039;&#039;Rebond&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
===Déclaration du script===&lt;br /&gt;
[[Fichier:2026-04-02 17h11 35.png|vignette]]&lt;br /&gt;
&lt;br /&gt;
Rendez-vous dans :&lt;br /&gt;
&lt;br /&gt;
 Admin / Intégrations / Scripts d&#039;appels / + Ajouter personnalisé&lt;br /&gt;
&lt;br /&gt;
#Donner un nom au traitement de l&#039;appel. Exemple : &#039;&#039;&#039;astreinte_weekend&#039;&#039;&#039;&lt;br /&gt;
#Créer un code de raccourci, ce qui permettra d&#039;exécuter le script simplement en appelant ce code, et in fine par une BLF. Exemple : &#039;&#039;&#039;*99&#039;&#039;&#039;&lt;br /&gt;
#OK&lt;br /&gt;
#Coller dans le champ script le script paramétré ( voir section suivante )&lt;br /&gt;
#Sauvegarder&lt;br /&gt;
#Un message doit indiquer &#039;&#039;&#039;Compilation réussie !&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Le script===&lt;br /&gt;
&lt;br /&gt;
L&#039;éxécution du script va modifier l&#039;extension &#039;&#039;&#039;targetExtNum &#039;&#039;&#039;, il va le basculer sur le statut &#039;&#039;&#039;profileName &#039;&#039;&#039;, modifier son mobile de contact &#039;&#039;&#039;mobileElu &#039;&#039;&#039;, son nom et prénom.&lt;br /&gt;
&lt;br /&gt;
Il faut donc seulement modifier les lignes surlignés dans le code ci-dessous :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;csharp&amp;quot; line highlight=&amp;quot;14-16,19-20&amp;quot;&amp;gt;&lt;br /&gt;
using System;&lt;br /&gt;
using System.Threading.Tasks;&lt;br /&gt;
using TCX.Configuration;&lt;br /&gt;
using CallFlow;&lt;br /&gt;
using System.Linq;&lt;br /&gt;
using System.Collections.Generic;&lt;br /&gt;
&lt;br /&gt;
namespace dummy&lt;br /&gt;
{&lt;br /&gt;
    public class SetDynamicAstreinte : ScriptBase&amp;lt;SetDynamicAstreinte&amp;gt;&lt;br /&gt;
    {&lt;br /&gt;
        public override Task&amp;lt;bool&amp;gt; StartAsync()&lt;br /&gt;
        {&lt;br /&gt;
            string targetExtNum = &amp;quot;100&amp;quot;; &lt;br /&gt;
            string mobileElu = &amp;quot;0601020304&amp;quot;;&lt;br /&gt;
            string profileName = &amp;quot;Away&amp;quot;; &lt;br /&gt;
            &lt;br /&gt;
            // Nommage de l&#039;astreinte&lt;br /&gt;
            string prenomElu = &amp;quot;ASTREINTE&amp;quot;; &lt;br /&gt;
            string nomElu = &amp;quot;ELU&amp;quot;; &lt;br /&gt;
&lt;br /&gt;
            try&lt;br /&gt;
            {&lt;br /&gt;
                IPhoneSystem ps = PhoneSystem.Root;&lt;br /&gt;
                Extension targetExt = ps.GetDNByNumber(targetExtNum) as Extension;&lt;br /&gt;
&lt;br /&gt;
                if (targetExt != null)&lt;br /&gt;
                {&lt;br /&gt;
                    // 1. Mise à jour du numéro de mobile&lt;br /&gt;
                    targetExt.SetProperty(&amp;quot;MOBILENUMBER&amp;quot;, mobileElu);&lt;br /&gt;
&lt;br /&gt;
                    // 2. MISE À JOUR DU NOM&lt;br /&gt;
                    targetExt.FirstName = prenomElu;&lt;br /&gt;
                    targetExt.LastName = nomElu;&lt;br /&gt;
&lt;br /&gt;
                    // 3. Changement du profil de statut&lt;br /&gt;
                    var profile = targetExt.FwdProfiles.FirstOrDefault(p =&amp;gt; p.Name.Equals(profileName, StringComparison.OrdinalIgnoreCase));&lt;br /&gt;
                    &lt;br /&gt;
                    if (profile != null)&lt;br /&gt;
                    {&lt;br /&gt;
                        targetExt.CurrentProfile = profile;&lt;br /&gt;
                    }&lt;br /&gt;
&lt;br /&gt;
                    // 4. Sauvegarde globale&lt;br /&gt;
                    targetExt.ResetCurrentProfileOverride();&lt;br /&gt;
                    targetExt.Save();&lt;br /&gt;
&lt;br /&gt;
                    return Task.FromResult(true);&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            catch (Exception)&lt;br /&gt;
            {&lt;br /&gt;
                // Erreur silencieuse&lt;br /&gt;
            }&lt;br /&gt;
            return Task.FromResult(false);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Table de correspondance des profileName====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Dans 3CX!! Dans le script&lt;br /&gt;
|-&lt;br /&gt;
| Disponible|| Available&lt;br /&gt;
|-&lt;br /&gt;
| Absent|| Away&lt;br /&gt;
|-&lt;br /&gt;
| Ne pas déranger|| Out of office&lt;br /&gt;
|-&lt;br /&gt;
| Custom 1|| Custom 1&lt;br /&gt;
|-&lt;br /&gt;
| Custom 2|| Custom 2&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===Configuration concrète===&lt;br /&gt;
&lt;br /&gt;
Il faut choisir un statut autre que &amp;quot;Disponible&amp;quot; qui sera activé pour l&#039;astreinte, &amp;quot;Away&amp;quot; pour cet exemple&lt;br /&gt;
&lt;br /&gt;
On a besoin de gérer deux astreintes. Le poste Accueil reçoit les appels en temps normal&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Texte de la légende&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;Marcel Patulacci&#039;&#039;&#039; || &#039;&#039;&#039;Jean-Michel Apeuprè&#039;&#039;&#039;|| &#039;&#039;&#039;Poste accueil &#039;&#039;&#039; hors période d&#039;astreinte&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;syntaxhighlight lang=&amp;quot;csharp&amp;quot; line highlight=&amp;quot;3-5,8-9&amp;quot;&amp;gt;&lt;br /&gt;
public override Task&amp;lt;bool&amp;gt; StartAsync()&lt;br /&gt;
        {&lt;br /&gt;
            string targetExtNum = &amp;quot;100&amp;quot;; &lt;br /&gt;
            string mobileElu = &amp;quot;0699999999&amp;quot;;&lt;br /&gt;
            string profileName = &amp;quot;Away&amp;quot;; &lt;br /&gt;
&lt;br /&gt;
            // Nommage de l&#039;astreinte&lt;br /&gt;
            string prenomElu = &amp;quot;Marcel&amp;quot;; &lt;br /&gt;
            string nomElu = &amp;quot;Patulacci&amp;quot;; &lt;br /&gt;
&lt;br /&gt;
            try&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt; || &amp;lt;syntaxhighlight lang=&amp;quot;csharp&amp;quot; line highlight=&amp;quot;3-5,8-9&amp;quot;&amp;gt;&lt;br /&gt;
public override Task&amp;lt;bool&amp;gt; StartAsync()&lt;br /&gt;
        {&lt;br /&gt;
            string targetExtNum = &amp;quot;100&amp;quot;; &lt;br /&gt;
            string mobileElu = &amp;quot;0688888888&amp;quot;;&lt;br /&gt;
            string profileName = &amp;quot;Away&amp;quot;; &lt;br /&gt;
&lt;br /&gt;
            // Nommage de l&#039;astreinte&lt;br /&gt;
            string prenomElu = &amp;quot;Jean-Michel&amp;quot;; &lt;br /&gt;
            string nomElu = &amp;quot;Apeuprè&amp;quot;; &lt;br /&gt;
&lt;br /&gt;
            try&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;|| &amp;lt;syntaxhighlight lang=&amp;quot;csharp&amp;quot; line highlight=&amp;quot;3-5,8-9&amp;quot;&amp;gt;&lt;br /&gt;
public override Task&amp;lt;bool&amp;gt; StartAsync()&lt;br /&gt;
        {&lt;br /&gt;
            string targetExtNum = &amp;quot;100&amp;quot;; &lt;br /&gt;
            string mobileElu = &amp;quot;&amp;quot;;&lt;br /&gt;
            string profileName = &amp;quot;Available&amp;quot;; &lt;br /&gt;
&lt;br /&gt;
            // Nommage de l&#039;astreinte&lt;br /&gt;
            string prenomElu = &amp;quot;Accueil&amp;quot;; &lt;br /&gt;
            string nomElu = &amp;quot;&amp;quot;; &lt;br /&gt;
&lt;br /&gt;
            try&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Une fois les 3 scripts produits, passer à l&#039;étape [[Astreinte#Déclaration_du_script|Déclaration du script]] qui va permettre d&#039;affecter un code court à chaque script.&lt;br /&gt;
Exemple : &lt;br /&gt;
* *90 pour hors période d&#039;astreinte&lt;br /&gt;
* *91 pour Jean-Michel&lt;br /&gt;
* *92 pour Marcel&lt;br /&gt;
&lt;br /&gt;
On peut communiquer les codes aux personnes habilitées à gérer le système d&#039;astreinte et aller jusqu&#039;à paramétrer des BLF pour faciliter la vie d&#039;une secrétaire par exemple.&lt;br /&gt;
&lt;br /&gt;
{{Valide|v20}}&lt;br /&gt;
[[Catégorie:3CX]]&lt;/div&gt;</summary>
		<author><name>Anthony</name></author>
	</entry>
	<entry>
		<id>https://indywiki.fr/index.php?title=Fichier:2026-04-03_13h29_01.png&amp;diff=22251</id>
		<title>Fichier:2026-04-03 13h29 01.png</title>
		<link rel="alternate" type="text/html" href="https://indywiki.fr/index.php?title=Fichier:2026-04-03_13h29_01.png&amp;diff=22251"/>
		<updated>2026-04-03T11:35:47Z</updated>

		<summary type="html">&lt;p&gt;Anthony : Anthony a téléversé une nouvelle version de Fichier:2026-04-03 13h29 01.png&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;renvoi vers mon mobile&lt;/div&gt;</summary>
		<author><name>Anthony</name></author>
	</entry>
	<entry>
		<id>https://indywiki.fr/index.php?title=Astreinte&amp;diff=22250</id>
		<title>Astreinte</title>
		<link rel="alternate" type="text/html" href="https://indywiki.fr/index.php?title=Astreinte&amp;diff=22250"/>
		<updated>2026-04-03T11:30:35Z</updated>

		<summary type="html">&lt;p&gt;Anthony : /* Par le statut + script */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== par le statut ==&lt;br /&gt;
Dans les réglages de l&#039;extension qui accueille les appels :&lt;br /&gt;
[[Fichier:2026-04-02 16h03 02.png|vignette]]&lt;br /&gt;
#Réglages&lt;br /&gt;
#Transfert d&#039;appels&lt;br /&gt;
#Choisir le statut de l&#039;extension à activer pour enclencher le renvoi vers l&#039;astreinte. Dans l&#039;exemple &#039;&#039;&#039;Absent&#039;&#039;&#039;. Pas l&#039;état &#039;&#039;&#039;Disponible&#039;&#039;&#039; évidemment.&lt;br /&gt;
#Dans &amp;quot;Transférer les appels externes à&amp;quot;, choisir &#039;&#039;&#039;Numéro externe&#039;&#039;&#039;&lt;br /&gt;
#Saisir le numéro de l&#039;astreinte&lt;br /&gt;
#Cocher &#039;&#039;&#039;Rebond&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Limite / contrainte : &lt;br /&gt;
*si les astreintes tournent, avant chaque période d&#039;astreinte, il faut faire ce cheminement pour que le bon numéro de mobile soit paramétré&lt;br /&gt;
*4 profils d&#039;astreinte maximum&lt;br /&gt;
*Nécessite de manipuler l&#039;application WEB&lt;br /&gt;
&lt;br /&gt;
== Par le statut + script==&lt;br /&gt;
===Principe===&lt;br /&gt;
On paramètre le statut choisi pour l&#039;astreinte en renvoi vers &#039;&#039;&#039;mon mobile&#039;&#039;&#039;. Un script viendra modifier le statut de l&#039;extension cible ainsi que son numéro de contact mobile, prénom et nom. Ce script déclenchable par l&#039;appel à un code court, paramétrable si on le souhaite sur une BLF. &lt;br /&gt;
===Paramétrage du statut de l&#039;extension vers &#039;&#039;&#039;mon mobile&#039;&#039;&#039;===&lt;br /&gt;
&lt;br /&gt;
[[Fichier:2026-04-03 13h29 01.png|vignette]]&lt;br /&gt;
&lt;br /&gt;
===Déclaration du script===&lt;br /&gt;
[[Fichier:2026-04-02 17h11 35.png|vignette]]&lt;br /&gt;
Rendez-vous dans :&lt;br /&gt;
&lt;br /&gt;
 Admin / Intégrations / Scripts d&#039;appels / + Ajouter personnalisé&lt;br /&gt;
&lt;br /&gt;
#Donner un nom au traitement de l&#039;appel. Exemple : &#039;&#039;&#039;astreinte_weekend&#039;&#039;&#039;&lt;br /&gt;
#Créer un code de raccourci, ce qui permettra d&#039;exécuter le script simplement en appelant ce code, et in fine par une BLF. Exemple : &#039;&#039;&#039;*99&#039;&#039;&#039;&lt;br /&gt;
#OK&lt;br /&gt;
#Coller dans le champ script le script paramétré ( voir section suivante )&lt;br /&gt;
#Sauvegarder&lt;br /&gt;
#Un message doit indiquer &#039;&#039;&#039;Compilation réussie !&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Le script===&lt;br /&gt;
&lt;br /&gt;
L&#039;éxécution du script va modifier l&#039;extension &#039;&#039;&#039;targetExtNum &#039;&#039;&#039;, il va le basculer sur le statut &#039;&#039;&#039;profileName &#039;&#039;&#039;, modifier son mobile de contact &#039;&#039;&#039;mobileElu &#039;&#039;&#039;, son nom et prénom.&lt;br /&gt;
&lt;br /&gt;
Il faut donc seulement modifier les lignes surlignés dans le code ci-dessous :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;csharp&amp;quot; line highlight=&amp;quot;14-16,19-20&amp;quot;&amp;gt;&lt;br /&gt;
using System;&lt;br /&gt;
using System.Threading.Tasks;&lt;br /&gt;
using TCX.Configuration;&lt;br /&gt;
using CallFlow;&lt;br /&gt;
using System.Linq;&lt;br /&gt;
using System.Collections.Generic;&lt;br /&gt;
&lt;br /&gt;
namespace dummy&lt;br /&gt;
{&lt;br /&gt;
    public class SetDynamicAstreinte : ScriptBase&amp;lt;SetDynamicAstreinte&amp;gt;&lt;br /&gt;
    {&lt;br /&gt;
        public override Task&amp;lt;bool&amp;gt; StartAsync()&lt;br /&gt;
        {&lt;br /&gt;
            string targetExtNum = &amp;quot;100&amp;quot;; &lt;br /&gt;
            string mobileElu = &amp;quot;0601020304&amp;quot;;&lt;br /&gt;
            string profileName = &amp;quot;Away&amp;quot;; &lt;br /&gt;
            &lt;br /&gt;
            // Nommage de l&#039;astreinte&lt;br /&gt;
            string prenomElu = &amp;quot;ASTREINTE&amp;quot;; &lt;br /&gt;
            string nomElu = &amp;quot;ELU&amp;quot;; &lt;br /&gt;
&lt;br /&gt;
            try&lt;br /&gt;
            {&lt;br /&gt;
                IPhoneSystem ps = PhoneSystem.Root;&lt;br /&gt;
                Extension targetExt = ps.GetDNByNumber(targetExtNum) as Extension;&lt;br /&gt;
&lt;br /&gt;
                if (targetExt != null)&lt;br /&gt;
                {&lt;br /&gt;
                    // 1. Mise à jour du numéro de mobile&lt;br /&gt;
                    targetExt.SetProperty(&amp;quot;MOBILENUMBER&amp;quot;, mobileElu);&lt;br /&gt;
&lt;br /&gt;
                    // 2. MISE À JOUR DU NOM&lt;br /&gt;
                    targetExt.FirstName = prenomElu;&lt;br /&gt;
                    targetExt.LastName = nomElu;&lt;br /&gt;
&lt;br /&gt;
                    // 3. Changement du profil de statut&lt;br /&gt;
                    var profile = targetExt.FwdProfiles.FirstOrDefault(p =&amp;gt; p.Name.Equals(profileName, StringComparison.OrdinalIgnoreCase));&lt;br /&gt;
                    &lt;br /&gt;
                    if (profile != null)&lt;br /&gt;
                    {&lt;br /&gt;
                        targetExt.CurrentProfile = profile;&lt;br /&gt;
                    }&lt;br /&gt;
&lt;br /&gt;
                    // 4. Sauvegarde globale&lt;br /&gt;
                    targetExt.ResetCurrentProfileOverride();&lt;br /&gt;
                    targetExt.Save();&lt;br /&gt;
&lt;br /&gt;
                    return Task.FromResult(true);&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            catch (Exception)&lt;br /&gt;
            {&lt;br /&gt;
                // Erreur silencieuse&lt;br /&gt;
            }&lt;br /&gt;
            return Task.FromResult(false);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Table de correspondance des profileName====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Dans 3CX!! Dans le script&lt;br /&gt;
|-&lt;br /&gt;
| Disponible|| Available&lt;br /&gt;
|-&lt;br /&gt;
| Absent|| Away&lt;br /&gt;
|-&lt;br /&gt;
| Ne pas déranger|| Out of office&lt;br /&gt;
|-&lt;br /&gt;
| Custom 1|| Custom 1&lt;br /&gt;
|-&lt;br /&gt;
| Custom 2|| Custom 2&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===Configuration concrète===&lt;br /&gt;
&lt;br /&gt;
Il faut choisir un statut autre que &amp;quot;Disponible&amp;quot; qui sera activé pour l&#039;astreinte, &amp;quot;Away&amp;quot; pour cet exemple&lt;br /&gt;
&lt;br /&gt;
On a besoin de gérer deux astreintes. Le poste Accueil reçoit les appels en temps normal&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Texte de la légende&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;Marcel Patulacci&#039;&#039;&#039; || &#039;&#039;&#039;Jean-Michel Apeuprè&#039;&#039;&#039;|| &#039;&#039;&#039;Poste accueil &#039;&#039;&#039; hors période d&#039;astreinte&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;syntaxhighlight lang=&amp;quot;csharp&amp;quot; line highlight=&amp;quot;3-5,8-9&amp;quot;&amp;gt;&lt;br /&gt;
public override Task&amp;lt;bool&amp;gt; StartAsync()&lt;br /&gt;
        {&lt;br /&gt;
            string targetExtNum = &amp;quot;100&amp;quot;; &lt;br /&gt;
            string mobileElu = &amp;quot;0699999999&amp;quot;;&lt;br /&gt;
            string profileName = &amp;quot;Away&amp;quot;; &lt;br /&gt;
&lt;br /&gt;
            // Nommage de l&#039;astreinte&lt;br /&gt;
            string prenomElu = &amp;quot;Marcel&amp;quot;; &lt;br /&gt;
            string nomElu = &amp;quot;Patulacci&amp;quot;; &lt;br /&gt;
&lt;br /&gt;
            try&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt; || &amp;lt;syntaxhighlight lang=&amp;quot;csharp&amp;quot; line highlight=&amp;quot;3-5,8-9&amp;quot;&amp;gt;&lt;br /&gt;
public override Task&amp;lt;bool&amp;gt; StartAsync()&lt;br /&gt;
        {&lt;br /&gt;
            string targetExtNum = &amp;quot;100&amp;quot;; &lt;br /&gt;
            string mobileElu = &amp;quot;0688888888&amp;quot;;&lt;br /&gt;
            string profileName = &amp;quot;Away&amp;quot;; &lt;br /&gt;
&lt;br /&gt;
            // Nommage de l&#039;astreinte&lt;br /&gt;
            string prenomElu = &amp;quot;Jean-Michel&amp;quot;; &lt;br /&gt;
            string nomElu = &amp;quot;Apeuprè&amp;quot;; &lt;br /&gt;
&lt;br /&gt;
            try&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;|| &amp;lt;syntaxhighlight lang=&amp;quot;csharp&amp;quot; line highlight=&amp;quot;3-5,8-9&amp;quot;&amp;gt;&lt;br /&gt;
public override Task&amp;lt;bool&amp;gt; StartAsync()&lt;br /&gt;
        {&lt;br /&gt;
            string targetExtNum = &amp;quot;100&amp;quot;; &lt;br /&gt;
            string mobileElu = &amp;quot;&amp;quot;;&lt;br /&gt;
            string profileName = &amp;quot;Available&amp;quot;; &lt;br /&gt;
&lt;br /&gt;
            // Nommage de l&#039;astreinte&lt;br /&gt;
            string prenomElu = &amp;quot;Accueil&amp;quot;; &lt;br /&gt;
            string nomElu = &amp;quot;&amp;quot;; &lt;br /&gt;
&lt;br /&gt;
            try&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Une fois les 3 scripts produits, passer à l&#039;étape [[Astreinte#Déclaration_du_script|Déclaration du script]] qui va permettre d&#039;affecter un code court à chaque script.&lt;br /&gt;
Exemple : &lt;br /&gt;
* *90 pour hors période d&#039;astreinte&lt;br /&gt;
* *91 pour Jean-Michel&lt;br /&gt;
* *92 pour Marcel&lt;br /&gt;
&lt;br /&gt;
On peut communiquer les codes aux personnes habilitées à gérer le système d&#039;astreinte et aller jusqu&#039;à paramétrer des BLF pour faciliter la vie d&#039;une secrétaire par exemple.&lt;br /&gt;
&lt;br /&gt;
{{Valide|v20}}&lt;br /&gt;
[[Catégorie:3CX]]&lt;/div&gt;</summary>
		<author><name>Anthony</name></author>
	</entry>
	<entry>
		<id>https://indywiki.fr/index.php?title=Fichier:2026-04-03_13h29_01.png&amp;diff=22249</id>
		<title>Fichier:2026-04-03 13h29 01.png</title>
		<link rel="alternate" type="text/html" href="https://indywiki.fr/index.php?title=Fichier:2026-04-03_13h29_01.png&amp;diff=22249"/>
		<updated>2026-04-03T11:30:27Z</updated>

		<summary type="html">&lt;p&gt;Anthony : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;renvoi vers mon mobile&lt;/div&gt;</summary>
		<author><name>Anthony</name></author>
	</entry>
	<entry>
		<id>https://indywiki.fr/index.php?title=Astreinte&amp;diff=22248</id>
		<title>Astreinte</title>
		<link rel="alternate" type="text/html" href="https://indywiki.fr/index.php?title=Astreinte&amp;diff=22248"/>
		<updated>2026-04-03T11:26:49Z</updated>

		<summary type="html">&lt;p&gt;Anthony : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== par le statut ==&lt;br /&gt;
Dans les réglages de l&#039;extension qui accueille les appels :&lt;br /&gt;
[[Fichier:2026-04-02 16h03 02.png|vignette]]&lt;br /&gt;
#Réglages&lt;br /&gt;
#Transfert d&#039;appels&lt;br /&gt;
#Choisir le statut de l&#039;extension à activer pour enclencher le renvoi vers l&#039;astreinte. Dans l&#039;exemple &#039;&#039;&#039;Absent&#039;&#039;&#039;. Pas l&#039;état &#039;&#039;&#039;Disponible&#039;&#039;&#039; évidemment.&lt;br /&gt;
#Dans &amp;quot;Transférer les appels externes à&amp;quot;, choisir &#039;&#039;&#039;Numéro externe&#039;&#039;&#039;&lt;br /&gt;
#Saisir le numéro de l&#039;astreinte&lt;br /&gt;
#Cocher &#039;&#039;&#039;Rebond&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Limite / contrainte : &lt;br /&gt;
*si les astreintes tournent, avant chaque période d&#039;astreinte, il faut faire ce cheminement pour que le bon numéro de mobile soit paramétré&lt;br /&gt;
*4 profils d&#039;astreinte maximum&lt;br /&gt;
*Nécessite de manipuler l&#039;application WEB&lt;br /&gt;
&lt;br /&gt;
== Par le statut + script==&lt;br /&gt;
===Principe===&lt;br /&gt;
On paramètre le statut choisi pour l&#039;astreinte en renvoi vers &#039;&#039;&#039;mon mobile&#039;&#039;&#039;. Un script viendra modifier le statut de l&#039;extension cible ainsi que son numéro de contact mobile, prénom et nom. Ce script déclenchable par l&#039;appel à un code court, paramétrable si on le souhaite sur une BLF. &lt;br /&gt;
===Paramétrage du statut de l&#039;extension vers &#039;&#039;&#039;mon mobile&#039;&#039;&#039;===&lt;br /&gt;
&lt;br /&gt;
[[Fichier:2026-04-02 16h03 02.png|vignette]]&lt;br /&gt;
&lt;br /&gt;
===Déclaration du script===&lt;br /&gt;
[[Fichier:2026-04-02 17h11 35.png|vignette]]&lt;br /&gt;
Rendez-vous dans :&lt;br /&gt;
&lt;br /&gt;
 Admin / Intégrations / Scripts d&#039;appels / + Ajouter personnalisé&lt;br /&gt;
&lt;br /&gt;
#Donner un nom au traitement de l&#039;appel. Exemple : &#039;&#039;&#039;astreinte_weekend&#039;&#039;&#039;&lt;br /&gt;
#Créer un code de raccourci, ce qui permettra d&#039;exécuter le script simplement en appelant ce code, et in fine par une BLF. Exemple : &#039;&#039;&#039;*99&#039;&#039;&#039;&lt;br /&gt;
#OK&lt;br /&gt;
#Coller dans le champ script le script paramétré ( voir section suivante )&lt;br /&gt;
#Sauvegarder&lt;br /&gt;
#Un message doit indiquer &#039;&#039;&#039;Compilation réussie !&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Le script===&lt;br /&gt;
&lt;br /&gt;
L&#039;éxécution du script va modifier l&#039;extension &#039;&#039;&#039;targetExtNum &#039;&#039;&#039;, il va le basculer sur le statut &#039;&#039;&#039;profileName &#039;&#039;&#039;, modifier son mobile de contact &#039;&#039;&#039;mobileElu &#039;&#039;&#039;, son nom et prénom.&lt;br /&gt;
&lt;br /&gt;
Il faut donc seulement modifier les lignes surlignés dans le code ci-dessous :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;csharp&amp;quot; line highlight=&amp;quot;14-16,19-20&amp;quot;&amp;gt;&lt;br /&gt;
using System;&lt;br /&gt;
using System.Threading.Tasks;&lt;br /&gt;
using TCX.Configuration;&lt;br /&gt;
using CallFlow;&lt;br /&gt;
using System.Linq;&lt;br /&gt;
using System.Collections.Generic;&lt;br /&gt;
&lt;br /&gt;
namespace dummy&lt;br /&gt;
{&lt;br /&gt;
    public class SetDynamicAstreinte : ScriptBase&amp;lt;SetDynamicAstreinte&amp;gt;&lt;br /&gt;
    {&lt;br /&gt;
        public override Task&amp;lt;bool&amp;gt; StartAsync()&lt;br /&gt;
        {&lt;br /&gt;
            string targetExtNum = &amp;quot;100&amp;quot;; &lt;br /&gt;
            string mobileElu = &amp;quot;0601020304&amp;quot;;&lt;br /&gt;
            string profileName = &amp;quot;Away&amp;quot;; &lt;br /&gt;
            &lt;br /&gt;
            // Nommage de l&#039;astreinte&lt;br /&gt;
            string prenomElu = &amp;quot;ASTREINTE&amp;quot;; &lt;br /&gt;
            string nomElu = &amp;quot;ELU&amp;quot;; &lt;br /&gt;
&lt;br /&gt;
            try&lt;br /&gt;
            {&lt;br /&gt;
                IPhoneSystem ps = PhoneSystem.Root;&lt;br /&gt;
                Extension targetExt = ps.GetDNByNumber(targetExtNum) as Extension;&lt;br /&gt;
&lt;br /&gt;
                if (targetExt != null)&lt;br /&gt;
                {&lt;br /&gt;
                    // 1. Mise à jour du numéro de mobile&lt;br /&gt;
                    targetExt.SetProperty(&amp;quot;MOBILENUMBER&amp;quot;, mobileElu);&lt;br /&gt;
&lt;br /&gt;
                    // 2. MISE À JOUR DU NOM&lt;br /&gt;
                    targetExt.FirstName = prenomElu;&lt;br /&gt;
                    targetExt.LastName = nomElu;&lt;br /&gt;
&lt;br /&gt;
                    // 3. Changement du profil de statut&lt;br /&gt;
                    var profile = targetExt.FwdProfiles.FirstOrDefault(p =&amp;gt; p.Name.Equals(profileName, StringComparison.OrdinalIgnoreCase));&lt;br /&gt;
                    &lt;br /&gt;
                    if (profile != null)&lt;br /&gt;
                    {&lt;br /&gt;
                        targetExt.CurrentProfile = profile;&lt;br /&gt;
                    }&lt;br /&gt;
&lt;br /&gt;
                    // 4. Sauvegarde globale&lt;br /&gt;
                    targetExt.ResetCurrentProfileOverride();&lt;br /&gt;
                    targetExt.Save();&lt;br /&gt;
&lt;br /&gt;
                    return Task.FromResult(true);&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            catch (Exception)&lt;br /&gt;
            {&lt;br /&gt;
                // Erreur silencieuse&lt;br /&gt;
            }&lt;br /&gt;
            return Task.FromResult(false);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Table de correspondance des profileName====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Dans 3CX!! Dans le script&lt;br /&gt;
|-&lt;br /&gt;
| Disponible|| Available&lt;br /&gt;
|-&lt;br /&gt;
| Absent|| Away&lt;br /&gt;
|-&lt;br /&gt;
| Ne pas déranger|| Out of office&lt;br /&gt;
|-&lt;br /&gt;
| Custom 1|| Custom 1&lt;br /&gt;
|-&lt;br /&gt;
| Custom 2|| Custom 2&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===Configuration concrète===&lt;br /&gt;
&lt;br /&gt;
Il faut choisir un statut autre que &amp;quot;Disponible&amp;quot; qui sera activé pour l&#039;astreinte, &amp;quot;Away&amp;quot; pour cet exemple&lt;br /&gt;
&lt;br /&gt;
On a besoin de gérer deux astreintes. Le poste Accueil reçoit les appels en temps normal&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Texte de la légende&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;Marcel Patulacci&#039;&#039;&#039; || &#039;&#039;&#039;Jean-Michel Apeuprè&#039;&#039;&#039;|| &#039;&#039;&#039;Poste accueil &#039;&#039;&#039; hors période d&#039;astreinte&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;syntaxhighlight lang=&amp;quot;csharp&amp;quot; line highlight=&amp;quot;3-5,8-9&amp;quot;&amp;gt;&lt;br /&gt;
public override Task&amp;lt;bool&amp;gt; StartAsync()&lt;br /&gt;
        {&lt;br /&gt;
            string targetExtNum = &amp;quot;100&amp;quot;; &lt;br /&gt;
            string mobileElu = &amp;quot;0699999999&amp;quot;;&lt;br /&gt;
            string profileName = &amp;quot;Away&amp;quot;; &lt;br /&gt;
&lt;br /&gt;
            // Nommage de l&#039;astreinte&lt;br /&gt;
            string prenomElu = &amp;quot;Marcel&amp;quot;; &lt;br /&gt;
            string nomElu = &amp;quot;Patulacci&amp;quot;; &lt;br /&gt;
&lt;br /&gt;
            try&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt; || &amp;lt;syntaxhighlight lang=&amp;quot;csharp&amp;quot; line highlight=&amp;quot;3-5,8-9&amp;quot;&amp;gt;&lt;br /&gt;
public override Task&amp;lt;bool&amp;gt; StartAsync()&lt;br /&gt;
        {&lt;br /&gt;
            string targetExtNum = &amp;quot;100&amp;quot;; &lt;br /&gt;
            string mobileElu = &amp;quot;0688888888&amp;quot;;&lt;br /&gt;
            string profileName = &amp;quot;Away&amp;quot;; &lt;br /&gt;
&lt;br /&gt;
            // Nommage de l&#039;astreinte&lt;br /&gt;
            string prenomElu = &amp;quot;Jean-Michel&amp;quot;; &lt;br /&gt;
            string nomElu = &amp;quot;Apeuprè&amp;quot;; &lt;br /&gt;
&lt;br /&gt;
            try&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;|| &amp;lt;syntaxhighlight lang=&amp;quot;csharp&amp;quot; line highlight=&amp;quot;3-5,8-9&amp;quot;&amp;gt;&lt;br /&gt;
public override Task&amp;lt;bool&amp;gt; StartAsync()&lt;br /&gt;
        {&lt;br /&gt;
            string targetExtNum = &amp;quot;100&amp;quot;; &lt;br /&gt;
            string mobileElu = &amp;quot;&amp;quot;;&lt;br /&gt;
            string profileName = &amp;quot;Available&amp;quot;; &lt;br /&gt;
&lt;br /&gt;
            // Nommage de l&#039;astreinte&lt;br /&gt;
            string prenomElu = &amp;quot;Accueil&amp;quot;; &lt;br /&gt;
            string nomElu = &amp;quot;&amp;quot;; &lt;br /&gt;
&lt;br /&gt;
            try&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Une fois les 3 scripts produits, passer à l&#039;étape [[Astreinte#Déclaration_du_script|Déclaration du script]] qui va permettre d&#039;affecter un code court à chaque script.&lt;br /&gt;
Exemple : &lt;br /&gt;
* *90 pour hors période d&#039;astreinte&lt;br /&gt;
* *91 pour Jean-Michel&lt;br /&gt;
* *92 pour Marcel&lt;br /&gt;
&lt;br /&gt;
On peut communiquer les codes aux personnes habilitées à gérer le système d&#039;astreinte et aller jusqu&#039;à paramétrer des BLF pour faciliter la vie d&#039;une secrétaire par exemple.&lt;br /&gt;
&lt;br /&gt;
{{Valide|v20}}&lt;br /&gt;
[[Catégorie:3CX]]&lt;/div&gt;</summary>
		<author><name>Anthony</name></author>
	</entry>
	<entry>
		<id>https://indywiki.fr/index.php?title=Astreinte&amp;diff=22247</id>
		<title>Astreinte</title>
		<link rel="alternate" type="text/html" href="https://indywiki.fr/index.php?title=Astreinte&amp;diff=22247"/>
		<updated>2026-04-03T09:30:58Z</updated>

		<summary type="html">&lt;p&gt;Anthony : /* par le statut */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== par le statut ==&lt;br /&gt;
Dans les réglages de l&#039;extension qui accueille les appels :&lt;br /&gt;
[[Fichier:2026-04-02 16h03 02.png|vignette]]&lt;br /&gt;
#Réglages&lt;br /&gt;
#Transfert d&#039;appels&lt;br /&gt;
#Choisir le statut de l&#039;extension à activer pour enclencher le renvoi vers l&#039;astreinte. Dans l&#039;exemple &#039;&#039;&#039;Absent&#039;&#039;&#039;. Pas l&#039;état &#039;&#039;&#039;Disponible&#039;&#039;&#039; évidemment.&lt;br /&gt;
#Dans &amp;quot;Transférer les appels externes à&amp;quot;, choisir &#039;&#039;&#039;Numéro externe&#039;&#039;&#039;&lt;br /&gt;
#Saisir le numéro de l&#039;astreinte&lt;br /&gt;
#Cocher &#039;&#039;&#039;Rebond&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Limite / contrainte : &lt;br /&gt;
*si les astreintes tournent, avant chaque période d&#039;astreinte, il faut faire ce cheminement pour que le bon numéro de mobile soit paramétré&lt;br /&gt;
*4 profils d&#039;astreinte maximum&lt;br /&gt;
*Nécessite de manipuler l&#039;application WEB&lt;br /&gt;
&lt;br /&gt;
== Par le statut + script==&lt;br /&gt;
===Principe===&lt;br /&gt;
On paramètre le statut choisi pour l&#039;astreinte en renvoi vers &#039;&#039;&#039;mon mobile&#039;&#039;&#039;. Un script viendra modifier le statut de l&#039;extension cible ainsi que son numéro de contact mobile, prénom et nom. Ce script déclenchable par l&#039;appel à un code court, paramétrable si on le souhaite sur une BLF. &lt;br /&gt;
===Paramétrage du statut de l&#039;extension vers &#039;&#039;&#039;mon mobile&#039;&#039;&#039;===&lt;br /&gt;
&lt;br /&gt;
[[Fichier:2026-04-03 11h09 54.png|cadre|néant]]&lt;br /&gt;
&lt;br /&gt;
===Déclaration du script===&lt;br /&gt;
[[Fichier:2026-04-02 17h11 35.png|vignette]]&lt;br /&gt;
Rendez-vous dans :&lt;br /&gt;
&lt;br /&gt;
 Admin / Intégrations / Scripts d&#039;appels / + Ajouter personnalisé&lt;br /&gt;
&lt;br /&gt;
#Donner un nom au traitement de l&#039;appel. Exemple : &#039;&#039;&#039;astreinte_weekend&#039;&#039;&#039;&lt;br /&gt;
#Créer un code de raccourci, ce qui permettra d&#039;exécuter le script simplement en appelant ce code, et in fine par une BLF. Exemple : &#039;&#039;&#039;*99&#039;&#039;&#039;&lt;br /&gt;
#OK&lt;br /&gt;
#Coller dans le champ script le script paramétré ( voir section suivante )&lt;br /&gt;
#Sauvegarder&lt;br /&gt;
#Un message doit indiquer &#039;&#039;&#039;Compilation réussie !&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Le script===&lt;br /&gt;
&lt;br /&gt;
L&#039;éxécution du script va modifier l&#039;extension &#039;&#039;&#039;targetExtNum &#039;&#039;&#039;, il va le basculer sur le statut &#039;&#039;&#039;profileName &#039;&#039;&#039;, modifier son mobile de contact &#039;&#039;&#039;mobileElu &#039;&#039;&#039;, son nom et prénom.&lt;br /&gt;
&lt;br /&gt;
Il faut donc seulement modifier les lignes surlignés dans le code ci-dessous :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;csharp&amp;quot; line highlight=&amp;quot;14-16,19-20&amp;quot;&amp;gt;&lt;br /&gt;
using System;&lt;br /&gt;
using System.Threading.Tasks;&lt;br /&gt;
using TCX.Configuration;&lt;br /&gt;
using CallFlow;&lt;br /&gt;
using System.Linq;&lt;br /&gt;
using System.Collections.Generic;&lt;br /&gt;
&lt;br /&gt;
namespace dummy&lt;br /&gt;
{&lt;br /&gt;
    public class SetDynamicAstreinte : ScriptBase&amp;lt;SetDynamicAstreinte&amp;gt;&lt;br /&gt;
    {&lt;br /&gt;
        public override Task&amp;lt;bool&amp;gt; StartAsync()&lt;br /&gt;
        {&lt;br /&gt;
            string targetExtNum = &amp;quot;100&amp;quot;; &lt;br /&gt;
            string mobileElu = &amp;quot;0601020304&amp;quot;;&lt;br /&gt;
            string profileName = &amp;quot;Away&amp;quot;; &lt;br /&gt;
            &lt;br /&gt;
            // Nommage de l&#039;astreinte&lt;br /&gt;
            string prenomElu = &amp;quot;ASTREINTE&amp;quot;; &lt;br /&gt;
            string nomElu = &amp;quot;ELU&amp;quot;; &lt;br /&gt;
&lt;br /&gt;
            try&lt;br /&gt;
            {&lt;br /&gt;
                IPhoneSystem ps = PhoneSystem.Root;&lt;br /&gt;
                Extension targetExt = ps.GetDNByNumber(targetExtNum) as Extension;&lt;br /&gt;
&lt;br /&gt;
                if (targetExt != null)&lt;br /&gt;
                {&lt;br /&gt;
                    // 1. Mise à jour du numéro de mobile&lt;br /&gt;
                    targetExt.SetProperty(&amp;quot;MOBILENUMBER&amp;quot;, mobileElu);&lt;br /&gt;
&lt;br /&gt;
                    // 2. MISE À JOUR DU NOM&lt;br /&gt;
                    targetExt.FirstName = prenomElu;&lt;br /&gt;
                    targetExt.LastName = nomElu;&lt;br /&gt;
&lt;br /&gt;
                    // 3. Changement du profil de statut&lt;br /&gt;
                    var profile = targetExt.FwdProfiles.FirstOrDefault(p =&amp;gt; p.Name.Equals(profileName, StringComparison.OrdinalIgnoreCase));&lt;br /&gt;
                    &lt;br /&gt;
                    if (profile != null)&lt;br /&gt;
                    {&lt;br /&gt;
                        targetExt.CurrentProfile = profile;&lt;br /&gt;
                    }&lt;br /&gt;
&lt;br /&gt;
                    // 4. Sauvegarde globale&lt;br /&gt;
                    targetExt.ResetCurrentProfileOverride();&lt;br /&gt;
                    targetExt.Save();&lt;br /&gt;
&lt;br /&gt;
                    return Task.FromResult(true);&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            catch (Exception)&lt;br /&gt;
            {&lt;br /&gt;
                // Erreur silencieuse&lt;br /&gt;
            }&lt;br /&gt;
            return Task.FromResult(false);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Table de correspondance des profileName====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Dans 3CX!! Dans le script&lt;br /&gt;
|-&lt;br /&gt;
| Disponible|| Available&lt;br /&gt;
|-&lt;br /&gt;
| Absent|| Away&lt;br /&gt;
|-&lt;br /&gt;
| Ne pas déranger|| Out of office&lt;br /&gt;
|-&lt;br /&gt;
| Custom 1|| Custom 1&lt;br /&gt;
|-&lt;br /&gt;
| Custom 2|| Custom 2&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===Configuration concrète===&lt;br /&gt;
&lt;br /&gt;
Il faut choisir un statut autre que &amp;quot;Disponible&amp;quot; qui sera activé pour l&#039;astreinte, &amp;quot;Away&amp;quot; pour cet exemple&lt;br /&gt;
&lt;br /&gt;
On a besoin de gérer deux astreintes. Le poste Accueil reçoit les appels en temps normal&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Texte de la légende&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;Marcel Patulacci&#039;&#039;&#039; || &#039;&#039;&#039;Jean-Michel Apeuprè&#039;&#039;&#039;|| &#039;&#039;&#039;Poste accueil &#039;&#039;&#039; hors période d&#039;astreinte&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;syntaxhighlight lang=&amp;quot;csharp&amp;quot; line highlight=&amp;quot;3-5,8-9&amp;quot;&amp;gt;&lt;br /&gt;
public override Task&amp;lt;bool&amp;gt; StartAsync()&lt;br /&gt;
        {&lt;br /&gt;
            string targetExtNum = &amp;quot;100&amp;quot;; &lt;br /&gt;
            string mobileElu = &amp;quot;0699999999&amp;quot;;&lt;br /&gt;
            string profileName = &amp;quot;Away&amp;quot;; &lt;br /&gt;
&lt;br /&gt;
            // Nommage de l&#039;astreinte&lt;br /&gt;
            string prenomElu = &amp;quot;Marcel&amp;quot;; &lt;br /&gt;
            string nomElu = &amp;quot;Patulacci&amp;quot;; &lt;br /&gt;
&lt;br /&gt;
            try&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt; || &amp;lt;syntaxhighlight lang=&amp;quot;csharp&amp;quot; line highlight=&amp;quot;3-5,8-9&amp;quot;&amp;gt;&lt;br /&gt;
public override Task&amp;lt;bool&amp;gt; StartAsync()&lt;br /&gt;
        {&lt;br /&gt;
            string targetExtNum = &amp;quot;100&amp;quot;; &lt;br /&gt;
            string mobileElu = &amp;quot;0688888888&amp;quot;;&lt;br /&gt;
            string profileName = &amp;quot;Away&amp;quot;; &lt;br /&gt;
&lt;br /&gt;
            // Nommage de l&#039;astreinte&lt;br /&gt;
            string prenomElu = &amp;quot;Jean-Michel&amp;quot;; &lt;br /&gt;
            string nomElu = &amp;quot;Apeuprè&amp;quot;; &lt;br /&gt;
&lt;br /&gt;
            try&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;|| &amp;lt;syntaxhighlight lang=&amp;quot;csharp&amp;quot; line highlight=&amp;quot;3-5,8-9&amp;quot;&amp;gt;&lt;br /&gt;
public override Task&amp;lt;bool&amp;gt; StartAsync()&lt;br /&gt;
        {&lt;br /&gt;
            string targetExtNum = &amp;quot;100&amp;quot;; &lt;br /&gt;
            string mobileElu = &amp;quot;&amp;quot;;&lt;br /&gt;
            string profileName = &amp;quot;Available&amp;quot;; &lt;br /&gt;
&lt;br /&gt;
            // Nommage de l&#039;astreinte&lt;br /&gt;
            string prenomElu = &amp;quot;Accueil&amp;quot;; &lt;br /&gt;
            string nomElu = &amp;quot;&amp;quot;; &lt;br /&gt;
&lt;br /&gt;
            try&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Une fois les 3 scripts produits, passer à l&#039;étape [[Astreinte#Déclaration_du_script|Déclaration du script]] qui va permettre d&#039;affecter un code court à chaque script.&lt;br /&gt;
Exemple : &lt;br /&gt;
* *90 pour hors période d&#039;astreinte&lt;br /&gt;
* *91 pour Jean-Michel&lt;br /&gt;
* *92 pour Marcel&lt;br /&gt;
&lt;br /&gt;
On peut communiquer les codes aux personnes habilitées à gérer le système d&#039;astreinte et aller jusqu&#039;à paramétrer des BLF pour faciliter la vie d&#039;une secrétaire par exemple.&lt;br /&gt;
&lt;br /&gt;
{{Valide|v20}}&lt;br /&gt;
[[Catégorie:3CX]]&lt;/div&gt;</summary>
		<author><name>Anthony</name></author>
	</entry>
	<entry>
		<id>https://indywiki.fr/index.php?title=Astreinte&amp;diff=22246</id>
		<title>Astreinte</title>
		<link rel="alternate" type="text/html" href="https://indywiki.fr/index.php?title=Astreinte&amp;diff=22246"/>
		<updated>2026-04-03T09:29:50Z</updated>

		<summary type="html">&lt;p&gt;Anthony : /* Via script */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== par le statut ==&lt;br /&gt;
Dans les réglages de l&#039;extension qui accueille les appels :&lt;br /&gt;
[[Fichier:2026-04-02 16h03 02.png|vignette]]&lt;br /&gt;
#Réglages&lt;br /&gt;
#Transfert d&#039;appels&lt;br /&gt;
#Choisir le statut de l&#039;extension à activer pour enclencher le renvoi vers l&#039;astreinte. Dans l&#039;exemple &#039;&#039;&#039;Absent&#039;&#039;&#039;. Pas l&#039;état &#039;&#039;&#039;Disponible&#039;&#039;&#039; évidemment.&lt;br /&gt;
#Dans &amp;quot;Transférer les appels externes à&amp;quot;, choisir &#039;&#039;&#039;Numéro externe&#039;&#039;&#039;&lt;br /&gt;
#Saisir le numéro de l&#039;astreinte&lt;br /&gt;
#Cocher &#039;&#039;&#039;Rebond&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Limite / contrainte : &lt;br /&gt;
*si les astreintes tournent, avant chaque période d&#039;astreinte, il faut faire ce cheminement pour que le bon numéro de mobile soit paramétré&lt;br /&gt;
*4 profils d&#039;astreinte maximum&lt;br /&gt;
*Nécessite de manipuler l&#039;application WEB&lt;br /&gt;
&lt;br /&gt;
== Par le statut + script==&lt;br /&gt;
===Principe===&lt;br /&gt;
On paramètre le statut choisi pour l&#039;astreinte en renvoi vers &#039;&#039;&#039;mon mobile&#039;&#039;&#039;. Un script viendra modifier le statut de l&#039;extension cible ainsi que son numéro de contact mobile, prénom et nom. Ce script déclenchable par l&#039;appel à un code court, paramétrable si on le souhaite sur une BLF. &lt;br /&gt;
===Paramétrage du statut de l&#039;extension vers &#039;&#039;&#039;mon mobile&#039;&#039;&#039;===&lt;br /&gt;
&lt;br /&gt;
[[Fichier:2026-04-03 11h09 54.png|cadre|néant]]&lt;br /&gt;
&lt;br /&gt;
===Déclaration du script===&lt;br /&gt;
[[Fichier:2026-04-02 17h11 35.png|vignette]]&lt;br /&gt;
Rendez-vous dans :&lt;br /&gt;
&lt;br /&gt;
 Admin / Intégrations / Scripts d&#039;appels / + Ajouter personnalisé&lt;br /&gt;
&lt;br /&gt;
#Donner un nom au traitement de l&#039;appel. Exemple : &#039;&#039;&#039;astreinte_weekend&#039;&#039;&#039;&lt;br /&gt;
#Créer un code de raccourci, ce qui permettra d&#039;exécuter le script simplement en appelant ce code, et in fine par une BLF. Exemple : &#039;&#039;&#039;*99&#039;&#039;&#039;&lt;br /&gt;
#OK&lt;br /&gt;
#Coller dans le champ script le script paramétré ( voir section suivante )&lt;br /&gt;
#Sauvegarder&lt;br /&gt;
#Un message doit indiquer &#039;&#039;&#039;Compilation réussie !&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Le script===&lt;br /&gt;
&lt;br /&gt;
L&#039;éxécution du script va modifier l&#039;extension &#039;&#039;&#039;targetExtNum &#039;&#039;&#039;, il va le basculer sur le statut &#039;&#039;&#039;profileName &#039;&#039;&#039;, modifier son mobile de contact &#039;&#039;&#039;mobileElu &#039;&#039;&#039;, son nom et prénom.&lt;br /&gt;
&lt;br /&gt;
Il faut donc seulement modifier les lignes surlignés dans le code ci-dessous :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;csharp&amp;quot; line highlight=&amp;quot;14-16,19-20&amp;quot;&amp;gt;&lt;br /&gt;
using System;&lt;br /&gt;
using System.Threading.Tasks;&lt;br /&gt;
using TCX.Configuration;&lt;br /&gt;
using CallFlow;&lt;br /&gt;
using System.Linq;&lt;br /&gt;
using System.Collections.Generic;&lt;br /&gt;
&lt;br /&gt;
namespace dummy&lt;br /&gt;
{&lt;br /&gt;
    public class SetDynamicAstreinte : ScriptBase&amp;lt;SetDynamicAstreinte&amp;gt;&lt;br /&gt;
    {&lt;br /&gt;
        public override Task&amp;lt;bool&amp;gt; StartAsync()&lt;br /&gt;
        {&lt;br /&gt;
            string targetExtNum = &amp;quot;100&amp;quot;; &lt;br /&gt;
            string mobileElu = &amp;quot;0601020304&amp;quot;;&lt;br /&gt;
            string profileName = &amp;quot;Away&amp;quot;; &lt;br /&gt;
            &lt;br /&gt;
            // Nommage de l&#039;astreinte&lt;br /&gt;
            string prenomElu = &amp;quot;ASTREINTE&amp;quot;; &lt;br /&gt;
            string nomElu = &amp;quot;ELU&amp;quot;; &lt;br /&gt;
&lt;br /&gt;
            try&lt;br /&gt;
            {&lt;br /&gt;
                IPhoneSystem ps = PhoneSystem.Root;&lt;br /&gt;
                Extension targetExt = ps.GetDNByNumber(targetExtNum) as Extension;&lt;br /&gt;
&lt;br /&gt;
                if (targetExt != null)&lt;br /&gt;
                {&lt;br /&gt;
                    // 1. Mise à jour du numéro de mobile&lt;br /&gt;
                    targetExt.SetProperty(&amp;quot;MOBILENUMBER&amp;quot;, mobileElu);&lt;br /&gt;
&lt;br /&gt;
                    // 2. MISE À JOUR DU NOM&lt;br /&gt;
                    targetExt.FirstName = prenomElu;&lt;br /&gt;
                    targetExt.LastName = nomElu;&lt;br /&gt;
&lt;br /&gt;
                    // 3. Changement du profil de statut&lt;br /&gt;
                    var profile = targetExt.FwdProfiles.FirstOrDefault(p =&amp;gt; p.Name.Equals(profileName, StringComparison.OrdinalIgnoreCase));&lt;br /&gt;
                    &lt;br /&gt;
                    if (profile != null)&lt;br /&gt;
                    {&lt;br /&gt;
                        targetExt.CurrentProfile = profile;&lt;br /&gt;
                    }&lt;br /&gt;
&lt;br /&gt;
                    // 4. Sauvegarde globale&lt;br /&gt;
                    targetExt.ResetCurrentProfileOverride();&lt;br /&gt;
                    targetExt.Save();&lt;br /&gt;
&lt;br /&gt;
                    return Task.FromResult(true);&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            catch (Exception)&lt;br /&gt;
            {&lt;br /&gt;
                // Erreur silencieuse&lt;br /&gt;
            }&lt;br /&gt;
            return Task.FromResult(false);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Table de correspondance des profileName====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Dans 3CX!! Dans le script&lt;br /&gt;
|-&lt;br /&gt;
| Disponible|| Available&lt;br /&gt;
|-&lt;br /&gt;
| Absent|| Away&lt;br /&gt;
|-&lt;br /&gt;
| Ne pas déranger|| Out of office&lt;br /&gt;
|-&lt;br /&gt;
| Custom 1|| Custom 1&lt;br /&gt;
|-&lt;br /&gt;
| Custom 2|| Custom 2&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===Configuration concrète===&lt;br /&gt;
&lt;br /&gt;
Il faut choisir un statut autre que &amp;quot;Disponible&amp;quot; qui sera activé pour l&#039;astreinte, &amp;quot;Away&amp;quot; pour cet exemple&lt;br /&gt;
&lt;br /&gt;
On a besoin de gérer deux astreintes. Le poste Accueil reçoit les appels en temps normal&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Texte de la légende&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;Marcel Patulacci&#039;&#039;&#039; || &#039;&#039;&#039;Jean-Michel Apeuprè&#039;&#039;&#039;|| &#039;&#039;&#039;Poste accueil &#039;&#039;&#039; hors période d&#039;astreinte&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;syntaxhighlight lang=&amp;quot;csharp&amp;quot; line highlight=&amp;quot;3-5,8-9&amp;quot;&amp;gt;&lt;br /&gt;
public override Task&amp;lt;bool&amp;gt; StartAsync()&lt;br /&gt;
        {&lt;br /&gt;
            string targetExtNum = &amp;quot;100&amp;quot;; &lt;br /&gt;
            string mobileElu = &amp;quot;0699999999&amp;quot;;&lt;br /&gt;
            string profileName = &amp;quot;Away&amp;quot;; &lt;br /&gt;
&lt;br /&gt;
            // Nommage de l&#039;astreinte&lt;br /&gt;
            string prenomElu = &amp;quot;Marcel&amp;quot;; &lt;br /&gt;
            string nomElu = &amp;quot;Patulacci&amp;quot;; &lt;br /&gt;
&lt;br /&gt;
            try&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt; || &amp;lt;syntaxhighlight lang=&amp;quot;csharp&amp;quot; line highlight=&amp;quot;3-5,8-9&amp;quot;&amp;gt;&lt;br /&gt;
public override Task&amp;lt;bool&amp;gt; StartAsync()&lt;br /&gt;
        {&lt;br /&gt;
            string targetExtNum = &amp;quot;100&amp;quot;; &lt;br /&gt;
            string mobileElu = &amp;quot;0688888888&amp;quot;;&lt;br /&gt;
            string profileName = &amp;quot;Away&amp;quot;; &lt;br /&gt;
&lt;br /&gt;
            // Nommage de l&#039;astreinte&lt;br /&gt;
            string prenomElu = &amp;quot;Jean-Michel&amp;quot;; &lt;br /&gt;
            string nomElu = &amp;quot;Apeuprè&amp;quot;; &lt;br /&gt;
&lt;br /&gt;
            try&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;|| &amp;lt;syntaxhighlight lang=&amp;quot;csharp&amp;quot; line highlight=&amp;quot;3-5,8-9&amp;quot;&amp;gt;&lt;br /&gt;
public override Task&amp;lt;bool&amp;gt; StartAsync()&lt;br /&gt;
        {&lt;br /&gt;
            string targetExtNum = &amp;quot;100&amp;quot;; &lt;br /&gt;
            string mobileElu = &amp;quot;&amp;quot;;&lt;br /&gt;
            string profileName = &amp;quot;Available&amp;quot;; &lt;br /&gt;
&lt;br /&gt;
            // Nommage de l&#039;astreinte&lt;br /&gt;
            string prenomElu = &amp;quot;Accueil&amp;quot;; &lt;br /&gt;
            string nomElu = &amp;quot;&amp;quot;; &lt;br /&gt;
&lt;br /&gt;
            try&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Une fois les 3 scripts produits, passer à l&#039;étape [[Astreinte#Déclaration_du_script|Déclaration du script]] qui va permettre d&#039;affecter un code court à chaque script.&lt;br /&gt;
Exemple : &lt;br /&gt;
* *90 pour hors période d&#039;astreinte&lt;br /&gt;
* *91 pour Jean-Michel&lt;br /&gt;
* *92 pour Marcel&lt;br /&gt;
&lt;br /&gt;
On peut communiquer les codes aux personnes habilitées à gérer le système d&#039;astreinte et aller jusqu&#039;à paramétrer des BLF pour faciliter la vie d&#039;une secrétaire par exemple.&lt;br /&gt;
&lt;br /&gt;
{{Valide|v20}}&lt;br /&gt;
[[Catégorie:3CX]]&lt;/div&gt;</summary>
		<author><name>Anthony</name></author>
	</entry>
	<entry>
		<id>https://indywiki.fr/index.php?title=Astreinte&amp;diff=22245</id>
		<title>Astreinte</title>
		<link rel="alternate" type="text/html" href="https://indywiki.fr/index.php?title=Astreinte&amp;diff=22245"/>
		<updated>2026-04-03T09:28:35Z</updated>

		<summary type="html">&lt;p&gt;Anthony : /* Configuration concrète */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== par le statut ==&lt;br /&gt;
Dans les réglages de l&#039;extension qui accueille les appels :&lt;br /&gt;
[[Fichier:2026-04-02 16h03 02.png|vignette]]&lt;br /&gt;
#Réglages&lt;br /&gt;
#Transfert d&#039;appels&lt;br /&gt;
#Choisir le statut de l&#039;extension à activer pour enclencher le renvoi vers l&#039;astreinte. Dans l&#039;exemple &#039;&#039;&#039;Absent&#039;&#039;&#039;. Pas l&#039;état &#039;&#039;&#039;Disponible&#039;&#039;&#039; évidemment.&lt;br /&gt;
#Dans &amp;quot;Transférer les appels externes à&amp;quot;, choisir &#039;&#039;&#039;Numéro externe&#039;&#039;&#039;&lt;br /&gt;
#Saisir le numéro de l&#039;astreinte&lt;br /&gt;
#Cocher &#039;&#039;&#039;Rebond&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Limite / contrainte : &lt;br /&gt;
*si les astreintes tournent, avant chaque période d&#039;astreinte, il faut faire ce cheminement pour que le bon numéro de mobile soit paramétré&lt;br /&gt;
*4 profils d&#039;astreinte maximum&lt;br /&gt;
*Nécessite de manipuler l&#039;application WEB&lt;br /&gt;
&lt;br /&gt;
== Via script==&lt;br /&gt;
===Principe===&lt;br /&gt;
On paramètre le statut choisi pour l&#039;astreinte en renvoi vers &#039;&#039;&#039;mon mobile&#039;&#039;&#039;. Un script viendra modifier le statut de l&#039;extension cible ainsi que son numéro de contact mobile, prénom et nom. Ce script déclenchable par l&#039;appel à un code court, paramétrable si on le souhaite sur une BLF. &lt;br /&gt;
===Paramétrage du statut de l&#039;extension vers &#039;&#039;&#039;mon mobile&#039;&#039;&#039;===&lt;br /&gt;
&lt;br /&gt;
[[Fichier:2026-04-03 11h09 54.png|cadre|néant]]&lt;br /&gt;
&lt;br /&gt;
===Déclaration du script===&lt;br /&gt;
[[Fichier:2026-04-02 17h11 35.png|vignette]]&lt;br /&gt;
Rendez-vous dans :&lt;br /&gt;
&lt;br /&gt;
 Admin / Intégrations / Scripts d&#039;appels / + Ajouter personnalisé&lt;br /&gt;
&lt;br /&gt;
#Donner un nom au traitement de l&#039;appel. Exemple : &#039;&#039;&#039;astreinte_weekend&#039;&#039;&#039;&lt;br /&gt;
#Créer un code de raccourci, ce qui permettra d&#039;exécuter le script simplement en appelant ce code, et in fine par une BLF. Exemple : &#039;&#039;&#039;*99&#039;&#039;&#039;&lt;br /&gt;
#OK&lt;br /&gt;
#Coller dans le champ script le script paramétré ( voir section suivante )&lt;br /&gt;
#Sauvegarder&lt;br /&gt;
#Un message doit indiquer &#039;&#039;&#039;Compilation réussie !&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Le script===&lt;br /&gt;
&lt;br /&gt;
L&#039;éxécution du script va modifier l&#039;extension &#039;&#039;&#039;targetExtNum &#039;&#039;&#039;, il va le basculer sur le statut &#039;&#039;&#039;profileName &#039;&#039;&#039;, modifier son mobile de contact &#039;&#039;&#039;mobileElu &#039;&#039;&#039;, son nom et prénom.&lt;br /&gt;
&lt;br /&gt;
Il faut donc seulement modifier les lignes surlignés dans le code ci-dessous :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;csharp&amp;quot; line highlight=&amp;quot;14-16,19-20&amp;quot;&amp;gt;&lt;br /&gt;
using System;&lt;br /&gt;
using System.Threading.Tasks;&lt;br /&gt;
using TCX.Configuration;&lt;br /&gt;
using CallFlow;&lt;br /&gt;
using System.Linq;&lt;br /&gt;
using System.Collections.Generic;&lt;br /&gt;
&lt;br /&gt;
namespace dummy&lt;br /&gt;
{&lt;br /&gt;
    public class SetDynamicAstreinte : ScriptBase&amp;lt;SetDynamicAstreinte&amp;gt;&lt;br /&gt;
    {&lt;br /&gt;
        public override Task&amp;lt;bool&amp;gt; StartAsync()&lt;br /&gt;
        {&lt;br /&gt;
            string targetExtNum = &amp;quot;100&amp;quot;; &lt;br /&gt;
            string mobileElu = &amp;quot;0601020304&amp;quot;;&lt;br /&gt;
            string profileName = &amp;quot;Away&amp;quot;; &lt;br /&gt;
            &lt;br /&gt;
            // Nommage de l&#039;astreinte&lt;br /&gt;
            string prenomElu = &amp;quot;ASTREINTE&amp;quot;; &lt;br /&gt;
            string nomElu = &amp;quot;ELU&amp;quot;; &lt;br /&gt;
&lt;br /&gt;
            try&lt;br /&gt;
            {&lt;br /&gt;
                IPhoneSystem ps = PhoneSystem.Root;&lt;br /&gt;
                Extension targetExt = ps.GetDNByNumber(targetExtNum) as Extension;&lt;br /&gt;
&lt;br /&gt;
                if (targetExt != null)&lt;br /&gt;
                {&lt;br /&gt;
                    // 1. Mise à jour du numéro de mobile&lt;br /&gt;
                    targetExt.SetProperty(&amp;quot;MOBILENUMBER&amp;quot;, mobileElu);&lt;br /&gt;
&lt;br /&gt;
                    // 2. MISE À JOUR DU NOM&lt;br /&gt;
                    targetExt.FirstName = prenomElu;&lt;br /&gt;
                    targetExt.LastName = nomElu;&lt;br /&gt;
&lt;br /&gt;
                    // 3. Changement du profil de statut&lt;br /&gt;
                    var profile = targetExt.FwdProfiles.FirstOrDefault(p =&amp;gt; p.Name.Equals(profileName, StringComparison.OrdinalIgnoreCase));&lt;br /&gt;
                    &lt;br /&gt;
                    if (profile != null)&lt;br /&gt;
                    {&lt;br /&gt;
                        targetExt.CurrentProfile = profile;&lt;br /&gt;
                    }&lt;br /&gt;
&lt;br /&gt;
                    // 4. Sauvegarde globale&lt;br /&gt;
                    targetExt.ResetCurrentProfileOverride();&lt;br /&gt;
                    targetExt.Save();&lt;br /&gt;
&lt;br /&gt;
                    return Task.FromResult(true);&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            catch (Exception)&lt;br /&gt;
            {&lt;br /&gt;
                // Erreur silencieuse&lt;br /&gt;
            }&lt;br /&gt;
            return Task.FromResult(false);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Table de correspondance des profileName====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Dans 3CX!! Dans le script&lt;br /&gt;
|-&lt;br /&gt;
| Disponible|| Available&lt;br /&gt;
|-&lt;br /&gt;
| Absent|| Away&lt;br /&gt;
|-&lt;br /&gt;
| Ne pas déranger|| Out of office&lt;br /&gt;
|-&lt;br /&gt;
| Custom 1|| Custom 1&lt;br /&gt;
|-&lt;br /&gt;
| Custom 2|| Custom 2&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===Configuration concrète===&lt;br /&gt;
&lt;br /&gt;
Il faut choisir un statut autre que &amp;quot;Disponible&amp;quot; qui sera activé pour l&#039;astreinte, &amp;quot;Away&amp;quot; pour cet exemple&lt;br /&gt;
&lt;br /&gt;
On a besoin de gérer deux astreintes. Le poste Accueil reçoit les appels en temps normal&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Texte de la légende&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;Marcel Patulacci&#039;&#039;&#039; || &#039;&#039;&#039;Jean-Michel Apeuprè&#039;&#039;&#039;|| &#039;&#039;&#039;Poste accueil &#039;&#039;&#039; hors période d&#039;astreinte&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;syntaxhighlight lang=&amp;quot;csharp&amp;quot; line highlight=&amp;quot;3-5,8-9&amp;quot;&amp;gt;&lt;br /&gt;
public override Task&amp;lt;bool&amp;gt; StartAsync()&lt;br /&gt;
        {&lt;br /&gt;
            string targetExtNum = &amp;quot;100&amp;quot;; &lt;br /&gt;
            string mobileElu = &amp;quot;0699999999&amp;quot;;&lt;br /&gt;
            string profileName = &amp;quot;Away&amp;quot;; &lt;br /&gt;
&lt;br /&gt;
            // Nommage de l&#039;astreinte&lt;br /&gt;
            string prenomElu = &amp;quot;Marcel&amp;quot;; &lt;br /&gt;
            string nomElu = &amp;quot;Patulacci&amp;quot;; &lt;br /&gt;
&lt;br /&gt;
            try&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt; || &amp;lt;syntaxhighlight lang=&amp;quot;csharp&amp;quot; line highlight=&amp;quot;3-5,8-9&amp;quot;&amp;gt;&lt;br /&gt;
public override Task&amp;lt;bool&amp;gt; StartAsync()&lt;br /&gt;
        {&lt;br /&gt;
            string targetExtNum = &amp;quot;100&amp;quot;; &lt;br /&gt;
            string mobileElu = &amp;quot;0688888888&amp;quot;;&lt;br /&gt;
            string profileName = &amp;quot;Away&amp;quot;; &lt;br /&gt;
&lt;br /&gt;
            // Nommage de l&#039;astreinte&lt;br /&gt;
            string prenomElu = &amp;quot;Jean-Michel&amp;quot;; &lt;br /&gt;
            string nomElu = &amp;quot;Apeuprè&amp;quot;; &lt;br /&gt;
&lt;br /&gt;
            try&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;|| &amp;lt;syntaxhighlight lang=&amp;quot;csharp&amp;quot; line highlight=&amp;quot;3-5,8-9&amp;quot;&amp;gt;&lt;br /&gt;
public override Task&amp;lt;bool&amp;gt; StartAsync()&lt;br /&gt;
        {&lt;br /&gt;
            string targetExtNum = &amp;quot;100&amp;quot;; &lt;br /&gt;
            string mobileElu = &amp;quot;&amp;quot;;&lt;br /&gt;
            string profileName = &amp;quot;Available&amp;quot;; &lt;br /&gt;
&lt;br /&gt;
            // Nommage de l&#039;astreinte&lt;br /&gt;
            string prenomElu = &amp;quot;Accueil&amp;quot;; &lt;br /&gt;
            string nomElu = &amp;quot;&amp;quot;; &lt;br /&gt;
&lt;br /&gt;
            try&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Une fois les 3 scripts produits, passer à l&#039;étape [[Astreinte#Déclaration_du_script|Déclaration du script]] qui va permettre d&#039;affecter un code court à chaque script.&lt;br /&gt;
Exemple : &lt;br /&gt;
* *90 pour hors période d&#039;astreinte&lt;br /&gt;
* *91 pour Jean-Michel&lt;br /&gt;
* *92 pour Marcel&lt;br /&gt;
&lt;br /&gt;
On peut communiquer les codes aux personnes habilitées à gérer le système d&#039;astreinte et aller jusqu&#039;à paramétrer des BLF pour faciliter la vie d&#039;une secrétaire par exemple.&lt;br /&gt;
&lt;br /&gt;
{{Valide|v20}}&lt;br /&gt;
[[Catégorie:3CX]]&lt;/div&gt;</summary>
		<author><name>Anthony</name></author>
	</entry>
	<entry>
		<id>https://indywiki.fr/index.php?title=Astreinte&amp;diff=22244</id>
		<title>Astreinte</title>
		<link rel="alternate" type="text/html" href="https://indywiki.fr/index.php?title=Astreinte&amp;diff=22244"/>
		<updated>2026-04-03T09:26:13Z</updated>

		<summary type="html">&lt;p&gt;Anthony : /* par le statut */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== par le statut ==&lt;br /&gt;
Dans les réglages de l&#039;extension qui accueille les appels :&lt;br /&gt;
[[Fichier:2026-04-02 16h03 02.png|vignette]]&lt;br /&gt;
#Réglages&lt;br /&gt;
#Transfert d&#039;appels&lt;br /&gt;
#Choisir le statut de l&#039;extension à activer pour enclencher le renvoi vers l&#039;astreinte. Dans l&#039;exemple &#039;&#039;&#039;Absent&#039;&#039;&#039;. Pas l&#039;état &#039;&#039;&#039;Disponible&#039;&#039;&#039; évidemment.&lt;br /&gt;
#Dans &amp;quot;Transférer les appels externes à&amp;quot;, choisir &#039;&#039;&#039;Numéro externe&#039;&#039;&#039;&lt;br /&gt;
#Saisir le numéro de l&#039;astreinte&lt;br /&gt;
#Cocher &#039;&#039;&#039;Rebond&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Limite / contrainte : &lt;br /&gt;
*si les astreintes tournent, avant chaque période d&#039;astreinte, il faut faire ce cheminement pour que le bon numéro de mobile soit paramétré&lt;br /&gt;
*4 profils d&#039;astreinte maximum&lt;br /&gt;
*Nécessite de manipuler l&#039;application WEB&lt;br /&gt;
&lt;br /&gt;
== Via script==&lt;br /&gt;
===Principe===&lt;br /&gt;
On paramètre le statut choisi pour l&#039;astreinte en renvoi vers &#039;&#039;&#039;mon mobile&#039;&#039;&#039;. Un script viendra modifier le statut de l&#039;extension cible ainsi que son numéro de contact mobile, prénom et nom. Ce script déclenchable par l&#039;appel à un code court, paramétrable si on le souhaite sur une BLF. &lt;br /&gt;
===Paramétrage du statut de l&#039;extension vers &#039;&#039;&#039;mon mobile&#039;&#039;&#039;===&lt;br /&gt;
&lt;br /&gt;
[[Fichier:2026-04-03 11h09 54.png|cadre|néant]]&lt;br /&gt;
&lt;br /&gt;
===Déclaration du script===&lt;br /&gt;
[[Fichier:2026-04-02 17h11 35.png|vignette]]&lt;br /&gt;
Rendez-vous dans :&lt;br /&gt;
&lt;br /&gt;
 Admin / Intégrations / Scripts d&#039;appels / + Ajouter personnalisé&lt;br /&gt;
&lt;br /&gt;
#Donner un nom au traitement de l&#039;appel. Exemple : &#039;&#039;&#039;astreinte_weekend&#039;&#039;&#039;&lt;br /&gt;
#Créer un code de raccourci, ce qui permettra d&#039;exécuter le script simplement en appelant ce code, et in fine par une BLF. Exemple : &#039;&#039;&#039;*99&#039;&#039;&#039;&lt;br /&gt;
#OK&lt;br /&gt;
#Coller dans le champ script le script paramétré ( voir section suivante )&lt;br /&gt;
#Sauvegarder&lt;br /&gt;
#Un message doit indiquer &#039;&#039;&#039;Compilation réussie !&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Le script===&lt;br /&gt;
&lt;br /&gt;
L&#039;éxécution du script va modifier l&#039;extension &#039;&#039;&#039;targetExtNum &#039;&#039;&#039;, il va le basculer sur le statut &#039;&#039;&#039;profileName &#039;&#039;&#039;, modifier son mobile de contact &#039;&#039;&#039;mobileElu &#039;&#039;&#039;, son nom et prénom.&lt;br /&gt;
&lt;br /&gt;
Il faut donc seulement modifier les lignes surlignés dans le code ci-dessous :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;csharp&amp;quot; line highlight=&amp;quot;14-16,19-20&amp;quot;&amp;gt;&lt;br /&gt;
using System;&lt;br /&gt;
using System.Threading.Tasks;&lt;br /&gt;
using TCX.Configuration;&lt;br /&gt;
using CallFlow;&lt;br /&gt;
using System.Linq;&lt;br /&gt;
using System.Collections.Generic;&lt;br /&gt;
&lt;br /&gt;
namespace dummy&lt;br /&gt;
{&lt;br /&gt;
    public class SetDynamicAstreinte : ScriptBase&amp;lt;SetDynamicAstreinte&amp;gt;&lt;br /&gt;
    {&lt;br /&gt;
        public override Task&amp;lt;bool&amp;gt; StartAsync()&lt;br /&gt;
        {&lt;br /&gt;
            string targetExtNum = &amp;quot;100&amp;quot;; &lt;br /&gt;
            string mobileElu = &amp;quot;0601020304&amp;quot;;&lt;br /&gt;
            string profileName = &amp;quot;Away&amp;quot;; &lt;br /&gt;
            &lt;br /&gt;
            // Nommage de l&#039;astreinte&lt;br /&gt;
            string prenomElu = &amp;quot;ASTREINTE&amp;quot;; &lt;br /&gt;
            string nomElu = &amp;quot;ELU&amp;quot;; &lt;br /&gt;
&lt;br /&gt;
            try&lt;br /&gt;
            {&lt;br /&gt;
                IPhoneSystem ps = PhoneSystem.Root;&lt;br /&gt;
                Extension targetExt = ps.GetDNByNumber(targetExtNum) as Extension;&lt;br /&gt;
&lt;br /&gt;
                if (targetExt != null)&lt;br /&gt;
                {&lt;br /&gt;
                    // 1. Mise à jour du numéro de mobile&lt;br /&gt;
                    targetExt.SetProperty(&amp;quot;MOBILENUMBER&amp;quot;, mobileElu);&lt;br /&gt;
&lt;br /&gt;
                    // 2. MISE À JOUR DU NOM&lt;br /&gt;
                    targetExt.FirstName = prenomElu;&lt;br /&gt;
                    targetExt.LastName = nomElu;&lt;br /&gt;
&lt;br /&gt;
                    // 3. Changement du profil de statut&lt;br /&gt;
                    var profile = targetExt.FwdProfiles.FirstOrDefault(p =&amp;gt; p.Name.Equals(profileName, StringComparison.OrdinalIgnoreCase));&lt;br /&gt;
                    &lt;br /&gt;
                    if (profile != null)&lt;br /&gt;
                    {&lt;br /&gt;
                        targetExt.CurrentProfile = profile;&lt;br /&gt;
                    }&lt;br /&gt;
&lt;br /&gt;
                    // 4. Sauvegarde globale&lt;br /&gt;
                    targetExt.ResetCurrentProfileOverride();&lt;br /&gt;
                    targetExt.Save();&lt;br /&gt;
&lt;br /&gt;
                    return Task.FromResult(true);&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            catch (Exception)&lt;br /&gt;
            {&lt;br /&gt;
                // Erreur silencieuse&lt;br /&gt;
            }&lt;br /&gt;
            return Task.FromResult(false);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Table de correspondance des profileName====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Dans 3CX!! Dans le script&lt;br /&gt;
|-&lt;br /&gt;
| Disponible|| Available&lt;br /&gt;
|-&lt;br /&gt;
| Absent|| Away&lt;br /&gt;
|-&lt;br /&gt;
| Ne pas déranger|| Out of office&lt;br /&gt;
|-&lt;br /&gt;
| Custom 1|| Custom 1&lt;br /&gt;
|-&lt;br /&gt;
| Custom 2|| Custom 2&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===Configuration concrète===&lt;br /&gt;
&lt;br /&gt;
Il faut choisir un statut autre que &amp;quot;Disponible&amp;quot; qui sera activé pour l&#039;astreinte, &amp;quot;Custom 2&amp;quot; pour cet exemple&lt;br /&gt;
&lt;br /&gt;
On a besoin de gérer deux astreintes. Le poste Accueil reçoit les appels en temps normal&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Texte de la légende&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;Marcel Patulacci&#039;&#039;&#039; || &#039;&#039;&#039;Jean-Michel Apeuprè&#039;&#039;&#039;|| &#039;&#039;&#039;Poste accueil &#039;&#039;&#039; hors période d&#039;astreinte&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;syntaxhighlight lang=&amp;quot;csharp&amp;quot; line highlight=&amp;quot;3-5,8-9&amp;quot;&amp;gt;&lt;br /&gt;
public override Task&amp;lt;bool&amp;gt; StartAsync()&lt;br /&gt;
        {&lt;br /&gt;
            string targetExtNum = &amp;quot;100&amp;quot;; &lt;br /&gt;
            string mobileElu = &amp;quot;0699999999&amp;quot;;&lt;br /&gt;
            string profileName = &amp;quot;Custom 2&amp;quot;; &lt;br /&gt;
&lt;br /&gt;
            // Nommage de l&#039;astreinte&lt;br /&gt;
            string prenomElu = &amp;quot;Marcel&amp;quot;; &lt;br /&gt;
            string nomElu = &amp;quot;Patulacci&amp;quot;; &lt;br /&gt;
&lt;br /&gt;
            try&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt; || &amp;lt;syntaxhighlight lang=&amp;quot;csharp&amp;quot; line highlight=&amp;quot;3-5,8-9&amp;quot;&amp;gt;&lt;br /&gt;
public override Task&amp;lt;bool&amp;gt; StartAsync()&lt;br /&gt;
        {&lt;br /&gt;
            string targetExtNum = &amp;quot;100&amp;quot;; &lt;br /&gt;
            string mobileElu = &amp;quot;0688888888&amp;quot;;&lt;br /&gt;
            string profileName = &amp;quot;Custom 2&amp;quot;; &lt;br /&gt;
&lt;br /&gt;
            // Nommage de l&#039;astreinte&lt;br /&gt;
            string prenomElu = &amp;quot;Jean-Michel&amp;quot;; &lt;br /&gt;
            string nomElu = &amp;quot;Apeuprè&amp;quot;; &lt;br /&gt;
&lt;br /&gt;
            try&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;|| &amp;lt;syntaxhighlight lang=&amp;quot;csharp&amp;quot; line highlight=&amp;quot;3-5,8-9&amp;quot;&amp;gt;&lt;br /&gt;
public override Task&amp;lt;bool&amp;gt; StartAsync()&lt;br /&gt;
        {&lt;br /&gt;
            string targetExtNum = &amp;quot;100&amp;quot;; &lt;br /&gt;
            string mobileElu = &amp;quot;&amp;quot;;&lt;br /&gt;
            string profileName = &amp;quot;Available&amp;quot;; &lt;br /&gt;
&lt;br /&gt;
            // Nommage de l&#039;astreinte&lt;br /&gt;
            string prenomElu = &amp;quot;Accueil&amp;quot;; &lt;br /&gt;
            string nomElu = &amp;quot;&amp;quot;; &lt;br /&gt;
&lt;br /&gt;
            try&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Une fois les 3 scripts produits, passer à l&#039;étape [[Astreinte#Déclaration_du_script|Déclaration du script]] qui va permettre d&#039;affecter un code court à chaque script.&lt;br /&gt;
Exemple : &lt;br /&gt;
* *90 pour hors période d&#039;astreinte&lt;br /&gt;
* *91 pour Jean-Michel&lt;br /&gt;
* *92 pour Marcel&lt;br /&gt;
&lt;br /&gt;
On peut communiquer les codes aux personnes habilitées à gérer le système d&#039;astreinte et aller jusqu&#039;à paramétrer des BLF pour faciliter la vie d&#039;une secrétaire par exemple.&lt;br /&gt;
&lt;br /&gt;
{{Valide|v20}}&lt;br /&gt;
[[Catégorie:3CX]]&lt;/div&gt;</summary>
		<author><name>Anthony</name></author>
	</entry>
	<entry>
		<id>https://indywiki.fr/index.php?title=Astreinte&amp;diff=22243</id>
		<title>Astreinte</title>
		<link rel="alternate" type="text/html" href="https://indywiki.fr/index.php?title=Astreinte&amp;diff=22243"/>
		<updated>2026-04-03T09:24:41Z</updated>

		<summary type="html">&lt;p&gt;Anthony : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== par le statut ==&lt;br /&gt;
&lt;br /&gt;
Dans les réglages de l&#039;extension qui accueille les appels :&lt;br /&gt;
&lt;br /&gt;
#Réglages&lt;br /&gt;
#Transfert d&#039;appels&lt;br /&gt;
#Choisir le statut de l&#039;extension à activer pour enclencher le renvoi vers l&#039;astreinte. Dans l&#039;exemple &#039;&#039;&#039;Absent&#039;&#039;&#039;. Pas l&#039;état &#039;&#039;&#039;Disponible&#039;&#039;&#039; évidemment.&lt;br /&gt;
#Dans &amp;quot;Transférer les appels externes à&amp;quot;, choisir &#039;&#039;&#039;Numéro externe&#039;&#039;&#039;&lt;br /&gt;
#Saisir le numéro de l&#039;astreinte&lt;br /&gt;
#Cocher &#039;&#039;&#039;Rebond&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:2026-04-02 16h03 02.png]]&lt;br /&gt;
&lt;br /&gt;
Limite / contrainte : &lt;br /&gt;
*si les astreintes tournent, avant chaque période d&#039;astreinte, il faut faire ce cheminement pour que le bon numéro de mobile soit paramétré&lt;br /&gt;
*4 profils d&#039;astreinte maximum&lt;br /&gt;
*Nécessite de manipuler l&#039;application WEB&lt;br /&gt;
&lt;br /&gt;
== Via script==&lt;br /&gt;
===Principe===&lt;br /&gt;
On paramètre le statut choisi pour l&#039;astreinte en renvoi vers &#039;&#039;&#039;mon mobile&#039;&#039;&#039;. Un script viendra modifier le statut de l&#039;extension cible ainsi que son numéro de contact mobile, prénom et nom. Ce script déclenchable par l&#039;appel à un code court, paramétrable si on le souhaite sur une BLF. &lt;br /&gt;
===Paramétrage du statut de l&#039;extension vers &#039;&#039;&#039;mon mobile&#039;&#039;&#039;===&lt;br /&gt;
&lt;br /&gt;
[[Fichier:2026-04-03 11h09 54.png|cadre|néant]]&lt;br /&gt;
&lt;br /&gt;
===Déclaration du script===&lt;br /&gt;
[[Fichier:2026-04-02 17h11 35.png|vignette]]&lt;br /&gt;
Rendez-vous dans :&lt;br /&gt;
&lt;br /&gt;
 Admin / Intégrations / Scripts d&#039;appels / + Ajouter personnalisé&lt;br /&gt;
&lt;br /&gt;
#Donner un nom au traitement de l&#039;appel. Exemple : &#039;&#039;&#039;astreinte_weekend&#039;&#039;&#039;&lt;br /&gt;
#Créer un code de raccourci, ce qui permettra d&#039;exécuter le script simplement en appelant ce code, et in fine par une BLF. Exemple : &#039;&#039;&#039;*99&#039;&#039;&#039;&lt;br /&gt;
#OK&lt;br /&gt;
#Coller dans le champ script le script paramétré ( voir section suivante )&lt;br /&gt;
#Sauvegarder&lt;br /&gt;
#Un message doit indiquer &#039;&#039;&#039;Compilation réussie !&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Le script===&lt;br /&gt;
&lt;br /&gt;
L&#039;éxécution du script va modifier l&#039;extension &#039;&#039;&#039;targetExtNum &#039;&#039;&#039;, il va le basculer sur le statut &#039;&#039;&#039;profileName &#039;&#039;&#039;, modifier son mobile de contact &#039;&#039;&#039;mobileElu &#039;&#039;&#039;, son nom et prénom.&lt;br /&gt;
&lt;br /&gt;
Il faut donc seulement modifier les lignes surlignés dans le code ci-dessous :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;csharp&amp;quot; line highlight=&amp;quot;14-16,19-20&amp;quot;&amp;gt;&lt;br /&gt;
using System;&lt;br /&gt;
using System.Threading.Tasks;&lt;br /&gt;
using TCX.Configuration;&lt;br /&gt;
using CallFlow;&lt;br /&gt;
using System.Linq;&lt;br /&gt;
using System.Collections.Generic;&lt;br /&gt;
&lt;br /&gt;
namespace dummy&lt;br /&gt;
{&lt;br /&gt;
    public class SetDynamicAstreinte : ScriptBase&amp;lt;SetDynamicAstreinte&amp;gt;&lt;br /&gt;
    {&lt;br /&gt;
        public override Task&amp;lt;bool&amp;gt; StartAsync()&lt;br /&gt;
        {&lt;br /&gt;
            string targetExtNum = &amp;quot;100&amp;quot;; &lt;br /&gt;
            string mobileElu = &amp;quot;0601020304&amp;quot;;&lt;br /&gt;
            string profileName = &amp;quot;Away&amp;quot;; &lt;br /&gt;
            &lt;br /&gt;
            // Nommage de l&#039;astreinte&lt;br /&gt;
            string prenomElu = &amp;quot;ASTREINTE&amp;quot;; &lt;br /&gt;
            string nomElu = &amp;quot;ELU&amp;quot;; &lt;br /&gt;
&lt;br /&gt;
            try&lt;br /&gt;
            {&lt;br /&gt;
                IPhoneSystem ps = PhoneSystem.Root;&lt;br /&gt;
                Extension targetExt = ps.GetDNByNumber(targetExtNum) as Extension;&lt;br /&gt;
&lt;br /&gt;
                if (targetExt != null)&lt;br /&gt;
                {&lt;br /&gt;
                    // 1. Mise à jour du numéro de mobile&lt;br /&gt;
                    targetExt.SetProperty(&amp;quot;MOBILENUMBER&amp;quot;, mobileElu);&lt;br /&gt;
&lt;br /&gt;
                    // 2. MISE À JOUR DU NOM&lt;br /&gt;
                    targetExt.FirstName = prenomElu;&lt;br /&gt;
                    targetExt.LastName = nomElu;&lt;br /&gt;
&lt;br /&gt;
                    // 3. Changement du profil de statut&lt;br /&gt;
                    var profile = targetExt.FwdProfiles.FirstOrDefault(p =&amp;gt; p.Name.Equals(profileName, StringComparison.OrdinalIgnoreCase));&lt;br /&gt;
                    &lt;br /&gt;
                    if (profile != null)&lt;br /&gt;
                    {&lt;br /&gt;
                        targetExt.CurrentProfile = profile;&lt;br /&gt;
                    }&lt;br /&gt;
&lt;br /&gt;
                    // 4. Sauvegarde globale&lt;br /&gt;
                    targetExt.ResetCurrentProfileOverride();&lt;br /&gt;
                    targetExt.Save();&lt;br /&gt;
&lt;br /&gt;
                    return Task.FromResult(true);&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            catch (Exception)&lt;br /&gt;
            {&lt;br /&gt;
                // Erreur silencieuse&lt;br /&gt;
            }&lt;br /&gt;
            return Task.FromResult(false);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Table de correspondance des profileName====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Dans 3CX!! Dans le script&lt;br /&gt;
|-&lt;br /&gt;
| Disponible|| Available&lt;br /&gt;
|-&lt;br /&gt;
| Absent|| Away&lt;br /&gt;
|-&lt;br /&gt;
| Ne pas déranger|| Out of office&lt;br /&gt;
|-&lt;br /&gt;
| Custom 1|| Custom 1&lt;br /&gt;
|-&lt;br /&gt;
| Custom 2|| Custom 2&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===Configuration concrète===&lt;br /&gt;
&lt;br /&gt;
Il faut choisir un statut autre que &amp;quot;Disponible&amp;quot; qui sera activé pour l&#039;astreinte, &amp;quot;Custom 2&amp;quot; pour cet exemple&lt;br /&gt;
&lt;br /&gt;
On a besoin de gérer deux astreintes. Le poste Accueil reçoit les appels en temps normal&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Texte de la légende&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;Marcel Patulacci&#039;&#039;&#039; || &#039;&#039;&#039;Jean-Michel Apeuprè&#039;&#039;&#039;|| &#039;&#039;&#039;Poste accueil &#039;&#039;&#039; hors période d&#039;astreinte&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;syntaxhighlight lang=&amp;quot;csharp&amp;quot; line highlight=&amp;quot;3-5,8-9&amp;quot;&amp;gt;&lt;br /&gt;
public override Task&amp;lt;bool&amp;gt; StartAsync()&lt;br /&gt;
        {&lt;br /&gt;
            string targetExtNum = &amp;quot;100&amp;quot;; &lt;br /&gt;
            string mobileElu = &amp;quot;0699999999&amp;quot;;&lt;br /&gt;
            string profileName = &amp;quot;Custom 2&amp;quot;; &lt;br /&gt;
&lt;br /&gt;
            // Nommage de l&#039;astreinte&lt;br /&gt;
            string prenomElu = &amp;quot;Marcel&amp;quot;; &lt;br /&gt;
            string nomElu = &amp;quot;Patulacci&amp;quot;; &lt;br /&gt;
&lt;br /&gt;
            try&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt; || &amp;lt;syntaxhighlight lang=&amp;quot;csharp&amp;quot; line highlight=&amp;quot;3-5,8-9&amp;quot;&amp;gt;&lt;br /&gt;
public override Task&amp;lt;bool&amp;gt; StartAsync()&lt;br /&gt;
        {&lt;br /&gt;
            string targetExtNum = &amp;quot;100&amp;quot;; &lt;br /&gt;
            string mobileElu = &amp;quot;0688888888&amp;quot;;&lt;br /&gt;
            string profileName = &amp;quot;Custom 2&amp;quot;; &lt;br /&gt;
&lt;br /&gt;
            // Nommage de l&#039;astreinte&lt;br /&gt;
            string prenomElu = &amp;quot;Jean-Michel&amp;quot;; &lt;br /&gt;
            string nomElu = &amp;quot;Apeuprè&amp;quot;; &lt;br /&gt;
&lt;br /&gt;
            try&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;|| &amp;lt;syntaxhighlight lang=&amp;quot;csharp&amp;quot; line highlight=&amp;quot;3-5,8-9&amp;quot;&amp;gt;&lt;br /&gt;
public override Task&amp;lt;bool&amp;gt; StartAsync()&lt;br /&gt;
        {&lt;br /&gt;
            string targetExtNum = &amp;quot;100&amp;quot;; &lt;br /&gt;
            string mobileElu = &amp;quot;&amp;quot;;&lt;br /&gt;
            string profileName = &amp;quot;Available&amp;quot;; &lt;br /&gt;
&lt;br /&gt;
            // Nommage de l&#039;astreinte&lt;br /&gt;
            string prenomElu = &amp;quot;Accueil&amp;quot;; &lt;br /&gt;
            string nomElu = &amp;quot;&amp;quot;; &lt;br /&gt;
&lt;br /&gt;
            try&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Une fois les 3 scripts produits, passer à l&#039;étape [[Astreinte#Déclaration_du_script|Déclaration du script]] qui va permettre d&#039;affecter un code court à chaque script.&lt;br /&gt;
Exemple : &lt;br /&gt;
* *90 pour hors période d&#039;astreinte&lt;br /&gt;
* *91 pour Jean-Michel&lt;br /&gt;
* *92 pour Marcel&lt;br /&gt;
&lt;br /&gt;
On peut communiquer les codes aux personnes habilitées à gérer le système d&#039;astreinte et aller jusqu&#039;à paramétrer des BLF pour faciliter la vie d&#039;une secrétaire par exemple.&lt;br /&gt;
&lt;br /&gt;
{{Valide|v20}}&lt;br /&gt;
[[Catégorie:3CX]]&lt;/div&gt;</summary>
		<author><name>Anthony</name></author>
	</entry>
	<entry>
		<id>https://indywiki.fr/index.php?title=Astreinte&amp;diff=22242</id>
		<title>Astreinte</title>
		<link rel="alternate" type="text/html" href="https://indywiki.fr/index.php?title=Astreinte&amp;diff=22242"/>
		<updated>2026-04-03T09:22:18Z</updated>

		<summary type="html">&lt;p&gt;Anthony : /* Configuration concrète */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== par le statut ==&lt;br /&gt;
&lt;br /&gt;
Dans les réglages de l&#039;extension qui accueille les appels :&lt;br /&gt;
&lt;br /&gt;
#Réglages&lt;br /&gt;
#Transfert d&#039;appels&lt;br /&gt;
#Choisir le statut de l&#039;extension à activer pour enclencher le renvoi vers l&#039;astreinte. Dans l&#039;exemple &#039;&#039;&#039;Absent&#039;&#039;&#039;. Pas l&#039;état &#039;&#039;&#039;Disponible&#039;&#039;&#039; évidemment.&lt;br /&gt;
#Dans &amp;quot;Transférer les appels externes à&amp;quot;, choisir &#039;&#039;&#039;Numéro externe&#039;&#039;&#039;&lt;br /&gt;
#Saisir le numéro de l&#039;astreinte&lt;br /&gt;
#Cocher &#039;&#039;&#039;Rebond&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:2026-04-02 16h03 02.png]]&lt;br /&gt;
&lt;br /&gt;
Limite / contrainte : &lt;br /&gt;
*si les astreintes tournent, avant chaque période d&#039;astreinte, il faut faire ce cheminement pour que le bon numéro de mobile soit paramétré&lt;br /&gt;
*4 profils d&#039;astreinte maximum&lt;br /&gt;
*Nécessite de manipuler l&#039;application WEB&lt;br /&gt;
&lt;br /&gt;
== Via script==&lt;br /&gt;
===Principe===&lt;br /&gt;
On paramètre le statut choisi pour l&#039;astreinte en renvoi vers &#039;&#039;&#039;mon mobile&#039;&#039;&#039;. Un script viendra modifier le statut de l&#039;extension cible ainsi que son numéro de contact mobile, prénom et nom. Ce script déclenchable par l&#039;appel à un code court, paramétrable si on le souhaite sur une BLF. &lt;br /&gt;
===Paramétrage du statut de l&#039;extension vers &#039;&#039;&#039;mon mobile&#039;&#039;&#039;===&lt;br /&gt;
&lt;br /&gt;
[[Fichier:2026-04-03 11h09 54.png|cadre|néant]]&lt;br /&gt;
&lt;br /&gt;
===Déclaration du script===&lt;br /&gt;
[[Fichier:2026-04-02 17h11 35.png|vignette]]&lt;br /&gt;
Rendez-vous dans :&lt;br /&gt;
&lt;br /&gt;
 Admin / Intégrations / Scripts d&#039;appels / + Ajouter personnalisé&lt;br /&gt;
&lt;br /&gt;
#Donner un nom au traitement de l&#039;appel. Exemple : &#039;&#039;&#039;astreinte_weekend&#039;&#039;&#039;&lt;br /&gt;
#Créer un code de raccourci, ce qui permettra d&#039;exécuter le script simplement en appelant ce code, et in fine par une BLF. Exemple : &#039;&#039;&#039;*99&#039;&#039;&#039;&lt;br /&gt;
#OK&lt;br /&gt;
#Coller dans le champ script le script paramétré ( voir section suivante )&lt;br /&gt;
#Sauvegarder&lt;br /&gt;
#Un message doit indiquer &#039;&#039;&#039;Compilation réussie !&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Le script===&lt;br /&gt;
&lt;br /&gt;
L&#039;éxécution du script va modifier l&#039;extension &#039;&#039;&#039;targetExtNum &#039;&#039;&#039;, il va le basculer sur le statut &#039;&#039;&#039;profileName &#039;&#039;&#039;, modifier son mobile de contact &#039;&#039;&#039;mobileElu &#039;&#039;&#039;, son nom et prénom.&lt;br /&gt;
&lt;br /&gt;
Il faut donc seulement modifier les lignes surlignés dans le code ci-dessous :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;csharp&amp;quot; line highlight=&amp;quot;14-16,19-20&amp;quot;&amp;gt;&lt;br /&gt;
using System;&lt;br /&gt;
using System.Threading.Tasks;&lt;br /&gt;
using TCX.Configuration;&lt;br /&gt;
using CallFlow;&lt;br /&gt;
using System.Linq;&lt;br /&gt;
using System.Collections.Generic;&lt;br /&gt;
&lt;br /&gt;
namespace dummy&lt;br /&gt;
{&lt;br /&gt;
    public class SetDynamicAstreinte : ScriptBase&amp;lt;SetDynamicAstreinte&amp;gt;&lt;br /&gt;
    {&lt;br /&gt;
        public override Task&amp;lt;bool&amp;gt; StartAsync()&lt;br /&gt;
        {&lt;br /&gt;
            string targetExtNum = &amp;quot;100&amp;quot;; &lt;br /&gt;
            string mobileElu = &amp;quot;0601020304&amp;quot;;&lt;br /&gt;
            string profileName = &amp;quot;Away&amp;quot;; &lt;br /&gt;
            &lt;br /&gt;
            // Nommage de l&#039;astreinte&lt;br /&gt;
            string prenomElu = &amp;quot;ASTREINTE&amp;quot;; &lt;br /&gt;
            string nomElu = &amp;quot;ELU&amp;quot;; &lt;br /&gt;
&lt;br /&gt;
            try&lt;br /&gt;
            {&lt;br /&gt;
                IPhoneSystem ps = PhoneSystem.Root;&lt;br /&gt;
                Extension targetExt = ps.GetDNByNumber(targetExtNum) as Extension;&lt;br /&gt;
&lt;br /&gt;
                if (targetExt != null)&lt;br /&gt;
                {&lt;br /&gt;
                    // 1. Mise à jour du numéro de mobile&lt;br /&gt;
                    targetExt.SetProperty(&amp;quot;MOBILENUMBER&amp;quot;, mobileElu);&lt;br /&gt;
&lt;br /&gt;
                    // 2. MISE À JOUR DU NOM&lt;br /&gt;
                    targetExt.FirstName = prenomElu;&lt;br /&gt;
                    targetExt.LastName = nomElu;&lt;br /&gt;
&lt;br /&gt;
                    // 3. Changement du profil de statut&lt;br /&gt;
                    var profile = targetExt.FwdProfiles.FirstOrDefault(p =&amp;gt; p.Name.Equals(profileName, StringComparison.OrdinalIgnoreCase));&lt;br /&gt;
                    &lt;br /&gt;
                    if (profile != null)&lt;br /&gt;
                    {&lt;br /&gt;
                        targetExt.CurrentProfile = profile;&lt;br /&gt;
                    }&lt;br /&gt;
&lt;br /&gt;
                    // 4. Sauvegarde globale&lt;br /&gt;
                    targetExt.ResetCurrentProfileOverride();&lt;br /&gt;
                    targetExt.Save();&lt;br /&gt;
&lt;br /&gt;
                    return Task.FromResult(true);&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            catch (Exception)&lt;br /&gt;
            {&lt;br /&gt;
                // Erreur silencieuse&lt;br /&gt;
            }&lt;br /&gt;
            return Task.FromResult(false);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Table de correspondance des profileName====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Dans 3CX!! Dans le script&lt;br /&gt;
|-&lt;br /&gt;
| Disponible|| Available&lt;br /&gt;
|-&lt;br /&gt;
| Absent|| Away&lt;br /&gt;
|-&lt;br /&gt;
| Ne pas déranger|| Out of office&lt;br /&gt;
|-&lt;br /&gt;
| Custom 1|| Custom 1&lt;br /&gt;
|-&lt;br /&gt;
| Custom 2|| Custom 2&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===Configuration concrète===&lt;br /&gt;
&lt;br /&gt;
Il faut choisir un statut autre que &amp;quot;Disponible&amp;quot; qui sera activé pour l&#039;astreinte, &amp;quot;Custom 2&amp;quot; pour cet exemple&lt;br /&gt;
&lt;br /&gt;
On a besoin de gérer deux astreintes. Le poste Accueil reçoit les appels en temps normal&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Texte de la légende&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;Marcel Patulacci&#039;&#039;&#039; || &#039;&#039;&#039;Jean-Michel Apeuprè&#039;&#039;&#039;|| &#039;&#039;&#039;Poste accueil &#039;&#039;&#039; hors période d&#039;astreinte&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;syntaxhighlight lang=&amp;quot;csharp&amp;quot; line highlight=&amp;quot;3-5,8-9&amp;quot;&amp;gt;&lt;br /&gt;
public override Task&amp;lt;bool&amp;gt; StartAsync()&lt;br /&gt;
        {&lt;br /&gt;
            string targetExtNum = &amp;quot;100&amp;quot;; &lt;br /&gt;
            string mobileElu = &amp;quot;0699999999&amp;quot;;&lt;br /&gt;
            string profileName = &amp;quot;Custom 2&amp;quot;; &lt;br /&gt;
&lt;br /&gt;
            // Nommage de l&#039;astreinte&lt;br /&gt;
            string prenomElu = &amp;quot;Marcel&amp;quot;; &lt;br /&gt;
            string nomElu = &amp;quot;Patulacci&amp;quot;; &lt;br /&gt;
&lt;br /&gt;
            try&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt; || &amp;lt;syntaxhighlight lang=&amp;quot;csharp&amp;quot; line highlight=&amp;quot;3-5,8-9&amp;quot;&amp;gt;&lt;br /&gt;
public override Task&amp;lt;bool&amp;gt; StartAsync()&lt;br /&gt;
        {&lt;br /&gt;
            string targetExtNum = &amp;quot;100&amp;quot;; &lt;br /&gt;
            string mobileElu = &amp;quot;0688888888&amp;quot;;&lt;br /&gt;
            string profileName = &amp;quot;Custom 2&amp;quot;; &lt;br /&gt;
&lt;br /&gt;
            // Nommage de l&#039;astreinte&lt;br /&gt;
            string prenomElu = &amp;quot;Jean-Michel&amp;quot;; &lt;br /&gt;
            string nomElu = &amp;quot;Apeuprè&amp;quot;; &lt;br /&gt;
&lt;br /&gt;
            try&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;|| &amp;lt;syntaxhighlight lang=&amp;quot;csharp&amp;quot; line highlight=&amp;quot;3-5,8-9&amp;quot;&amp;gt;&lt;br /&gt;
public override Task&amp;lt;bool&amp;gt; StartAsync()&lt;br /&gt;
        {&lt;br /&gt;
            string targetExtNum = &amp;quot;100&amp;quot;; &lt;br /&gt;
            string mobileElu = &amp;quot;&amp;quot;;&lt;br /&gt;
            string profileName = &amp;quot;Available&amp;quot;; &lt;br /&gt;
&lt;br /&gt;
            // Nommage de l&#039;astreinte&lt;br /&gt;
            string prenomElu = &amp;quot;Accueil&amp;quot;; &lt;br /&gt;
            string nomElu = &amp;quot;&amp;quot;; &lt;br /&gt;
&lt;br /&gt;
            try&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Une fois les 3 scripts produits, passer à l&#039;étape [[Astreinte#Déclaration_du_script|Déclaration du script]] qui va permettre d&#039;affecter un code court à chaque script.&lt;br /&gt;
Exemple : &lt;br /&gt;
* *90 pour hors période d&#039;astreinte&lt;br /&gt;
* *91 pour Jean-Michel&lt;br /&gt;
* *92 pour Marcel&lt;br /&gt;
&lt;br /&gt;
On peut communiquer les codes aux personnes habilitées à gérer le système d&#039;astreinte et aller jusqu&#039;à paramétrer des BLF pour faciliter la vie d&#039;une secrétaire par exemple.&lt;br /&gt;
&lt;br /&gt;
[[Catégorie:3CX]]&lt;/div&gt;</summary>
		<author><name>Anthony</name></author>
	</entry>
	<entry>
		<id>https://indywiki.fr/index.php?title=Astreinte&amp;diff=22241</id>
		<title>Astreinte</title>
		<link rel="alternate" type="text/html" href="https://indywiki.fr/index.php?title=Astreinte&amp;diff=22241"/>
		<updated>2026-04-03T09:12:25Z</updated>

		<summary type="html">&lt;p&gt;Anthony : /* Paramétrage du statut vers mon mobile */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== par le statut ==&lt;br /&gt;
&lt;br /&gt;
Dans les réglages de l&#039;extension qui accueille les appels :&lt;br /&gt;
&lt;br /&gt;
#Réglages&lt;br /&gt;
#Transfert d&#039;appels&lt;br /&gt;
#Choisir le statut de l&#039;extension à activer pour enclencher le renvoi vers l&#039;astreinte. Dans l&#039;exemple &#039;&#039;&#039;Absent&#039;&#039;&#039;. Pas l&#039;état &#039;&#039;&#039;Disponible&#039;&#039;&#039; évidemment.&lt;br /&gt;
#Dans &amp;quot;Transférer les appels externes à&amp;quot;, choisir &#039;&#039;&#039;Numéro externe&#039;&#039;&#039;&lt;br /&gt;
#Saisir le numéro de l&#039;astreinte&lt;br /&gt;
#Cocher &#039;&#039;&#039;Rebond&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:2026-04-02 16h03 02.png]]&lt;br /&gt;
&lt;br /&gt;
Limite / contrainte : &lt;br /&gt;
*si les astreintes tournent, avant chaque période d&#039;astreinte, il faut faire ce cheminement pour que le bon numéro de mobile soit paramétré&lt;br /&gt;
*4 profils d&#039;astreinte maximum&lt;br /&gt;
*Nécessite de manipuler l&#039;application WEB&lt;br /&gt;
&lt;br /&gt;
== Via script==&lt;br /&gt;
===Principe===&lt;br /&gt;
On paramètre le statut choisi pour l&#039;astreinte en renvoi vers &#039;&#039;&#039;mon mobile&#039;&#039;&#039;. Un script viendra modifier le statut de l&#039;extension cible ainsi que son numéro de contact mobile, prénom et nom. Ce script déclenchable par l&#039;appel à un code court, paramétrable si on le souhaite sur une BLF. &lt;br /&gt;
===Paramétrage du statut de l&#039;extension vers &#039;&#039;&#039;mon mobile&#039;&#039;&#039;===&lt;br /&gt;
&lt;br /&gt;
[[Fichier:2026-04-03 11h09 54.png|cadre|néant]]&lt;br /&gt;
&lt;br /&gt;
===Déclaration du script===&lt;br /&gt;
[[Fichier:2026-04-02 17h11 35.png|vignette]]&lt;br /&gt;
Rendez-vous dans :&lt;br /&gt;
&lt;br /&gt;
 Admin / Intégrations / Scripts d&#039;appels / + Ajouter personnalisé&lt;br /&gt;
&lt;br /&gt;
#Donner un nom au traitement de l&#039;appel. Exemple : &#039;&#039;&#039;astreinte_weekend&#039;&#039;&#039;&lt;br /&gt;
#Créer un code de raccourci, ce qui permettra d&#039;exécuter le script simplement en appelant ce code, et in fine par une BLF. Exemple : &#039;&#039;&#039;*99&#039;&#039;&#039;&lt;br /&gt;
#OK&lt;br /&gt;
#Coller dans le champ script le script paramétré ( voir section suivante )&lt;br /&gt;
#Sauvegarder&lt;br /&gt;
#Un message doit indiquer &#039;&#039;&#039;Compilation réussie !&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Le script===&lt;br /&gt;
&lt;br /&gt;
L&#039;éxécution du script va modifier l&#039;extension &#039;&#039;&#039;targetExtNum &#039;&#039;&#039;, il va le basculer sur le statut &#039;&#039;&#039;profileName &#039;&#039;&#039;, modifier son mobile de contact &#039;&#039;&#039;mobileElu &#039;&#039;&#039;, son nom et prénom.&lt;br /&gt;
&lt;br /&gt;
Il faut donc seulement modifier les lignes surlignés dans le code ci-dessous :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;csharp&amp;quot; line highlight=&amp;quot;14-16,19-20&amp;quot;&amp;gt;&lt;br /&gt;
using System;&lt;br /&gt;
using System.Threading.Tasks;&lt;br /&gt;
using TCX.Configuration;&lt;br /&gt;
using CallFlow;&lt;br /&gt;
using System.Linq;&lt;br /&gt;
using System.Collections.Generic;&lt;br /&gt;
&lt;br /&gt;
namespace dummy&lt;br /&gt;
{&lt;br /&gt;
    public class SetDynamicAstreinte : ScriptBase&amp;lt;SetDynamicAstreinte&amp;gt;&lt;br /&gt;
    {&lt;br /&gt;
        public override Task&amp;lt;bool&amp;gt; StartAsync()&lt;br /&gt;
        {&lt;br /&gt;
            string targetExtNum = &amp;quot;100&amp;quot;; &lt;br /&gt;
            string mobileElu = &amp;quot;0601020304&amp;quot;;&lt;br /&gt;
            string profileName = &amp;quot;Away&amp;quot;; &lt;br /&gt;
            &lt;br /&gt;
            // Nommage de l&#039;astreinte&lt;br /&gt;
            string prenomElu = &amp;quot;ASTREINTE&amp;quot;; &lt;br /&gt;
            string nomElu = &amp;quot;ELU&amp;quot;; &lt;br /&gt;
&lt;br /&gt;
            try&lt;br /&gt;
            {&lt;br /&gt;
                IPhoneSystem ps = PhoneSystem.Root;&lt;br /&gt;
                Extension targetExt = ps.GetDNByNumber(targetExtNum) as Extension;&lt;br /&gt;
&lt;br /&gt;
                if (targetExt != null)&lt;br /&gt;
                {&lt;br /&gt;
                    // 1. Mise à jour du numéro de mobile&lt;br /&gt;
                    targetExt.SetProperty(&amp;quot;MOBILENUMBER&amp;quot;, mobileElu);&lt;br /&gt;
&lt;br /&gt;
                    // 2. MISE À JOUR DU NOM&lt;br /&gt;
                    targetExt.FirstName = prenomElu;&lt;br /&gt;
                    targetExt.LastName = nomElu;&lt;br /&gt;
&lt;br /&gt;
                    // 3. Changement du profil de statut&lt;br /&gt;
                    var profile = targetExt.FwdProfiles.FirstOrDefault(p =&amp;gt; p.Name.Equals(profileName, StringComparison.OrdinalIgnoreCase));&lt;br /&gt;
                    &lt;br /&gt;
                    if (profile != null)&lt;br /&gt;
                    {&lt;br /&gt;
                        targetExt.CurrentProfile = profile;&lt;br /&gt;
                    }&lt;br /&gt;
&lt;br /&gt;
                    // 4. Sauvegarde globale&lt;br /&gt;
                    targetExt.ResetCurrentProfileOverride();&lt;br /&gt;
                    targetExt.Save();&lt;br /&gt;
&lt;br /&gt;
                    return Task.FromResult(true);&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            catch (Exception)&lt;br /&gt;
            {&lt;br /&gt;
                // Erreur silencieuse&lt;br /&gt;
            }&lt;br /&gt;
            return Task.FromResult(false);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Table de correspondance des profileName====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Dans 3CX!! Dans le script&lt;br /&gt;
|-&lt;br /&gt;
| Disponible|| Available&lt;br /&gt;
|-&lt;br /&gt;
| Absent|| Away&lt;br /&gt;
|-&lt;br /&gt;
| Ne pas déranger|| Out of office&lt;br /&gt;
|-&lt;br /&gt;
| Custom 1|| Custom 1&lt;br /&gt;
|-&lt;br /&gt;
| Custom 2|| Custom 2&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===Configuration concrète===&lt;br /&gt;
&lt;br /&gt;
Il faut choisir un statut autre que &amp;quot;Disponible&amp;quot; qui sera activé pour l&#039;astreinte, &amp;quot;Custom 2&amp;quot; pour cet exemple&lt;br /&gt;
&lt;br /&gt;
On a besoin de gérer deux astreintes. Le poste Accueil reçoit les appels en temps normal&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Texte de la légende&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;Marcel Patulacci&#039;&#039;&#039; || &#039;&#039;&#039;Jean-Michel Apeuprè&#039;&#039;&#039;|| &#039;&#039;&#039;Poste accueil &#039;&#039;&#039; hors période d&#039;astreinte&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;syntaxhighlight lang=&amp;quot;csharp&amp;quot; line highlight=&amp;quot;3-5,8-9&amp;quot;&amp;gt;&lt;br /&gt;
public override Task&amp;lt;bool&amp;gt; StartAsync()&lt;br /&gt;
        {&lt;br /&gt;
            string targetExtNum = &amp;quot;100&amp;quot;; &lt;br /&gt;
            string mobileElu = &amp;quot;0699999999&amp;quot;;&lt;br /&gt;
            string profileName = &amp;quot;Custom 2&amp;quot;; &lt;br /&gt;
&lt;br /&gt;
            // Nommage de l&#039;astreinte&lt;br /&gt;
            string prenomElu = &amp;quot;Marcel&amp;quot;; &lt;br /&gt;
            string nomElu = &amp;quot;Patulacci&amp;quot;; &lt;br /&gt;
&lt;br /&gt;
            try&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt; || &amp;lt;syntaxhighlight lang=&amp;quot;csharp&amp;quot; line highlight=&amp;quot;3-5,8-9&amp;quot;&amp;gt;&lt;br /&gt;
public override Task&amp;lt;bool&amp;gt; StartAsync()&lt;br /&gt;
        {&lt;br /&gt;
            string targetExtNum = &amp;quot;100&amp;quot;; &lt;br /&gt;
            string mobileElu = &amp;quot;0688888888&amp;quot;;&lt;br /&gt;
            string profileName = &amp;quot;Custom 2&amp;quot;; &lt;br /&gt;
&lt;br /&gt;
            // Nommage de l&#039;astreinte&lt;br /&gt;
            string prenomElu = &amp;quot;Jean-Michel&amp;quot;; &lt;br /&gt;
            string nomElu = &amp;quot;Apeuprè&amp;quot;; &lt;br /&gt;
&lt;br /&gt;
            try&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;|| &amp;lt;syntaxhighlight lang=&amp;quot;csharp&amp;quot; line highlight=&amp;quot;3-5,8-9&amp;quot;&amp;gt;&lt;br /&gt;
public override Task&amp;lt;bool&amp;gt; StartAsync()&lt;br /&gt;
        {&lt;br /&gt;
            string targetExtNum = &amp;quot;100&amp;quot;; &lt;br /&gt;
            string mobileElu = &amp;quot;&amp;quot;;&lt;br /&gt;
            string profileName = &amp;quot;Available&amp;quot;; &lt;br /&gt;
&lt;br /&gt;
            // Nommage de l&#039;astreinte&lt;br /&gt;
            string prenomElu = &amp;quot;Accueil&amp;quot;; &lt;br /&gt;
            string nomElu = &amp;quot;&amp;quot;; &lt;br /&gt;
&lt;br /&gt;
            try&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
[[Catégorie:3CX]]&lt;/div&gt;</summary>
		<author><name>Anthony</name></author>
	</entry>
	<entry>
		<id>https://indywiki.fr/index.php?title=Astreinte&amp;diff=22240</id>
		<title>Astreinte</title>
		<link rel="alternate" type="text/html" href="https://indywiki.fr/index.php?title=Astreinte&amp;diff=22240"/>
		<updated>2026-04-03T09:11:47Z</updated>

		<summary type="html">&lt;p&gt;Anthony : /* Paramétrage du statut vers mon mobile */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== par le statut ==&lt;br /&gt;
&lt;br /&gt;
Dans les réglages de l&#039;extension qui accueille les appels :&lt;br /&gt;
&lt;br /&gt;
#Réglages&lt;br /&gt;
#Transfert d&#039;appels&lt;br /&gt;
#Choisir le statut de l&#039;extension à activer pour enclencher le renvoi vers l&#039;astreinte. Dans l&#039;exemple &#039;&#039;&#039;Absent&#039;&#039;&#039;. Pas l&#039;état &#039;&#039;&#039;Disponible&#039;&#039;&#039; évidemment.&lt;br /&gt;
#Dans &amp;quot;Transférer les appels externes à&amp;quot;, choisir &#039;&#039;&#039;Numéro externe&#039;&#039;&#039;&lt;br /&gt;
#Saisir le numéro de l&#039;astreinte&lt;br /&gt;
#Cocher &#039;&#039;&#039;Rebond&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:2026-04-02 16h03 02.png]]&lt;br /&gt;
&lt;br /&gt;
Limite / contrainte : &lt;br /&gt;
*si les astreintes tournent, avant chaque période d&#039;astreinte, il faut faire ce cheminement pour que le bon numéro de mobile soit paramétré&lt;br /&gt;
*4 profils d&#039;astreinte maximum&lt;br /&gt;
*Nécessite de manipuler l&#039;application WEB&lt;br /&gt;
&lt;br /&gt;
== Via script==&lt;br /&gt;
===Principe===&lt;br /&gt;
On paramètre le statut choisi pour l&#039;astreinte en renvoi vers &#039;&#039;&#039;mon mobile&#039;&#039;&#039;. Un script viendra modifier le statut de l&#039;extension cible ainsi que son numéro de contact mobile, prénom et nom. Ce script déclenchable par l&#039;appel à un code court, paramétrable si on le souhaite sur une BLF. &lt;br /&gt;
===Paramétrage du statut vers &#039;&#039;&#039;mon mobile&#039;&#039;&#039;===&lt;br /&gt;
&lt;br /&gt;
[[Fichier:2026-04-03 11h09 54.png|cadre|néant]]&lt;br /&gt;
&lt;br /&gt;
===Déclaration du script===&lt;br /&gt;
[[Fichier:2026-04-02 17h11 35.png|vignette]]&lt;br /&gt;
Rendez-vous dans :&lt;br /&gt;
&lt;br /&gt;
 Admin / Intégrations / Scripts d&#039;appels / + Ajouter personnalisé&lt;br /&gt;
&lt;br /&gt;
#Donner un nom au traitement de l&#039;appel. Exemple : &#039;&#039;&#039;astreinte_weekend&#039;&#039;&#039;&lt;br /&gt;
#Créer un code de raccourci, ce qui permettra d&#039;exécuter le script simplement en appelant ce code, et in fine par une BLF. Exemple : &#039;&#039;&#039;*99&#039;&#039;&#039;&lt;br /&gt;
#OK&lt;br /&gt;
#Coller dans le champ script le script paramétré ( voir section suivante )&lt;br /&gt;
#Sauvegarder&lt;br /&gt;
#Un message doit indiquer &#039;&#039;&#039;Compilation réussie !&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Le script===&lt;br /&gt;
&lt;br /&gt;
L&#039;éxécution du script va modifier l&#039;extension &#039;&#039;&#039;targetExtNum &#039;&#039;&#039;, il va le basculer sur le statut &#039;&#039;&#039;profileName &#039;&#039;&#039;, modifier son mobile de contact &#039;&#039;&#039;mobileElu &#039;&#039;&#039;, son nom et prénom.&lt;br /&gt;
&lt;br /&gt;
Il faut donc seulement modifier les lignes surlignés dans le code ci-dessous :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;csharp&amp;quot; line highlight=&amp;quot;14-16,19-20&amp;quot;&amp;gt;&lt;br /&gt;
using System;&lt;br /&gt;
using System.Threading.Tasks;&lt;br /&gt;
using TCX.Configuration;&lt;br /&gt;
using CallFlow;&lt;br /&gt;
using System.Linq;&lt;br /&gt;
using System.Collections.Generic;&lt;br /&gt;
&lt;br /&gt;
namespace dummy&lt;br /&gt;
{&lt;br /&gt;
    public class SetDynamicAstreinte : ScriptBase&amp;lt;SetDynamicAstreinte&amp;gt;&lt;br /&gt;
    {&lt;br /&gt;
        public override Task&amp;lt;bool&amp;gt; StartAsync()&lt;br /&gt;
        {&lt;br /&gt;
            string targetExtNum = &amp;quot;100&amp;quot;; &lt;br /&gt;
            string mobileElu = &amp;quot;0601020304&amp;quot;;&lt;br /&gt;
            string profileName = &amp;quot;Away&amp;quot;; &lt;br /&gt;
            &lt;br /&gt;
            // Nommage de l&#039;astreinte&lt;br /&gt;
            string prenomElu = &amp;quot;ASTREINTE&amp;quot;; &lt;br /&gt;
            string nomElu = &amp;quot;ELU&amp;quot;; &lt;br /&gt;
&lt;br /&gt;
            try&lt;br /&gt;
            {&lt;br /&gt;
                IPhoneSystem ps = PhoneSystem.Root;&lt;br /&gt;
                Extension targetExt = ps.GetDNByNumber(targetExtNum) as Extension;&lt;br /&gt;
&lt;br /&gt;
                if (targetExt != null)&lt;br /&gt;
                {&lt;br /&gt;
                    // 1. Mise à jour du numéro de mobile&lt;br /&gt;
                    targetExt.SetProperty(&amp;quot;MOBILENUMBER&amp;quot;, mobileElu);&lt;br /&gt;
&lt;br /&gt;
                    // 2. MISE À JOUR DU NOM&lt;br /&gt;
                    targetExt.FirstName = prenomElu;&lt;br /&gt;
                    targetExt.LastName = nomElu;&lt;br /&gt;
&lt;br /&gt;
                    // 3. Changement du profil de statut&lt;br /&gt;
                    var profile = targetExt.FwdProfiles.FirstOrDefault(p =&amp;gt; p.Name.Equals(profileName, StringComparison.OrdinalIgnoreCase));&lt;br /&gt;
                    &lt;br /&gt;
                    if (profile != null)&lt;br /&gt;
                    {&lt;br /&gt;
                        targetExt.CurrentProfile = profile;&lt;br /&gt;
                    }&lt;br /&gt;
&lt;br /&gt;
                    // 4. Sauvegarde globale&lt;br /&gt;
                    targetExt.ResetCurrentProfileOverride();&lt;br /&gt;
                    targetExt.Save();&lt;br /&gt;
&lt;br /&gt;
                    return Task.FromResult(true);&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            catch (Exception)&lt;br /&gt;
            {&lt;br /&gt;
                // Erreur silencieuse&lt;br /&gt;
            }&lt;br /&gt;
            return Task.FromResult(false);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Table de correspondance des profileName====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Dans 3CX!! Dans le script&lt;br /&gt;
|-&lt;br /&gt;
| Disponible|| Available&lt;br /&gt;
|-&lt;br /&gt;
| Absent|| Away&lt;br /&gt;
|-&lt;br /&gt;
| Ne pas déranger|| Out of office&lt;br /&gt;
|-&lt;br /&gt;
| Custom 1|| Custom 1&lt;br /&gt;
|-&lt;br /&gt;
| Custom 2|| Custom 2&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===Configuration concrète===&lt;br /&gt;
&lt;br /&gt;
Il faut choisir un statut autre que &amp;quot;Disponible&amp;quot; qui sera activé pour l&#039;astreinte, &amp;quot;Custom 2&amp;quot; pour cet exemple&lt;br /&gt;
&lt;br /&gt;
On a besoin de gérer deux astreintes. Le poste Accueil reçoit les appels en temps normal&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Texte de la légende&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;Marcel Patulacci&#039;&#039;&#039; || &#039;&#039;&#039;Jean-Michel Apeuprè&#039;&#039;&#039;|| &#039;&#039;&#039;Poste accueil &#039;&#039;&#039; hors période d&#039;astreinte&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;syntaxhighlight lang=&amp;quot;csharp&amp;quot; line highlight=&amp;quot;3-5,8-9&amp;quot;&amp;gt;&lt;br /&gt;
public override Task&amp;lt;bool&amp;gt; StartAsync()&lt;br /&gt;
        {&lt;br /&gt;
            string targetExtNum = &amp;quot;100&amp;quot;; &lt;br /&gt;
            string mobileElu = &amp;quot;0699999999&amp;quot;;&lt;br /&gt;
            string profileName = &amp;quot;Custom 2&amp;quot;; &lt;br /&gt;
&lt;br /&gt;
            // Nommage de l&#039;astreinte&lt;br /&gt;
            string prenomElu = &amp;quot;Marcel&amp;quot;; &lt;br /&gt;
            string nomElu = &amp;quot;Patulacci&amp;quot;; &lt;br /&gt;
&lt;br /&gt;
            try&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt; || &amp;lt;syntaxhighlight lang=&amp;quot;csharp&amp;quot; line highlight=&amp;quot;3-5,8-9&amp;quot;&amp;gt;&lt;br /&gt;
public override Task&amp;lt;bool&amp;gt; StartAsync()&lt;br /&gt;
        {&lt;br /&gt;
            string targetExtNum = &amp;quot;100&amp;quot;; &lt;br /&gt;
            string mobileElu = &amp;quot;0688888888&amp;quot;;&lt;br /&gt;
            string profileName = &amp;quot;Custom 2&amp;quot;; &lt;br /&gt;
&lt;br /&gt;
            // Nommage de l&#039;astreinte&lt;br /&gt;
            string prenomElu = &amp;quot;Jean-Michel&amp;quot;; &lt;br /&gt;
            string nomElu = &amp;quot;Apeuprè&amp;quot;; &lt;br /&gt;
&lt;br /&gt;
            try&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;|| &amp;lt;syntaxhighlight lang=&amp;quot;csharp&amp;quot; line highlight=&amp;quot;3-5,8-9&amp;quot;&amp;gt;&lt;br /&gt;
public override Task&amp;lt;bool&amp;gt; StartAsync()&lt;br /&gt;
        {&lt;br /&gt;
            string targetExtNum = &amp;quot;100&amp;quot;; &lt;br /&gt;
            string mobileElu = &amp;quot;&amp;quot;;&lt;br /&gt;
            string profileName = &amp;quot;Available&amp;quot;; &lt;br /&gt;
&lt;br /&gt;
            // Nommage de l&#039;astreinte&lt;br /&gt;
            string prenomElu = &amp;quot;Accueil&amp;quot;; &lt;br /&gt;
            string nomElu = &amp;quot;&amp;quot;; &lt;br /&gt;
&lt;br /&gt;
            try&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
[[Catégorie:3CX]]&lt;/div&gt;</summary>
		<author><name>Anthony</name></author>
	</entry>
	<entry>
		<id>https://indywiki.fr/index.php?title=Astreinte&amp;diff=22239</id>
		<title>Astreinte</title>
		<link rel="alternate" type="text/html" href="https://indywiki.fr/index.php?title=Astreinte&amp;diff=22239"/>
		<updated>2026-04-03T09:11:03Z</updated>

		<summary type="html">&lt;p&gt;Anthony : /* Via script */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== par le statut ==&lt;br /&gt;
&lt;br /&gt;
Dans les réglages de l&#039;extension qui accueille les appels :&lt;br /&gt;
&lt;br /&gt;
#Réglages&lt;br /&gt;
#Transfert d&#039;appels&lt;br /&gt;
#Choisir le statut de l&#039;extension à activer pour enclencher le renvoi vers l&#039;astreinte. Dans l&#039;exemple &#039;&#039;&#039;Absent&#039;&#039;&#039;. Pas l&#039;état &#039;&#039;&#039;Disponible&#039;&#039;&#039; évidemment.&lt;br /&gt;
#Dans &amp;quot;Transférer les appels externes à&amp;quot;, choisir &#039;&#039;&#039;Numéro externe&#039;&#039;&#039;&lt;br /&gt;
#Saisir le numéro de l&#039;astreinte&lt;br /&gt;
#Cocher &#039;&#039;&#039;Rebond&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
[[Fichier:2026-04-02 16h03 02.png]]&lt;br /&gt;
&lt;br /&gt;
Limite / contrainte : &lt;br /&gt;
*si les astreintes tournent, avant chaque période d&#039;astreinte, il faut faire ce cheminement pour que le bon numéro de mobile soit paramétré&lt;br /&gt;
*4 profils d&#039;astreinte maximum&lt;br /&gt;
*Nécessite de manipuler l&#039;application WEB&lt;br /&gt;
&lt;br /&gt;
== Via script==&lt;br /&gt;
===Principe===&lt;br /&gt;
On paramètre le statut choisi pour l&#039;astreinte en renvoi vers &#039;&#039;&#039;mon mobile&#039;&#039;&#039;. Un script viendra modifier le statut de l&#039;extension cible ainsi que son numéro de contact mobile, prénom et nom. Ce script déclenchable par l&#039;appel à un code court, paramétrable si on le souhaite sur une BLF. &lt;br /&gt;
===Paramétrage du statut vers &#039;&#039;&#039;mon mobile&#039;&#039;&#039;===&lt;br /&gt;
&lt;br /&gt;
[[Fichier:2026-04-03 11h09 54.png|cadre|gauche]]&lt;br /&gt;
&lt;br /&gt;
===Déclaration du script===&lt;br /&gt;
[[Fichier:2026-04-02 17h11 35.png|vignette]]&lt;br /&gt;
Rendez-vous dans :&lt;br /&gt;
&lt;br /&gt;
 Admin / Intégrations / Scripts d&#039;appels / + Ajouter personnalisé&lt;br /&gt;
&lt;br /&gt;
#Donner un nom au traitement de l&#039;appel. Exemple : &#039;&#039;&#039;astreinte_weekend&#039;&#039;&#039;&lt;br /&gt;
#Créer un code de raccourci, ce qui permettra d&#039;exécuter le script simplement en appelant ce code, et in fine par une BLF. Exemple : &#039;&#039;&#039;*99&#039;&#039;&#039;&lt;br /&gt;
#OK&lt;br /&gt;
#Coller dans le champ script le script paramétré ( voir section suivante )&lt;br /&gt;
#Sauvegarder&lt;br /&gt;
#Un message doit indiquer &#039;&#039;&#039;Compilation réussie !&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Le script===&lt;br /&gt;
&lt;br /&gt;
L&#039;éxécution du script va modifier l&#039;extension &#039;&#039;&#039;targetExtNum &#039;&#039;&#039;, il va le basculer sur le statut &#039;&#039;&#039;profileName &#039;&#039;&#039;, modifier son mobile de contact &#039;&#039;&#039;mobileElu &#039;&#039;&#039;, son nom et prénom.&lt;br /&gt;
&lt;br /&gt;
Il faut donc seulement modifier les lignes surlignés dans le code ci-dessous :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;csharp&amp;quot; line highlight=&amp;quot;14-16,19-20&amp;quot;&amp;gt;&lt;br /&gt;
using System;&lt;br /&gt;
using System.Threading.Tasks;&lt;br /&gt;
using TCX.Configuration;&lt;br /&gt;
using CallFlow;&lt;br /&gt;
using System.Linq;&lt;br /&gt;
using System.Collections.Generic;&lt;br /&gt;
&lt;br /&gt;
namespace dummy&lt;br /&gt;
{&lt;br /&gt;
    public class SetDynamicAstreinte : ScriptBase&amp;lt;SetDynamicAstreinte&amp;gt;&lt;br /&gt;
    {&lt;br /&gt;
        public override Task&amp;lt;bool&amp;gt; StartAsync()&lt;br /&gt;
        {&lt;br /&gt;
            string targetExtNum = &amp;quot;100&amp;quot;; &lt;br /&gt;
            string mobileElu = &amp;quot;0601020304&amp;quot;;&lt;br /&gt;
            string profileName = &amp;quot;Away&amp;quot;; &lt;br /&gt;
            &lt;br /&gt;
            // Nommage de l&#039;astreinte&lt;br /&gt;
            string prenomElu = &amp;quot;ASTREINTE&amp;quot;; &lt;br /&gt;
            string nomElu = &amp;quot;ELU&amp;quot;; &lt;br /&gt;
&lt;br /&gt;
            try&lt;br /&gt;
            {&lt;br /&gt;
                IPhoneSystem ps = PhoneSystem.Root;&lt;br /&gt;
                Extension targetExt = ps.GetDNByNumber(targetExtNum) as Extension;&lt;br /&gt;
&lt;br /&gt;
                if (targetExt != null)&lt;br /&gt;
                {&lt;br /&gt;
                    // 1. Mise à jour du numéro de mobile&lt;br /&gt;
                    targetExt.SetProperty(&amp;quot;MOBILENUMBER&amp;quot;, mobileElu);&lt;br /&gt;
&lt;br /&gt;
                    // 2. MISE À JOUR DU NOM&lt;br /&gt;
                    targetExt.FirstName = prenomElu;&lt;br /&gt;
                    targetExt.LastName = nomElu;&lt;br /&gt;
&lt;br /&gt;
                    // 3. Changement du profil de statut&lt;br /&gt;
                    var profile = targetExt.FwdProfiles.FirstOrDefault(p =&amp;gt; p.Name.Equals(profileName, StringComparison.OrdinalIgnoreCase));&lt;br /&gt;
                    &lt;br /&gt;
                    if (profile != null)&lt;br /&gt;
                    {&lt;br /&gt;
                        targetExt.CurrentProfile = profile;&lt;br /&gt;
                    }&lt;br /&gt;
&lt;br /&gt;
                    // 4. Sauvegarde globale&lt;br /&gt;
                    targetExt.ResetCurrentProfileOverride();&lt;br /&gt;
                    targetExt.Save();&lt;br /&gt;
&lt;br /&gt;
                    return Task.FromResult(true);&lt;br /&gt;
                }&lt;br /&gt;
            }&lt;br /&gt;
            catch (Exception)&lt;br /&gt;
            {&lt;br /&gt;
                // Erreur silencieuse&lt;br /&gt;
            }&lt;br /&gt;
            return Task.FromResult(false);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Table de correspondance des profileName====&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Dans 3CX!! Dans le script&lt;br /&gt;
|-&lt;br /&gt;
| Disponible|| Available&lt;br /&gt;
|-&lt;br /&gt;
| Absent|| Away&lt;br /&gt;
|-&lt;br /&gt;
| Ne pas déranger|| Out of office&lt;br /&gt;
|-&lt;br /&gt;
| Custom 1|| Custom 1&lt;br /&gt;
|-&lt;br /&gt;
| Custom 2|| Custom 2&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===Configuration concrète===&lt;br /&gt;
&lt;br /&gt;
Il faut choisir un statut autre que &amp;quot;Disponible&amp;quot; qui sera activé pour l&#039;astreinte, &amp;quot;Custom 2&amp;quot; pour cet exemple&lt;br /&gt;
&lt;br /&gt;
On a besoin de gérer deux astreintes. Le poste Accueil reçoit les appels en temps normal&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Texte de la légende&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;Marcel Patulacci&#039;&#039;&#039; || &#039;&#039;&#039;Jean-Michel Apeuprè&#039;&#039;&#039;|| &#039;&#039;&#039;Poste accueil &#039;&#039;&#039; hors période d&#039;astreinte&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;syntaxhighlight lang=&amp;quot;csharp&amp;quot; line highlight=&amp;quot;3-5,8-9&amp;quot;&amp;gt;&lt;br /&gt;
public override Task&amp;lt;bool&amp;gt; StartAsync()&lt;br /&gt;
        {&lt;br /&gt;
            string targetExtNum = &amp;quot;100&amp;quot;; &lt;br /&gt;
            string mobileElu = &amp;quot;0699999999&amp;quot;;&lt;br /&gt;
            string profileName = &amp;quot;Custom 2&amp;quot;; &lt;br /&gt;
&lt;br /&gt;
            // Nommage de l&#039;astreinte&lt;br /&gt;
            string prenomElu = &amp;quot;Marcel&amp;quot;; &lt;br /&gt;
            string nomElu = &amp;quot;Patulacci&amp;quot;; &lt;br /&gt;
&lt;br /&gt;
            try&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt; || &amp;lt;syntaxhighlight lang=&amp;quot;csharp&amp;quot; line highlight=&amp;quot;3-5,8-9&amp;quot;&amp;gt;&lt;br /&gt;
public override Task&amp;lt;bool&amp;gt; StartAsync()&lt;br /&gt;
        {&lt;br /&gt;
            string targetExtNum = &amp;quot;100&amp;quot;; &lt;br /&gt;
            string mobileElu = &amp;quot;0688888888&amp;quot;;&lt;br /&gt;
            string profileName = &amp;quot;Custom 2&amp;quot;; &lt;br /&gt;
&lt;br /&gt;
            // Nommage de l&#039;astreinte&lt;br /&gt;
            string prenomElu = &amp;quot;Jean-Michel&amp;quot;; &lt;br /&gt;
            string nomElu = &amp;quot;Apeuprè&amp;quot;; &lt;br /&gt;
&lt;br /&gt;
            try&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;|| &amp;lt;syntaxhighlight lang=&amp;quot;csharp&amp;quot; line highlight=&amp;quot;3-5,8-9&amp;quot;&amp;gt;&lt;br /&gt;
public override Task&amp;lt;bool&amp;gt; StartAsync()&lt;br /&gt;
        {&lt;br /&gt;
            string targetExtNum = &amp;quot;100&amp;quot;; &lt;br /&gt;
            string mobileElu = &amp;quot;&amp;quot;;&lt;br /&gt;
            string profileName = &amp;quot;Available&amp;quot;; &lt;br /&gt;
&lt;br /&gt;
            // Nommage de l&#039;astreinte&lt;br /&gt;
            string prenomElu = &amp;quot;Accueil&amp;quot;; &lt;br /&gt;
            string nomElu = &amp;quot;&amp;quot;; &lt;br /&gt;
&lt;br /&gt;
            try&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
[[Catégorie:3CX]]&lt;/div&gt;</summary>
		<author><name>Anthony</name></author>
	</entry>
</feed>