protected async Task MarkToDeleteSponsorshipAsync(OrganizationSponsorship sponsorship)
        {
            if (sponsorship == null)
            {
                throw new BadRequestException("The sponsorship you are trying to cancel does not exist");
            }

            sponsorship.ToDelete = true;
            await _organizationSponsorshipRepository.UpsertAsync(sponsorship);
        }
        public async Task UpdateExpirationDateAsync(Guid organizationId, DateTime expireDate)
        {
            var sponsorship = await _organizationSponsorshipRepository.GetBySponsoredOrganizationIdAsync(organizationId);

            if (sponsorship == null)
            {
                return;
            }

            sponsorship.ValidUntil = expireDate;
            await _organizationSponsorshipRepository.UpsertAsync(sponsorship);
        }
        public async Task SetUpSponsorshipAsync(OrganizationSponsorship sponsorship,
                                                Organization sponsoredOrganization)
        {
            if (sponsorship == null)
            {
                throw new BadRequestException("No unredeemed sponsorship offer exists for you.");
            }

            var existingOrgSponsorship = await _organizationSponsorshipRepository
                                         .GetBySponsoredOrganizationIdAsync(sponsoredOrganization.Id);

            if (existingOrgSponsorship != null)
            {
                throw new BadRequestException("Cannot redeem a sponsorship offer for an organization that is already sponsored. Revoke existing sponsorship first.");
            }

            if (sponsorship.PlanSponsorshipType == null)
            {
                throw new BadRequestException("Cannot set up sponsorship without a known sponsorship type.");
            }

            // Do not allow self-hosted sponsorships that haven't been synced for > 0.5 year
            if (sponsorship.LastSyncDate != null && DateTime.UtcNow.Subtract(sponsorship.LastSyncDate.Value).TotalDays > 182.5)
            {
                await _organizationSponsorshipRepository.DeleteAsync(sponsorship);

                throw new BadRequestException("This sponsorship offer is more than 6 months old and has expired.");
            }

            // Check org to sponsor's product type
            var requiredSponsoredProductType = StaticStore.GetSponsoredPlan(sponsorship.PlanSponsorshipType.Value)?.SponsoredProductType;

            if (requiredSponsoredProductType == null ||
                sponsoredOrganization == null ||
                StaticStore.GetPlan(sponsoredOrganization.PlanType).Product != requiredSponsoredProductType.Value)
            {
                throw new BadRequestException("Can only redeem sponsorship offer on families organizations.");
            }

            await _paymentService.SponsorOrganizationAsync(sponsoredOrganization, sponsorship);

            await _organizationRepository.UpsertAsync(sponsoredOrganization);

            sponsorship.SponsoredOrganizationId = sponsoredOrganization.Id;
            sponsorship.OfferedToEmail          = null;
            await _organizationSponsorshipRepository.UpsertAsync(sponsorship);
        }
        public async Task <OrganizationSponsorship> CreateSponsorshipAsync(Organization sponsoringOrg, OrganizationUser sponsoringOrgUser,
                                                                           PlanSponsorshipType sponsorshipType, string sponsoredEmail, string friendlyName)
        {
            var sponsoringUser = await _userService.GetUserByIdAsync(sponsoringOrgUser.UserId.Value);

            if (sponsoringUser == null || string.Equals(sponsoringUser.Email, sponsoredEmail, System.StringComparison.InvariantCultureIgnoreCase))
            {
                throw new BadRequestException("Cannot offer a Families Organization Sponsorship to yourself. Choose a different email.");
            }

            var requiredSponsoringProductType = StaticStore.GetSponsoredPlan(sponsorshipType)?.SponsoringProductType;

            if (requiredSponsoringProductType == null ||
                sponsoringOrg == null ||
                StaticStore.GetPlan(sponsoringOrg.PlanType).Product != requiredSponsoringProductType.Value)
            {
                throw new BadRequestException("Specified Organization cannot sponsor other organizations.");
            }

            if (sponsoringOrgUser == null || sponsoringOrgUser.Status != OrganizationUserStatusType.Confirmed)
            {
                throw new BadRequestException("Only confirmed users can sponsor other organizations.");
            }

            var existingOrgSponsorship = await _organizationSponsorshipRepository
                                         .GetBySponsoringOrganizationUserIdAsync(sponsoringOrgUser.Id);

            if (existingOrgSponsorship?.SponsoredOrganizationId != null)
            {
                throw new BadRequestException("Can only sponsor one organization per Organization User.");
            }

            var sponsorship = new OrganizationSponsorship
            {
                SponsoringOrganizationId     = sponsoringOrg.Id,
                SponsoringOrganizationUserId = sponsoringOrgUser.Id,
                FriendlyName        = friendlyName,
                OfferedToEmail      = sponsoredEmail,
                PlanSponsorshipType = sponsorshipType,
            };

            if (existingOrgSponsorship != null)
            {
                // Replace existing invalid offer with our new sponsorship offer
                sponsorship.Id = existingOrgSponsorship.Id;
            }

            try
            {
                await _organizationSponsorshipRepository.UpsertAsync(sponsorship);

                return(sponsorship);
            }
            catch
            {
                if (sponsorship.Id != default)
                {
                    await _organizationSponsorshipRepository.DeleteAsync(sponsorship);
                }
                throw;
            }
        }