functions/public/New-SMBOfficeDeployment.ps1

function New-SMBOfficeDeployment {
      <#
            .SYNOPSIS
            Provisions a set of groups/users in Office 365 based on an input CSV file
 
            .DESCRIPTION
            Adds a file name extension to a supplied name.
            Takes any strings for the file name or extension.
 
            .INPUTS
            None. You cannot pipe objects to New-SBSOfficeDeployment.
 
            .OUTPUTS
            System.Management.Automation.PSObject .
            New-SBSDeployment returns a custom PS object with information on the deployment:
            - Error information, if one occured
            - Provisioned users with sign-in information
            - Provisioned groups
 
            .EXAMPLE
            C:\PS> extension -name "File"
            File.txt
 
            .EXAMPLE
            C:\PS> extension -name "File" -extension "doc"
            File.doc
 
            .EXAMPLE
            C:\PS> extension "File" "doc"
            File.doc
 
            .LINK
            http://www.fabrikam.com/extension.html
 
            .LINK
            Set-Item
            #>


    [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()]
        [ValidateNotNullOrEmpty()]
        [string] $DefaultPassword = $(New-SWRandomPassword),
         [parameter(,Mandatory=$true)]
        [ValidateNotNullOrEmpty()]
        [pscredential] $Credential = (Get-Credential -Message "Please provide your Partner Credentials"),
        [Parameter(DontShow)]
        [ValidateNotNullOrEmpty()]
        [object] $SyncHash
    )
    
    begin{
        if($script:Log -eq $null){
            Start-Log
        }

         try{
             $DeploymentJob = new-object psobject -Property @{
                 Type="Office"
                 Duration = "00:00:00"
                 Completed = $false
                 Status = @{
                    ProvisionedUsers = @()
                    ProvisionedGroups = @()
                 }
                 Error=$null  
             }
            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
            }
            $DefaultDomain = (Get-MsolDomain|where{$_.IsDefault -eq $true}).Name
            write-log "Using default domain '$DefaultDomain' as mail suffix"
            $PSDefaultParameterValues = @{"*-MSOL*:TenantId"=$TenantId}
            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 -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-log "Populating Group Memberships"
            foreach($User in $Inventory.Users){
                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 verbose -message "$User is owner of the group $Group, membership creation skipped"
                    }
                }
            }

            write-log -type information -message "Provisioning Onedrives"
            $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
            
            
           
           
               

        } 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"
    }
}