diff --git a/.env b/.env
index a6f280a01..d690cde6f 100644
--- a/.env
+++ b/.env
@@ -97,6 +97,7 @@ PLATFORM_IBAN=
IMPORT_TRX_TASK_INTERVAL_MINUTES=60
CHECK_IRIS_CONSENT_TASK_HOUR=10
BILLING_ADMIN_MAIL=billing_admin@podkrepi.bg
+CAMPAIGN_ADMIN_MAIL=
## Cache ##
##############
diff --git a/.env.example b/.env.example
index f39073e05..6a8620a88 100644
--- a/.env.example
+++ b/.env.example
@@ -101,6 +101,7 @@ IMPORT_TRX_TASK_INTERVAL_MINUTES=60
#which hour of the day to run the check for consent
CHECK_IRIS_CONSENT_TASK_HOUR=10
BILLING_ADMIN_MAIL=billing_admin@podkrepi.bg
+CAMPAIGN_ADMIN_MAIL=responsible for campaign management
## Cache ##
##############
diff --git a/apps/api/src/assets/templates/campaign-news-draft.json b/apps/api/src/assets/templates/campaign-news-draft.json
new file mode 100644
index 000000000..8f04ccca3
--- /dev/null
+++ b/apps/api/src/assets/templates/campaign-news-draft.json
@@ -0,0 +1,3 @@
+{
+ "subject": "Новина по Кампания Е Качена за Одобрение"
+}
diff --git a/apps/api/src/assets/templates/campaign-news-draft.mjml b/apps/api/src/assets/templates/campaign-news-draft.mjml
new file mode 100644
index 000000000..e0375f1c3
--- /dev/null
+++ b/apps/api/src/assets/templates/campaign-news-draft.mjml
@@ -0,0 +1,69 @@
+
+
+
+
+
+ {{campaignNewsTitle}}
+
+
+
+
+
+
+
+
+
+ Има качена новина по кампания {{campaignName}}, която
+ изчаква одобрение от администратор!
+
+
+
+ Към Новината
+
+
+
+ Поздрави,
+ Екипът на Подкрепи.бг
+
+
+
+
+
diff --git a/apps/api/src/campaign-file/campaign-file.controller.spec.ts b/apps/api/src/campaign-file/campaign-file.controller.spec.ts
index 1ca210948..db17cabcd 100644
--- a/apps/api/src/campaign-file/campaign-file.controller.spec.ts
+++ b/apps/api/src/campaign-file/campaign-file.controller.spec.ts
@@ -48,7 +48,7 @@ describe('CampaignFileController', () => {
ConfigService,
{
provide: CampaignService,
- useValue: { getCampaignByIdAndCoordinatorId: jest.fn(() => null) },
+ useValue: { verifyCampaignOwner: jest.fn(() => null) },
},
VaultService,
CampaignNewsService,
@@ -92,7 +92,7 @@ describe('CampaignFileController', () => {
).toEqual([fileId, fileId])
expect(personService.findOneByKeycloakId).toHaveBeenCalledWith(userMock.sub)
- expect(campaignService.getCampaignByIdAndCoordinatorId).not.toHaveBeenCalled()
+ expect(campaignService.verifyCampaignOwner).not.toHaveBeenCalled()
expect(campaignFileService.create).toHaveBeenCalledTimes(2)
})
@@ -102,16 +102,13 @@ describe('CampaignFileController', () => {
await expect(controller.create(campaignId, { roles: [] }, [], userMock)).rejects.toThrowError()
expect(personService.findOneByKeycloakId).toHaveBeenCalledWith(userMock.sub)
- expect(campaignService.getCampaignByIdAndCoordinatorId).not.toHaveBeenCalled()
+ expect(campaignService.verifyCampaignOwner).not.toHaveBeenCalled()
})
it('should throw an error for user not owning updated campaign', async () => {
await expect(controller.create(campaignId, { roles: [] }, [], userMock)).rejects.toThrowError()
expect(personService.findOneByKeycloakId).toHaveBeenCalledWith(userMock.sub)
- expect(campaignService.getCampaignByIdAndCoordinatorId).toHaveBeenCalledWith(
- campaignId,
- personIdMock,
- )
+ expect(campaignService.verifyCampaignOwner).toHaveBeenCalledWith(campaignId, personIdMock)
})
})
diff --git a/apps/api/src/campaign-file/campaign-file.controller.ts b/apps/api/src/campaign-file/campaign-file.controller.ts
index 458f183fe..dbd136931 100644
--- a/apps/api/src/campaign-file/campaign-file.controller.ts
+++ b/apps/api/src/campaign-file/campaign-file.controller.ts
@@ -23,7 +23,7 @@ import { FilesRoleDto } from './dto/files-role.dto'
import { CampaignFileService } from './campaign-file.service'
import { CampaignService } from '../campaign/campaign.service'
import { KeycloakTokenParsed, isAdmin } from '../auth/keycloak'
-import { ApiTags } from '@nestjs/swagger';
+import { ApiTags } from '@nestjs/swagger'
import { CampaignFileRole } from '@prisma/client'
@ApiTags('campaign-file')
@@ -51,10 +51,7 @@ export class CampaignFileController {
}
if (!isAdmin(user)) {
- const campaign = await this.campaignService.getCampaignByIdAndCoordinatorId(
- campaignId,
- person.id,
- )
+ const campaign = await this.campaignService.verifyCampaignOwner(campaignId, person.id)
if (!campaign) {
throw new NotFoundException(
'User ' + user.name + 'is not admin or coordinator of campaign with id: ' + campaignId,
@@ -88,8 +85,8 @@ export class CampaignFileController {
'Content-Type': file.mimetype,
'Content-Disposition': 'attachment; filename="' + file.filename + '"',
'Cache-Control': file.mimetype.startsWith('image/')
- ? 'public, s-maxage=15552000, stale-while-revalidate=15552000, immutable'
- : 'no-store'
+ ? 'public, s-maxage=15552000, stale-while-revalidate=15552000, immutable'
+ : 'no-store',
})
return new StreamableFile(file.stream)
diff --git a/apps/api/src/campaign-news/campaign-news.module.ts b/apps/api/src/campaign-news/campaign-news.module.ts
index 011c57f71..e1d3df1d6 100644
--- a/apps/api/src/campaign-news/campaign-news.module.ts
+++ b/apps/api/src/campaign-news/campaign-news.module.ts
@@ -5,11 +5,12 @@ import { PrismaService } from '../prisma/prisma.service'
import { PersonModule } from '../person/person.module'
import { MarketingNotificationsModule } from '../notifications/notifications.module'
import { ConfigService } from '@nestjs/config'
+import { EmailService } from '../email/email.service'
@Module({
imports: [PersonModule, MarketingNotificationsModule],
controllers: [CampaignNewsController],
- providers: [CampaignNewsService, PrismaService, ConfigService],
+ providers: [CampaignNewsService, PrismaService, ConfigService, EmailService],
exports: [CampaignNewsService],
})
export class CampaignNewsModule {}
diff --git a/apps/api/src/campaign-news/campaign-news.service.ts b/apps/api/src/campaign-news/campaign-news.service.ts
index c887a2a05..a48d7a51b 100644
--- a/apps/api/src/campaign-news/campaign-news.service.ts
+++ b/apps/api/src/campaign-news/campaign-news.service.ts
@@ -8,12 +8,15 @@ import { SendGridParams } from '../notifications/providers/notifications.sendgri
import { DateTime } from 'luxon'
import { ConfigService } from '@nestjs/config'
import { MarketingNotificationsService } from '../notifications/notifications.service'
+import { CampaignNewsDraftEmailDto } from '../email/template.interface'
+import { EmailService } from '../email/email.service'
@Injectable()
export class CampaignNewsService {
constructor(
private prisma: PrismaService,
private readonly config: ConfigService,
+ private sendEmail: EmailService,
private readonly marketingNotificationsService: MarketingNotificationsService,
) {}
private RECORDS_PER_PAGE = 4
@@ -24,8 +27,14 @@ export class CampaignNewsService {
try {
const campaignNews = await this.prisma.campaignNews.create({ data: campaignNewsDto })
if (campaignNews.state === 'published' && notify)
+ // USER Notification
//Don't await --> send to background
- this.sendArticleNotification(campaignNews).catch((e) => console.log(e))
+ this.sendArticleNotification(campaignNews).catch((e) => Logger.warn(e))
+
+ // ADMIN Notification
+ //Don't await --> send to background
+ this.notifyAdminsForNewsUpload(campaignNews).catch((e) => Logger.warn(e))
+
return campaignNews
} catch (error) {
const message = 'Creating article about campaign failed'
@@ -34,6 +43,39 @@ export class CampaignNewsService {
}
}
+ async notifyAdminsForNewsUpload(news: CampaignNews) {
+ const campaign = await this.prisma.campaign.findFirst({
+ where: { id: news.campaignId },
+ })
+
+ if (!campaign) return
+
+ // Build the links
+ const stage = this.config.get('APP_ENV') === 'development' ? 'APP_URL_LOCAL' : 'APP_URL'
+ const appUrl = this.config.get(stage)
+ const newsLink = `${appUrl}/campaigns/${campaign.slug}/news/admin-panel`
+ const campaignLink = `${appUrl}/campaigns/${campaign.slug}`
+ const campaignAdminEmail = this.config.get('mail.campaignAdminEmail', '')
+
+ if (!campaignAdminEmail) return
+
+ // Prepare Email data
+ const recepient = { to: [campaignAdminEmail] }
+
+ const mail = new CampaignNewsDraftEmailDto({
+ campaignName: campaign.title,
+ campaignNewsTitle: news.title,
+ campaignLink,
+ newsLink,
+ })
+
+ // Send Notification
+ await this.sendEmail.sendFromTemplate(mail, recepient, {
+ //Allow users to receive the mail, regardles of unsubscribes
+ bypassUnsubscribeManagement: { enable: true },
+ })
+ }
+
async sendArticleNotification(news: CampaignNews) {
const template = await this.prisma.marketingTemplates.findFirst({
where: {
diff --git a/apps/api/src/campaign/campaign.service.ts b/apps/api/src/campaign/campaign.service.ts
index 23dfd820b..e46c60d62 100644
--- a/apps/api/src/campaign/campaign.service.ts
+++ b/apps/api/src/campaign/campaign.service.ts
@@ -235,15 +235,23 @@ export class CampaignService {
return campaigns
}
- async getCampaignByIdAndCoordinatorId(
- campaignId: string,
- coordinatorId: string,
- ): Promise {
- const campaign = await this.prisma.campaign.findFirst({
- where: { id: campaignId, coordinator: { personId: coordinatorId } },
- include: { coordinator: true },
+ // Check if the campaign exists by coordinator or organizer
+ async verifyCampaignOwner(campaignId: string, personId: string): Promise {
+ const campaignByCoordinator = await this.prisma.campaign.findFirst({
+ where: { id: campaignId, coordinator: { personId } },
+ include: { coordinator: true, organizer: true },
})
- return campaign
+
+ if (campaignByCoordinator !== null) {
+ return campaignByCoordinator
+ }
+
+ const campaignByOrganizer = await this.prisma.campaign.findFirst({
+ where: { id: campaignId, organizer: { personId } },
+ include: { coordinator: true, organizer: true },
+ })
+
+ return campaignByOrganizer
}
async getCampaignByIdWithPersonIds(id: string) {
@@ -630,8 +638,15 @@ export class CampaignService {
})
//if donation is switching to successful, increment the vault amount and send notification
- if (newDonationStatus === DonationStatus.succeeded) {
- await this.vaultService.incrementVaultAmount(donation.targetVaultId, donation.amount, tx)
+ if (
+ donation.status != DonationStatus.succeeded &&
+ newDonationStatus === DonationStatus.succeeded
+ ) {
+ await this.vaultService.incrementVaultAmount(
+ donation.targetVaultId,
+ paymentData.netAmount,
+ tx,
+ )
this.notificationService.sendNotification('successfulDonation', {
...updatedDonation,
person: updatedDonation.person,
@@ -739,8 +754,15 @@ export class CampaignService {
async createDonationWish(wish: string, donationId: string, campaignId: string) {
const person = await this.prisma.donation.findUnique({ where: { id: donationId } }).person()
- await this.prisma.donationWish.create({
- data: {
+ await this.prisma.donationWish.upsert({
+ where: { donationId },
+ create: {
+ message: wish,
+ donationId,
+ campaignId,
+ personId: person?.id,
+ },
+ update: {
message: wish,
donationId,
campaignId,
@@ -1056,7 +1078,7 @@ export class CampaignService {
throw new UnauthorizedException()
}
- const campaign = await this.getCampaignByIdAndCoordinatorId(campaignId, person.id)
+ const campaign = await this.verifyCampaignOwner(campaignId, person.id)
if (!campaign) {
throw new UnauthorizedException()
}
diff --git a/apps/api/src/config/configuration.ts b/apps/api/src/config/configuration.ts
index 57e0b38f0..6dee37d3a 100644
--- a/apps/api/src/config/configuration.ts
+++ b/apps/api/src/config/configuration.ts
@@ -45,7 +45,10 @@ export default () => ({
banksEndPoint: process.env.IRIS_API_URL + '/banks?country=bulgaria',
ibansEndPoint: process.env.IRIS_API_URL + '/ibans',
transactionsEndPoint: process.env.IRIS_API_URL + '/transactions',
+ },
+ mail: {
billingAdminEmail: process.env.BILLING_ADMIN_MAIL,
+ campaignAdminEmail: process.env.CAMPAIGN_ADMIN_MAIL,
},
tasks: {
import_transactions: { interval: process.env.IMPORT_TRX_TASK_INTERVAL_MINUTES },
diff --git a/apps/api/src/donations/events/stripe-payment.service.spec.ts b/apps/api/src/donations/events/stripe-payment.service.spec.ts
index 8586aade3..48988c2c1 100644
--- a/apps/api/src/donations/events/stripe-payment.service.spec.ts
+++ b/apps/api/src/donations/events/stripe-payment.service.spec.ts
@@ -11,7 +11,14 @@ import { INestApplication } from '@nestjs/common'
import request from 'supertest'
import { StripeModule, StripeModuleConfig, StripePayloadService } from '@golevelup/nestjs-stripe'
-import { Donation, DonationType, RecurringDonationStatus } from '@prisma/client'
+import {
+ Campaign,
+ CampaignState,
+ Donation,
+ DonationType,
+ RecurringDonationStatus,
+ Vault,
+} from '@prisma/client'
import {
campaignId,
@@ -218,17 +225,17 @@ describe('StripePaymentService', () => {
.mockName('createDonationWish')
.mockImplementation(() => Promise.resolve())
- prismaMock.donation.create.mockResolvedValue({
+ prismaMock.donation.findUnique.mockResolvedValue({
id: 'test-donation-id',
type: DonationType.donation,
- status: DonationStatus.succeeded,
+ status: DonationStatus.waiting,
provider: 'stripe',
extCustomerId: paymentData.stripeCustomerId ?? '',
extPaymentIntentId: paymentData.paymentIntentId,
extPaymentMethodId: 'card',
targetVaultId: 'test-vault-id',
- amount: paymentData.netAmount,
- chargedAmount: paymentData.netAmount,
+ amount: 0, //amount is 0 on donation created from payment-intent
+ chargedAmount: 0,
currency: 'BGN',
createdAt: new Date(),
updatedAt: new Date(),
@@ -237,14 +244,34 @@ describe('StripePaymentService', () => {
personId: 'donation-person',
})
+ prismaMock.donation.update.mockResolvedValue({
+ id: 'test-donation-id',
+ targetVaultId: 'test-vault-id',
+ amount: paymentData.netAmount,
+ status: 'succeeded',
+ person: { firstName: 'Full', lastName: 'Name' },
+ } as Donation & { person: unknown })
+
+ prismaMock.vault.update.mockResolvedValue({ campaignId: 'test-campaign' } as Vault)
+
+ prismaMock.campaign.findFirst.mockResolvedValue({
+ id: 'test-campaign',
+ state: CampaignState.active,
+ targetAmount: paymentData.netAmount,
+ vaults: [{ amount: paymentData.netAmount }],
+ } as unknown as Campaign)
+
jest.spyOn(prismaMock, '$transaction').mockImplementation((callback) => callback(prismaMock))
const mockedUpdateDonationPayment = jest
.spyOn(campaignService, 'updateDonationPayment')
.mockName('updateDonationPayment')
- const mockedIncrementVaultAmount = jest
- .spyOn(vaultService, 'incrementVaultAmount')
- .mockImplementation()
+ const mockedIncrementVaultAmount = jest.spyOn(vaultService, 'incrementVaultAmount')
+
+ const mockedUpdateCampaignStatusIfTargetReached = jest.spyOn(
+ campaignService,
+ 'updateCampaignStatusIfTargetReached',
+ )
return request(app.getHttpServer())
.post(defaultStripeWebhookEndpoint)
@@ -255,16 +282,17 @@ describe('StripePaymentService', () => {
.then(() => {
expect(mockedCampaignById).toHaveBeenCalledWith(campaignId) //campaignId from the Stripe Event
expect(mockedUpdateDonationPayment).toHaveBeenCalled()
- expect(prismaMock.donation.create).toHaveBeenCalled()
+ expect(prismaMock.donation.findUnique).toHaveBeenCalled()
+ expect(prismaMock.donation.create).not.toHaveBeenCalled()
expect(mockedIncrementVaultAmount).toHaveBeenCalled()
- expect(prismaMock.donation.update).toHaveBeenCalledWith({
- where: { id: 'test-donation-id' },
+ expect(prismaMock.donation.update).toHaveBeenCalledTimes(2) //once for the amount and second time for assigning donation to the person
+ expect(mockedUpdateCampaignStatusIfTargetReached).toHaveBeenCalled()
+ expect(prismaMock.campaign.update).toHaveBeenCalledWith({
+ where: {
+ id: 'test-campaign',
+ },
data: {
- person: {
- connect: {
- email: paymentData.billingEmail,
- },
- },
+ state: CampaignState.complete,
},
})
expect(mockedcreateDonationWish).toHaveBeenCalled()
@@ -293,31 +321,22 @@ describe('StripePaymentService', () => {
mockChargeEventSucceeded.data.object as Stripe.Charge,
)
- jest.spyOn(prismaMock, '$transaction').mockImplementation((callback) => callback(prismaMock))
- const mockedUpdateDonationPayment = jest
- .spyOn(campaignService, 'updateDonationPayment')
- .mockName('updateDonationPayment')
-
- const mockedIncrementVaultAmount = jest
- .spyOn(vaultService, 'incrementVaultAmount')
- .mockImplementation()
-
const mockedcreateDonationWish = jest
.spyOn(campaignService, 'createDonationWish')
.mockName('createDonationWish')
.mockImplementation(() => Promise.resolve())
- prismaMock.donation.create.mockResolvedValue({
+ prismaMock.donation.findUnique.mockResolvedValue({
id: 'test-donation-id',
type: DonationType.donation,
- status: DonationStatus.succeeded,
+ status: DonationStatus.waiting,
provider: 'stripe',
extCustomerId: paymentData.stripeCustomerId ?? '',
extPaymentIntentId: paymentData.paymentIntentId,
extPaymentMethodId: 'card',
targetVaultId: 'test-vault-id',
- amount: paymentData.netAmount,
- chargedAmount: paymentData.netAmount,
+ amount: 0, //amount is 0 on donation created from payment-intent
+ chargedAmount: 0,
currency: 'BGN',
createdAt: new Date(),
updatedAt: new Date(),
@@ -326,6 +345,23 @@ describe('StripePaymentService', () => {
personId: 'donation-person',
})
+ prismaMock.donation.update.mockResolvedValue({
+ id: 'test-donation-id',
+ targetVaultId: 'test-vault-id',
+ amount: (mockInvoicePaidEvent.data.object as Stripe.Invoice).amount_paid,
+ status: 'succeeded',
+ person: { firstName: 'Full', lastName: 'Name' },
+ } as Donation & { person: unknown })
+
+ prismaMock.vault.update.mockResolvedValue({ campaignId: 'test-campaign' } as Vault)
+
+ jest.spyOn(prismaMock, '$transaction').mockImplementation((callback) => callback(prismaMock))
+ const mockedUpdateDonationPayment = jest
+ .spyOn(campaignService, 'updateDonationPayment')
+ .mockName('updateDonationPayment')
+
+ const mockedIncrementVaultAmount = jest.spyOn(vaultService, 'incrementVaultAmount')
+
return request(app.getHttpServer())
.post(defaultStripeWebhookEndpoint)
.set('stripe-signature', header)
@@ -335,8 +371,9 @@ describe('StripePaymentService', () => {
.then(() => {
expect(mockedCampaignById).toHaveBeenCalledWith(campaignId) //campaignId from the Stripe Event
expect(mockedUpdateDonationPayment).toHaveBeenCalled()
- expect(prismaMock.donation.create).toHaveBeenCalled()
- expect(prismaMock.donation.update).not.toHaveBeenCalled()
+ expect(prismaMock.donation.findUnique).toHaveBeenCalled()
+ expect(prismaMock.donation.create).not.toHaveBeenCalled()
+ expect(prismaMock.donation.update).toHaveBeenCalledOnce() //for the donation to succeeded
expect(mockedIncrementVaultAmount).toHaveBeenCalled()
expect(mockedcreateDonationWish).toHaveBeenCalled()
})
diff --git a/apps/api/src/donations/events/stripe-payment.service.ts b/apps/api/src/donations/events/stripe-payment.service.ts
index 3a214299b..6658ea241 100644
--- a/apps/api/src/donations/events/stripe-payment.service.ts
+++ b/apps/api/src/donations/events/stripe-payment.service.ts
@@ -117,8 +117,9 @@ export class StripePaymentService {
DonationStatus.succeeded,
metadata,
)
+
//updateDonationPayment will mark the campaign as completed if amount is reached
- await this.checkForCompletedCampaign(metadata.campaignId)
+ await this.cancelSubscriptionsIfCompletedCampaign(metadata.campaignId)
//and finally save the donation wish
if (donationId && metadata?.wish) {
@@ -306,11 +307,11 @@ export class StripePaymentService {
)
//updateDonationPayment will mark the campaign as completed if amount is reached
- await this.checkForCompletedCampaign(metadata.campaignId)
+ await this.cancelSubscriptionsIfCompletedCampaign(metadata.campaignId)
}
//if the campaign is finished, we need to stop all active subscriptions
- async checkForCompletedCampaign(campaignId: string) {
+ async cancelSubscriptionsIfCompletedCampaign(campaignId: string) {
const updatedCampaign = await this.campaignService.getCampaignById(campaignId)
if (updatedCampaign.state === CampaignState.complete) {
const recurring =
diff --git a/apps/api/src/email/template.interface.ts b/apps/api/src/email/template.interface.ts
index 371ee6f13..035fe0fc6 100644
--- a/apps/api/src/email/template.interface.ts
+++ b/apps/api/src/email/template.interface.ts
@@ -12,6 +12,7 @@ export enum TemplateType {
unrecognizedDonation = 'unrecognized-donation',
expiringIrisConsent = 'expiring-iris-consent',
confirmConsent = 'confirm-notifications-consent',
+ campaignNewsDraft = 'campaign-news-draft',
}
export type TemplateTypeKeys = keyof typeof TemplateType
export type TemplateTypeValues = typeof TemplateType[TemplateTypeKeys]
@@ -80,3 +81,12 @@ export class ConfirmConsentEmailDto extends EmailTemplate<{
}> {
name = TemplateType.confirmConsent
}
+
+export class CampaignNewsDraftEmailDto extends EmailTemplate<{
+ campaignLink: string
+ campaignName: string
+ newsLink: string
+ campaignNewsTitle: string
+}> {
+ name = TemplateType.campaignNewsDraft
+}
diff --git a/apps/api/src/prisma/prisma-client-exception.filter.ts b/apps/api/src/prisma/prisma-client-exception.filter.ts
index 9b8e9bf75..228a4faac 100644
--- a/apps/api/src/prisma/prisma-client-exception.filter.ts
+++ b/apps/api/src/prisma/prisma-client-exception.filter.ts
@@ -67,11 +67,13 @@ export class PrismaClientExceptionFilter extends BaseExceptionFilter {
return { property: el, children: [], constraints }
})
- response.status(status).json({
- statusCode: status,
- message,
- error: this.cleanUpException(exception),
- })
+ if (response) {
+ response.status(status).json({
+ statusCode: status,
+ message,
+ error: this.cleanUpException(exception),
+ })
+ }
}
/**
diff --git a/apps/api/src/tasks/bank-import/import-transactions.task.ts b/apps/api/src/tasks/bank-import/import-transactions.task.ts
index ec7fc1543..1d5332517 100644
--- a/apps/api/src/tasks/bank-import/import-transactions.task.ts
+++ b/apps/api/src/tasks/bank-import/import-transactions.task.ts
@@ -62,7 +62,7 @@ export class IrisTasks {
this.bankBIC = this.config.get('iris.bankBIC', '')
this.IBAN = this.config.get('iris.platformIBAN', '')
this.apiUrl = this.config.get('iris.apiUrl', '')
- this.billingAdminEmail = this.config.get('iris.billingAdminEmail', '')
+ this.billingAdminEmail = this.config.get('mail.billingAdminEmail', '')
this.checkForRequiredVariables()
}
@@ -324,7 +324,7 @@ export class IrisTasks {
transactionAmount.currency = Currency.BGN
} else {
// mark as unrecognized
- matchedRef = null;
+ matchedRef = null
}
}
diff --git a/manifests/base/deployment.yaml b/manifests/base/deployment.yaml
index 9707213d3..46b98591e 100644
--- a/manifests/base/deployment.yaml
+++ b/manifests/base/deployment.yaml
@@ -125,6 +125,8 @@ spec:
value: '10'
- name: BILLING_ADMIN_MAIL
value: billing_admin@podkrepi.bg
+ - name: CAMPAIGN_ADMIN_MAIL
+ value: campaign_coordinators@podkrepi.bg
- name: IRIS_AGENT_HASH
valueFrom:
secretKeyRef: