functions/public/New-SMBOfficeDeployment.ps1

function New-SMBOfficeDeployment {

    [cmdletbinding(DefaultParameterSetName="TenantId")]
    [OutputType([psobject])]
    param(
    [parameter(Mandatory=$true)]
    [ValidateNotNullOrEmpty()]
    # The location of the input CSV file.
    [String] $CSV,
    [parameter(ParameterSetName="TenantId",Mandatory=$true)]
    [ValidateNotNullOrEmpty()]
    [string] $TenantId,
    [parameter(ParameterSetName="TenantDomain",Mandatory=$true)]
    [ValidateNotNullOrEmpty()]
    [string] $TenantDomain,
    [parameter()]
    [string] $MailDomain,
    #[ValidateNotNullOrEmpty()]
    [parameter()]
    [ValidateNotNullOrEmpty()]
    [string] $DefaultPassword = $(New-SWRandomPassword),
    [parameter(Mandatory=$true)]
    [ValidateNotNullOrEmpty()]
    [pscredential] $Credential = (Get-Credential -Message "Please provide your Partner Credentials"),
    [Parameter(DontShow)]
    [ValidateNotNullOrEmpty()]
    [object] $SyncHash = $null,
    [Parameter(DontShow=$true)]
    [string] $Log
    )
    
    begin{
        if([string]::IsNullOrEmpty($Log) -eq $false){
            if(test-path $Log){} else {
                $Log = Start-Log
            }
        } else {
            $Log = Start-Log
        }
        $PSDefaultParameterValues = @{"Write-Log:Log"="$Log"}


        try{
            $DeploymentJob = new-object psobject -Property @{
                Type="Office"
                Duration = "00:00:00"
                Completed = $false
                Status = @{
                    ProvisionedUsers = @()
                    ProvisionedGroups = @()
                }
                Error=$null
                Log = $Log
            }
            if($SyncHash){
                $SyncHash.DeploymentJob = ([ref]$DeploymentJob).value
            }
            $DeploymentStart = get-date
            $null = Connect-MsolService -Credential $Credential
            if($TenantDomain){
                $TenantId = ((Get-MsolPartnerContract -all).where{$_.DefaultDomainName -eq $TenantDomain}).TenantId
            }
            elseif($TenantId){$TenantDomain = ((Get-MsolPartnerContract).where{$_.TenantId -eq $TenantId}).DefaultDomainName}
            else{
                Write-Error -Type Error -Message "Invalid or missing tenant information provided"
                return $null
            }
            $PSDefaultParameterValues.Add('*-MSOL*:TenantId',$TenantId)
            $DefaultDomain = $(
                $VerifiedDomains = Get-MsolDomain -Status Verified
                if($MailDomain){
                    if($VerifiedDomains.Name -contains $MailDomain){
                        $MailDomain
                        write-log "Using the specified domain '$MailDomain' as mail domain"
                    } else {
                        throw "Mail Domain not present or verified in the tenant"
                    }
                } else {
                    $MailDomain = ($VerifiedDomains.where{$_.IsDefault -eq $true}).Name
                    $MailDomain
                    write-log "Using the default domain ($MailDomain) as mail domain"
                    
                }
        
            )
                
            #write-log "Using default domain '$DefaultDomain' as mail suffix"
            
            write-log "Getting available licenses from O365"
            $Licenses = Get-O365License -TenantId $TenantId
            write-log "Creating CSP admin account"
            $CSPAdminCredential = new-cspadmin -DomainName $TenantDomain

            
            
        } catch {
            Write-Log -Type Error -Message "Error during Office 365 Connection: $_"
        }
    }
    
    
    
    process{

        try {
            write-log "Generating O365 Deployment Inventory"
            $Inventory = ConvertTo-O365 -Path $CSV -Licenses $Licenses -Separator ','
            ##### Exchange Connection
            write-log "Opening remote session to Exchange online"
            $Connect = $false
            while($Connect -eq $false){
                try{
                    $Session = Connect-O365 -Credential $CSPAdminCredential
                    $Connect = $true
                } catch {
                    if($_.Exception.Message -like "*403*"){
                        write-log "CSP Admin Account not ready yet. Retrying Connection in 60 seconds"
                        start-sleep -Seconds 60
                    } else {throw $_}
                }
            }
            write-log -type verbose -message "Connection succeeded. Importing Exchange Online PS Session."
            #####
            
            write-log -type information -message "Provisioning Users"
            $OneDriveUsers = @()
            $i = 0
            foreach($User in $Inventory.Users){
                $i++
                Write-Progress -Id 1 -Activity "Deploying O365 Solution"`
                -Status "Provisioning Users "`
                -CurrentOperation "$i/$($Inventory.Users.Count)"`
                -PercentComplete (($i/$($Inventory.Users.Count))*100)
                $UserParameters = @{
                    Username=[Regex]::Replace("$($User.First).$($User.Last)@$($DefaultDomain)",'[^a-zA-Z0-9\@\.]', '')
                    FirstName=$User.First
                    LastName=$User.Last
                    Title=$User.Title
                    Password=$DefaultPassword
                    License=$User.License.Id
                    MobilePhone=$User.Mobile
                    Country=$User.Country
                }
                $ReturnUser = New-O365User @UserParameters
                $User.Login = $ReturnUser.SignInName
                $User.Password = $DefaultPassword
                $Inventory.Groups|where{$_.Owner -eq $User}|foreach{$_.Owner = $User}

                $DeploymentJob.Status.ProvisionedUsers += $User
                $OneDriveUsers += $UserParameters.UserName
                
            }
            Write-Progress -Id 1 -Completed -Activity "Deploying 0365 Solution"
            #write-log "Waiting some time to allow the user mailboxes to provision"
            #Start-Sleep -Seconds 30

            write-log -type information -message "Provisioning Groups"
            $i = 1
            foreach($Group in $Inventory.Groups){
                Write-Progress -Id 1 -Activity "Deploying O365 Solution"`
                -Status "Provisioning Groups"`
                -CurrentOperation "$i/$($Inventory.Groups.Count)"`
                -PercentComplete (($i/$($Inventory.Groups.Count))*100)
                $null = New-O365Group -GroupName $Group.Name -Type office -owner ($Group.Owner.Login.split('@')[0])
                $DeploymentJob.Status.ProvisionedGroups += $Group
                $i++
            }
            Write-Progress -Id 1 -Completed -Activity "Deploying 0365 Solution"
            write-log "Populating Group Memberships"
            $i = 1
            foreach($User in $Inventory.Users){
                Write-Progress -Id 1 -Activity "Deploying O365 Solution"`
                -Status "Provisioning Group Memberships"`
                -CurrentOperation "$i/$($Inventory.Users.Count)"`
                -PercentComplete (($i/$($Inventory.Users.Count))*100)
                foreach($Group in $User.Groups){
                    if(($Group.Owner).Login -ne $User.Login){
                        $null = Add-O365UserToGroup -UserName $User.Login -GroupName $Group.Name -Type Office
                    } else {
                        write-log -type information -message "$User is owner of the group $Group, membership creation skipped"
                    }
                }
                $i++
            }
            Write-Progress -Id 1 -Completed -Activity "Deploying 0365 Solution"

            write-log -type information -message "Provisioning Onedrives"
            Write-Progress -Id 1 -Activity "Deploying O365 Solution"`
                -Status "Provisioning Onedrives"`
                -PercentComplete -1
            $OnMicrosoftDomain = ((Get-MsolDomain).where{$_.Name -like "*onmicrosoft.com"}).Name
            $TenantName = $OnMicrosoftDomain.split(".")[0]
            $TenantSPAdminUrl = "https://$($TenantName)-admin.sharepoint.com"
            write-log -message "Using $TenantSPAdminUrl as admin url for SP online" -type verbose
            $null = Initialize-O365OneDrive -Users $OneDriveUsers -Credential $CSPAdminCredential -SPOAdminUrl $TenantSPAdminUrl
            Write-Progress -Id 1 -Completed -Activity "Deploying 0365 Solution"
            
            
            
            

        } catch {
            $DeploymentJob.Error = $_
            write-log -type error -message "$_ @ $($_.InvocationInfo.ScriptLineNumber) - $($_.InvocationInfo.Line))"  
        }
        finally{
            get-pssession|Remove-PSSession
            $DeploymentEnd = get-date
            $DeploymentDuration = New-TimeSpan -Start $DeploymentStart -End $DeploymentEnd
            $DeploymentJob.Duration = $("{0:HH:mm:ss}" -f ([datetime]$DeploymentDuration.Ticks))
            $DeploymentJob.Completed = $true
            ([ref]$DeploymentJob).Value
        }
        
    }
    end{
        write-log -message "Deployment Complete"
    }
}