Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
99cb569
feat: downgrade setup for hub
aakashreddy-p Oct 9, 2025
0fe9a68
feat: setup of downgrade and autograde for hub
aakashreddy-p Oct 11, 2025
c9926b5
feat: manual downgrade setup and auto downgrade
aakashreddy-p Oct 13, 2025
a7ba2f2
Merge pull request #859 from sparrowapp-dev/development
itsmdasifraza Oct 13, 2025
9a1db1f
feat: updated downgrade model and approach
aakashreddy-p Oct 13, 2025
c082723
feat: updated downgrade model and approach
aakashreddy-p Oct 13, 2025
8198b1a
feat: updated downgrade model and approach
aakashreddy-p Oct 13, 2025
7b37d81
fix: email template link issue
aakashreddy-p Oct 13, 2025
6efe685
feat: manual downgrade condition added
aakashreddy-p Oct 13, 2025
a6fc0d1
fix: setup of restoring workspaces
aakashreddy-p Oct 14, 2025
2e31c99
feat: workspace restrcited flag are check before returning the worksp…
aakashreddy-p Oct 14, 2025
7b30995
feat: file name corrected.
aakashreddy-p Oct 14, 2025
7f6cfe9
Merge pull request #856 from aakashreddy-p/aakash/feat/maunal-downgra…
itsmdasifraza Oct 14, 2025
b650f95
add the generate-pre-script
kishangupta4514 Oct 14, 2025
e3a5139
feat: auto-downgrade restriction setup
aakashreddy-p Oct 14, 2025
5b1f05d
updated branch
aakashreddy-p Oct 14, 2025
ccab2cb
feat: staging workflow for sparrow-api []
jatinlodhi2002 Oct 14, 2025
77494d6
Merge branch 'release/2.34.0' of https://github.com/sparrowapp-dev/sp…
kishangupta4514 Oct 15, 2025
98e3b23
feat: add stg workflow and mac and linux version env[]
jatinlodhi2002 Oct 15, 2025
e917ad8
feat: add stg workflow []
jatinlodhi2002 Oct 15, 2025
8095ae9
feat: autodown grade with email template
aakashreddy-p Oct 15, 2025
30cd24b
Merge pull request #865 from sparrowapp-dev/releases/infra
itsmdasifraza Oct 16, 2025
6ee9f91
feat: remove user function updation
aakashreddy-p Oct 16, 2025
d4b57f8
add user guide in prescript and test assertions
kishangupta4514 Oct 16, 2025
76165ea
Merge branch 'release/2.34.0' of https://github.com/sparrowapp-dev/sp…
kishangupta4514 Oct 16, 2025
bd855f0
Merge pull request #862 from aakashreddy-p/aakash/feat/auto-downgrade…
itsmdasifraza Oct 16, 2025
0ac3c80
add the instruction for generating prescript
kishangupta4514 Oct 16, 2025
7036d11
Merge pull request #863 from kishangupta4514/add-pre-script
itsmdasifraza Oct 17, 2025
cf32b34
Merge branch 'development' into release/2.34.0
kishangupta4514 Oct 17, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ AZURE_CONNECTION_STRING= # Azure Storage connection string
AZURE_INSIGHTS_CONNECTION_STRING= # Azure Application Insights connection string
FEEDBACK_BLOB_CONTAINER= # Azure Blob container name for feedback storage
AI_CONVERSATION_BLOB_CONTAINER= # Azure Blob container name for AI Conversation storage
DOWNGRADE_HUB_BLOB_CONTAINER= # Azure Blob container name for downgrade Hub Details storage.

# [AI SERVICES]
# Azure OpenAI Configuration
Expand Down
44 changes: 44 additions & 0 deletions .github/workflows/staging.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
name: Staging
on:
push:
branches:
- release/2.34.0

jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@master

- uses: Azure/docker-login@v1
with:
login-server: sparrowprod.azurecr.io
username: ${{ secrets.REGISTRY_USERNAME }}
password: ${{ secrets.REGISTRY_PASSWORD }}

- run: |
docker build . -t sparrowprod.azurecr.io/sparrow-api:${{ github.run_number }} --build-arg GITHUB_TOKEN=${{ secrets.SPARROW_GITHUB_TOKEN }}
docker push sparrowprod.azurecr.io/sparrow-api:${{ github.run_number }}
deploy:
needs: build
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@master
- uses: richardrigutins/replace-in-files@v1
with:
files: "./deploymentManifests/deployment.yml"
search-text: '_BUILD__ID_'
replacement-text: '${{ github.run_number }}'

- uses: azure/setup-kubectl@v2.0

- uses: Azure/k8s-set-context@v2
with:
kubeconfig: ${{ secrets.KUBE_CONFIG }}

- uses: Azure/k8s-deploy@v4
with:
action: deploy
namespace: sparrow-staging
manifests: |
./deploymentManifests/deployment.yml
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@
"crypto-js": "^4.2.0",
"curlconverter": "^4.9.0",
"dotenv": "16.0.1",
"exceljs": "^4.4.0",
"fastify": "4.28.1",
"form-data": "^4.0.1",
"gravatar": "1.8.2",
Expand Down
448 changes: 427 additions & 21 deletions pnpm-lock.yaml

Large diffs are not rendered by default.

15 changes: 15 additions & 0 deletions src/modules/billing/billing.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,11 @@ import { UserRepository } from "@src/modules/identity/repositories/user.reposito
import { PricingService } from "@src/modules/workspace/services/pricing.repository";
import { PricingRepository } from "@src/modules/workspace/repositories/pricing.repository";
import { SalesEmailRepository } from "../workspace/repositories/sales-email.repository";
import { DownGradeTeamRepository } from "./repositories/downgradeTeam.repository";
import { DownGradeUserRepository } from "./repositories/downgradeUser.repository";
import { DownGradeWorkspaceRepository } from "./repositories/downgradeWorkspace.repository";
import { DownGradeService } from "./services/downgrade.service";
import { ExcelEmailService } from "./services/excel-email.service";

// Try to import the Stripe module, but don't crash if it's not available
let StripeModule: any;
Expand All @@ -48,6 +53,11 @@ export class BillingModule {
BillingAuditRepository,
PromoCodeRepository,
PricingRepository,
DownGradeTeamRepository,
DownGradeUserRepository,
DownGradeWorkspaceRepository,
DownGradeService,
ExcelEmailService,
BillingAuditService,
PromoCodeService,
PricingService,
Expand All @@ -73,6 +83,11 @@ export class BillingModule {
BillingAuditRepository,
BillingAuditService,
PromoCodeService,
DownGradeTeamRepository,
DownGradeUserRepository,
DownGradeWorkspaceRepository,
DownGradeService,
ExcelEmailService,
PricingService,
PaymentEmailService,
PaymentEmailHelper,
Expand Down
28 changes: 23 additions & 5 deletions src/modules/billing/controllers/stripe.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ import { SalesEmailRepository } from "@src/modules/workspace/repositories/sales-
import { ConfigService } from "@nestjs/config";
import { TrialType } from "@src/modules/common/enum/trial.enum";
import { PricingPlan } from "@src/modules/common/models/pricing.model";
import { DownGradeService } from "../services/downgrade.service";

// Dynamically import Stripe services
let StripeService: any;
Expand All @@ -72,6 +73,7 @@ export class StripeController {
private readonly pricingService: PricingService,
private readonly configService: ConfigService,
private readonly salesEmailRepository: SalesEmailRepository,
private readonly downgradeService: DownGradeService,
) {
this.isStripeAvailable = !!this.stripeService;

Expand Down Expand Up @@ -295,10 +297,10 @@ export class StripeController {
for (const planBilling of currentPlan.billing) {
if (planBilling.providers?.stripe === createSubscriptionDto.priceId) {
selectedPlan = currentPlan;
break;
break;
}
}
if (selectedPlan) break;
if (selectedPlan) break;
}
if (selectedPlan) {
// Replace or set planName
Expand Down Expand Up @@ -423,6 +425,13 @@ export class StripeController {
updateSubscriptionDto.seats,
updateSubscriptionDto.paymentBehavior,
);
if (subscription && updateSubscriptionDto?.workspaces) {
await this.downgradeService.addDowgradeDetails(
updateSubscriptionDto?.metadata?.hubId,
updateSubscriptionDto?.workspaces,
updateSubscriptionDto?.users,
);
}

return subscription;
} catch (error) {
Expand Down Expand Up @@ -459,12 +468,17 @@ export class StripeController {
): Promise<SubscriptionResponseDto> {
try {
this.checkStripeAvailability();

const subscription = await this.stripeService.cancelSubscription(
subscriptionId,
false, //disables cancellation at mid cycle
);

if (subscription) {
await this.downgradeService.addDowgradeDetails(
cancelSubscriptionDto.teamId,
cancelSubscriptionDto.workspaces,
cancelSubscriptionDto.users,
);
}
return { subscription };
} catch (error) {
throw new HttpException(
Expand Down Expand Up @@ -509,7 +523,11 @@ export class StripeController {
subscriptionId,
reactivateDto.metadata,
);

if (subscription) {
await this.downgradeService.removeDowngradeDetails(
reactivateDto.metadata?.hubId,
);
}
return { subscription };
} catch (error) {
throw new HttpException(
Expand Down
62 changes: 62 additions & 0 deletions src/modules/billing/helpers/payment-email.helper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ import {
} from "../services/payment-email.service";
import { StripeCustomerService } from "../services/stripe-customer.service";
import { PlanName } from "@src/modules/common/enum/plan.enum";
import {
UserExcelDto,
WorkspaceExcelDto,
} from "../payloads/downgrade-user.payload";

// Dynamically import payment methods service
let PaymentMethodsService: any;
Expand Down Expand Up @@ -187,6 +191,64 @@ export class PaymentEmailHelper {
}
}

/**
* Send plan downgraded emails to existing users in Hub.
*/
async sendHubDowngradedEmail(
team: any,
startDate: Date,
previousPlan: string,
newPlan: string,
sendEmails: string[],
workspaces: WorkspaceExcelDto[],
users: UserExcelDto[],
): Promise<void> {
try {
const emailData = await this.buildPlanDowngradeEmailData(
team,
startDate,
previousPlan,
newPlan,
);
if (!emailData) return;
const updateEmailData = { ...emailData, sendEmails, workspaces, users };
await this.paymentEmailService.sendPaymentEmail(
PaymentEmailType.HUB_DOWNGRADED,
updateEmailData,
);
} catch (error) {
console.error("Error sending plan downgraded email:", error);
}
}

/**
* Send plan downgraded emails to Removed users in Hub.
*/
async sendHubDowngradeRemoveUserEmail(
team: any,
startDate: Date,
previousPlan: string,
newPlan: string,
sendEmails: string[],
): Promise<void> {
try {
const emailData = await this.buildPlanDowngradeEmailData(
team,
startDate,
previousPlan,
newPlan,
);
if (!emailData) return;
const updateEmailData = { ...emailData, sendEmails };
await this.paymentEmailService.sendPaymentEmail(
PaymentEmailType.HUB_DOWNGRADED_REMOVE_USER,
updateEmailData,
);
} catch (error) {
console.error("Error sending plan downgraded email:", error);
}
}

/**
* Send upcoming payment email using customer's default payment method email
*/
Expand Down
5 changes: 3 additions & 2 deletions src/modules/billing/helpers/stripe-webhook.helper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -95,19 +95,20 @@ export class StripeWebhookHelper {
* Handle subscription updated webhook event
*/
private async handleSubscriptionUpdated(event: any): Promise<void> {
// Check for resubscription (subscription reactivated)
const isResubscribed = this.detectResubscription(event);
// Only handle for specific status changes, like cancellation
await this.stripeSubscriptionService.handleSubscriptionUpdated(
event.data.object,
event.id,
isResubscribed
);

// Get the updated team data
const teamUpdated = await this.stripeSubscriptionRepo.findTeamById(
event.data.object.metadata?.hubId,
);

// Check for resubscription (subscription reactivated)
const isResubscribed = this.detectResubscription(event);
if (isResubscribed && teamUpdated) {
// Send resubscription email
await this.paymentEmailHelper.sendSubscriptionResubscribedEmail(
Expand Down
Loading
Loading