<?xml version="1.0" encoding="utf-8"?>
<AlvaoApplication xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" ModelVersion="1">
  <Applications>
    <Application id="45">
      <Name>Asset Check Automation</Name>
      <Description>Automates asset check status update. When assets are manually moved or when check-in data is received from supported connectors - such as Microsoft Intune, Jamf, Zabbix, and others - the asset status is automatically set to Found. If no activity is detected within the past six months, the asset is marked for asset check.</Description>
      <UniqueId>5ab6a5b7-b08a-42bb-bd92-0879468afa12</UniqueId>
      <Version>11</Version>
      <AdvancedSettings />
      <Scripts>
        <Script id="103">
          <Name>AutomaticAssetCheck</Name>
          <Code>using System;
using System.Data;
using Microsoft.Data.SqlClient;
using Alvao.Apps.API;
using Alvao.Context;
using Dapper;
using Alvao.API.Common;
using System.Linq;
using Alvao.API.Common.Model.Database;

class ObjectMoveAutoAction : IObjectMoveAutoAction
{
    public Tuple&lt;bool, string&gt; OnObjectMoving(SqlConnection con, int objectId, int newParentObjectId, int personId)
    {
        throw new NotImplementedException();
    }

    public void OnObjectMoved(SqlConnection con, int objectId, int oldParentObjectId, int personId)
    {
        if (!Activation.IsModuleActivated(Alvao.Global.ModuleInfo.ModuleId.AMAutopilot))
        {
            throw new Exception("AMAutopilot module is not activated.");
        }
        var obj = Alvao.API.AM.Object.GetById(personId, objectId);
        if (obj.lintClassId == (int)Alvao.API.AM.Model.ObjectClass.Code.SpecObjTrash)
        {
            return;
        }
        if (Alvao.API.AM.ObjectProperty.TemplateContains(obj.lintClassId ?? 0, tblKind.KindCode.LastFoundAssetCheck))
        {
            Alvao.API.AM.ObjectProperty.Update(objectId, tblKind.KindCode.LastFoundAssetCheck, DateTime.Now.Date, false, true);
        }

        var propertyValues = Alvao.API.AM.ObjectProperty.GetValueList(0, (int)tblKind.KindCode.StatusAssetCheck).ToList();
        var kindValue = Alvao.API.AM.ObjectProperty.GetValuesByKindCodes(objectId, new[] { tblKind.KindCode.StatusAssetCheck }).FirstOrDefault().Value;
        var pendingValue = propertyValues.First(m =&gt; m.KindValueBehaviorId == 1).txtValue;
        var foundValue = propertyValues.First(m =&gt; m.KindValueBehaviorId == 2).txtValue;
        if (kindValue == pendingValue &amp;&amp; Alvao.API.AM.ObjectProperty.TemplateContains(obj.lintClassId ?? 0, tblKind.KindCode.StatusAssetCheck))
        {
            Alvao.API.AM.ObjectProperty.Update(objectId, tblKind.KindCode.StatusAssetCheck, foundValue, false);
        }
    }
}</Code>
          <IsLibCode>false</IsLibCode>
          <Codesign>TR3XFxHYd5k4rSpQOXgb7ZvuZMgW1AkqEJhO3gDj8EWl3nkcS7ThKA0rnDXK4xjTCZn/1/bE04bJ2h9DYk/rIPP+qtYLY+MnD1y1Tq+6FL0+FCKMUrP0QWOw3ribSLFzOgR77akgnG9hlpwqc5CxPVmUNmbL0bYXx2BjvlbG130ps50w8tjSkTs2SUNh2dtnFdL9Z5goAhEdo3N/N4p+yBXK0/Ci9QOfQNQlMjwJkQa3WI5NpVB98cMQ8HhB5W4O7yUyiOONFXrmcebFNe0UesenNuSvK1sgIJ8iqpne5D4g2SKwLs+Uyw3s7lq3jY7a6NhKqeBEcoAcB+xxwG2esQ==</Codesign>
        </Script>
        <Script id="104">
          <Name>PeriodicAssetCheckPending</Name>
          <Code>using System;
using System.Data;
using Microsoft.Data.SqlClient;
using Alvao.Global;
using Alvao.API.Common;
using Alvao.Apps.API;
using Alvao.Context;
using Dapper;
using System.Collections.Generic;
using Alvao.API.Common.Model.Database;
using System.Linq;

public class PeriodicAssetCheckPending : IPeriodicAction
{
    public string Name 
    { 
        get =&gt; "Asset check pending after 6 months";
        set { }
    }

    public void OnPeriod(SqlConnection con)
    {
        if (!Activation.IsModuleActivated(Alvao.Global.ModuleInfo.ModuleId.AMAutopilot))
        {
            throw new Exception("AMAutopilot module is not activated.");
        }
        DateTime serverTime = DateTime.Now;
        if (serverTime.Hour == 2)
        {
            var properties = Alvao.API.AM.ObjectProperty.GetValueList(0, (int)tblKind.KindCode.StatusAssetCheck);
            string notFound = properties.First(m =&gt; m.KindValueBehaviorId == 3).txtValue;
            using (var scope = AlvaoContext.GetConnectionScope())
            {
                string sql = @$"select nc.NodeId from NodeCust nc
                inner join tblNode tn on nc.NodeId = tn.intNodeId
                inner join ClassKind ck on tn.lintClassId = ck.ClassId
                inner join tblKind tk on ck.KindId = tk.intKindId
                left join vPersonalMonitors pm on pm.NodeId = tn.intNodeId
                where AssetCheckDate &lt; DATEADD(MONTH, -6, GETDATE())
                    AND tn.IsActive = 1
                    AND tk.intKindCode = @statusAssetCheckKindCodeId
                    AND (StatusAssetCheck IS NULL OR StatusAssetCheck != @notFound)
                    AND pm.NodeId IS NULL
                ";
                var nodeIds = scope.Connection.Query&lt;int&gt;(sql, 
                new { statusAssetCheckKindCodeId = (int)tblKind.KindCode.StatusAssetCheck, notFound }, 
                transaction: scope.Transaction).ToList();
                string pending = properties.First(m =&gt; m.KindValueBehaviorId == 1).txtValue;
                foreach (int id in nodeIds)
                {
                    Alvao.API.AM.ObjectProperty.Update(id, tblKind.KindCode.StatusAssetCheck, pending, false, true);
                }
            }
        }
    }
}</Code>
          <IsLibCode>false</IsLibCode>
          <Codesign>WgG9LtY/Eq0JUJXwcdd/PFOYeziGZgoXgckYV6blXk8LqftfzF1F5oouxEsxqDTAGKKz6pGXxLEKTlE2sXJB69trk9Fx+bxaLj3tVS2TKMRAJXF6MR7kTZrTFwoNjtZgec0e8Yhl5U6gOgNWMyAlFER8QffQAQLCkuq1/LDnxLZLALNKtHWKagYPb+u1Pv8oENrj+F0KUwbUUBXylQqZYUUAiUUqLL2au0p5Ez7RwzkhsPXoVi7tlrUZssZ2o0cA51kYMjmEh7x/dScC9t1I9zODbpAZTL+CaqwSTLaZyWGBQcFUUCwK/M4fDqLDOrGtC4vhoJglIc66HeRJmBXyhw==</Codesign>
        </Script>
        <Script id="106">
          <Name>ObjectPropertyAutoAction</Name>
          <Code>using System;
using System.Data;
using Microsoft.Data.SqlClient;
using Alvao.Apps.API;
using Alvao.Context;
using Dapper;
using System.Collections.Generic;
using Alvao.API.Common.Model.Database;
using Alvao.API.Common;
using System.Linq;

class ObjectPropertyAutoAction : IObjectPropertyAutoAction
{
    public ObjectPropertyModifyResult OnObjectPropertyModifying(ObjectPropertyEventArgs e)
    {
        throw new NotImplementedException();
    }

    public void OnObjectPropertyModified(ObjectPropertyEventArgs e)
    {
        if (!Activation.IsModuleActivated(Alvao.Global.ModuleInfo.ModuleId.AMAutopilot))
        {
            throw new Exception("AMAutopilot module is not activated.");
        }
        var allowedProps = new List&lt;tblKind.KindCode&gt;()
        {
            tblKind.KindCode.IntuneLastCheckIn,
            tblKind.KindCode.JamfLastCheckIn,
            tblKind.KindCode.AlvaoAgentLastCheckIn,
            tblKind.KindCode.ZabbixLastCheckIn,
            tblKind.KindCode.LansweeperLastCheckIn,
            tblKind.KindCode.LastScanDate
        };
        var property = Alvao.API.AM.ObjectProperty.GetDefinition(e.PropertyKindId);
        if (property.intKindCode.HasValue &amp;&amp; allowedProps.Contains((tblKind.KindCode)property.intKindCode))
        {
            if (e.NewValue == null)
                return;
            string strDate = e.NewValue.ToString();
            var objectClassId = Alvao.API.AM.Object.GetById(e.PersonId, e.ObjectId).lintClassId;
            bool hasLastFoundProperty = objectClassId.HasValue &amp;&amp; Alvao.API.AM.ObjectProperty.TemplateContains(objectClassId.Value , tblKind.KindCode.LastFoundAssetCheck); 
            if (hasLastFoundProperty &amp;&amp; DateTime.TryParse(strDate, out DateTime dateValue))
            {
                Alvao.API.AM.ObjectProperty.Update(e.ObjectId, tblKind.KindCode.LastFoundAssetCheck, dateValue, true, false);
            }
            var propertyValues = Alvao.API.AM.ObjectProperty.GetValueList(0, (int)tblKind.KindCode.StatusAssetCheck).ToList();
            var kindValue = Alvao.API.AM.ObjectProperty.GetValuesByKindCodes(e.ObjectId, new[] { tblKind.KindCode.StatusAssetCheck }).FirstOrDefault().Value;
            var pendingValue = propertyValues.First(m =&gt; m.KindValueBehaviorId == 1).txtValue;
            var foundValue = propertyValues.First(m =&gt; m.KindValueBehaviorId == 2).txtValue;
            if (kindValue == pendingValue)
            {
                Alvao.API.AM.ObjectProperty.Update(e.ObjectId, tblKind.KindCode.StatusAssetCheck, foundValue, false);
            }
        }
    }
}</Code>
          <IsLibCode>false</IsLibCode>
          <Codesign>D6TfAIXwjnaq+UyAV7r9dMguDj1DzmW10LNa4HQ2WjatwQRf3ub+WX456ORlN7HjxOkbpptWqJJC3r9FeWSRVPiMbSFjbGylI7OmBzxvzVIe0TNioZL6YQCwmGiNnQxI8PYne+aWkwT26xDanNvVLnetkQ7LQOEf+bRj05o5d4vWhQJmBDKrVZEcSPjpZ27r1eTJXj+Xhl474AMmw6nqNQEdlEVgyThKqGSGD73jylv4af8mQIPU6N+ISYj9KDuI1ICVoV/2il1WoK0cVvvjMSLZWjfvOc9YozZtpNkTHr1EzK/NwR6P+4xkQOmgGyqHH/fYuhToDJD4hMdNGmZuoQ==</Codesign>
        </Script>
      </Scripts>
    </Application>
  </Applications>
</AlvaoApplication>