Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
11 changes: 0 additions & 11 deletions src/common/enums/messages.enum.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,14 +43,3 @@ export enum TrackingMessages {
PackageDelivered = 'بسته شما با موفقیت تحویل داده شد.',
TripDelayed = 'سفر با تأخیر مواجه شده است. لطفاً برای اطلاعات بیشتر با سفیر تماس بگیرید.',
}

export enum NotificationMessages {
Welcome = 'به پلتفرم هم‌بار خوش آمدید.',
PackageCreated = 'بسته شما با موفقیت ایجاد شد.',
TripCreated = 'سفر شما با موفقیت ایجاد شد.',
TripRequestCreated = 'درخواست شما برای سفیر موردنظر با موفقیت ارسال شد.',
TripRequestCanceled = 'درخواست ارسالی شما برای سفیر موردنظر با موفقیت کنسل شد.',
TripRequestAccepted = 'درخواست ارسالی شما برای سفیر موردنظر قبول شد.',
TripRequestRejected = 'درخواست ارسالی شما برای سفیر موردنظر رد شد.',
NewTransporterNote = 'سفیر برای شما یک یادداشت ارسال کرد.'
}
3 changes: 2 additions & 1 deletion src/modules/auth/auth.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { Cache } from 'cache-manager';
import { Keyv } from '@keyv/redis';
import { CheckOtpDto } from './dto/check-otp.dto';
import { ConfigService } from '@nestjs/config';
import { AuthMessages, NotFoundMessages, NotificationMessages } from '../../common/enums/messages.enum';
import { AuthMessages, NotFoundMessages } from '../../common/enums/messages.enum';
import { TokenService } from '../token/token.service';
import { UserService } from '../user/user.service';
import { AuthTokens } from '../../common/enums/auth.enum';
Expand All @@ -23,6 +23,7 @@ import { UserStatesEnum } from './types/auth.enums';
import { TransporterResponseDto } from '../user/dto/transporter-response.dto';
import { SmsService } from '../sms/sms.service';
import { NotificationService } from '../notification/notification.service';
import { NotificationMessages } from '../notification/notification-messages';

@Injectable()
export class AuthService {
Expand Down
34 changes: 34 additions & 0 deletions src/modules/notification/notification-messages.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
export enum NotificationMessages {
Welcome = '🎉 به پلتفرم هم‌بار خوش آمدید.',
PackageCreated = '📦 بسته شما با کد #{packageCode} با موفقیت ایجاد شد. حال می‌توانید برای سفرهای متناسب درخواست بفرستید.',
PackagePickedUp = '🚛 بسته #{packageCode} دریافت شد. در مسیر است!',
PackageDelivered = '🎊 بسته #{packageCode} با موفقیت تحویل داده شد. از اعتماد شما سپاسگزاریم!',
TripCreated = '🚚 سفر شما با کد #{tripCode} با موفقیت ایجاد شد.',
TripRequestCreated = '📬 درخواست سفر #{tripCode} برای بسته #{packageCode} ارسال شد. منتظر تأیید باشید!',
TripRequestCanceled = '❌ درخواست سفر #{tripCode} برای بسته #{packageCode} با موفقیت لغو شد.',
TripRequestAccepted = '✅ عالی! درخواست سفر #{tripCode} برای بسته #{packageCode} پذیرفته شد.',
TripRequestRejected = '⚠️ متأسفانه درخواست سفر #{tripCode} برای بسته #{packageCode} رد شد.',
NewTransporterNote = '📝 سفیر {transporterName} برای بسته #{packageCode} یک یادداشت جدید ارسال کرده: {noteContent}.',
}

export interface NotificationContext {
packageCode?: number;
tripCode?: number;
transporterName?: string;
noteContent?: string;
}

export function getNotificationMessage(
messageKey: NotificationMessages,
context: NotificationContext = {}
): string {
let baseMessage = messageKey as string;

// Replace placeholders with a value
Object.keys(context).forEach(key => {
const placeholder = `{${key}}`;
baseMessage = baseMessage.replace(new RegExp(placeholder, 'g'), context[key]);
});

return baseMessage;
}
14 changes: 9 additions & 5 deletions src/modules/package/package.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { BadRequestException, ForbiddenException, Injectable, NotFoundException
import { PrismaService } from '../prisma/prisma.service';
import { CreateRecipientDto } from './dto/create-recipient.dto';
import { CreatePackageDto } from './dto/create-package.dto';
import { AuthMessages, BadRequestMessages, NotFoundMessages, NotificationMessages } from '../../common/enums/messages.enum';
import { AuthMessages, BadRequestMessages, NotFoundMessages } from '../../common/enums/messages.enum';
import { formatPrismaError } from '../../common/utilities';
import { UpdatePackageDto } from './dto/update.package.dto';
import { PackageStatusEnum, RequestStatusEnum, TripStatusEnum } from '../../../generated/prisma';
Expand All @@ -18,6 +18,7 @@ import { CreateRequestDto } from '../trip/dto/create-request.dto';
import { instanceToPlain } from 'class-transformer';
import { TurfService } from '../turf/turf.service';
import { NotificationService } from '../notification/notification.service';
import { getNotificationMessage, NotificationMessages } from '../notification/notification-messages';

@Injectable()
export class PackageService {
Expand Down Expand Up @@ -192,7 +193,7 @@ export class PackageService {
userId,
{
packageId: packageData.id,
content: NotificationMessages.PackageCreated
content: getNotificationMessage(NotificationMessages.PackageCreated, { packageCode: packageData.code })
},
tx
);
Expand Down Expand Up @@ -518,9 +519,9 @@ export class PackageService {
...trip,
additionalPrice
};
}).filter(Boolean));
}));

return matchingResult;
return matchingResult.filter(Boolean);
});
}

Expand Down Expand Up @@ -596,7 +597,10 @@ export class PackageService {
userId,
{
packageId,
content: NotificationMessages.TripRequestCreated
content: getNotificationMessage(NotificationMessages.TripRequestCreated, {
packageCode: packageData.code,
tripCode: tripData.code,
})
},
tx
);
Expand Down
9 changes: 8 additions & 1 deletion src/modules/trip/trip.service.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -407,7 +407,8 @@ describe('TripService', () => {
prisma.$transaction.mockImplementation(async (callback) => callback(prisma));
prisma.tripRequest.update.mockResolvedValue({
...updatedRequest,
package: { senderId: 'user-123' }
package: { code: 'PKG-123', senderId: 'user-123' },
trip: { code: 'TRIP-123' }
} as any);

const result = await service.updateRequest('request-123', {
Expand All @@ -421,8 +422,14 @@ describe('TripService', () => {
include: {
package: {
select: {
code: true,
senderId: true
}
},
trip: {
select: {
code: true
}
}
}
});
Expand Down
52 changes: 42 additions & 10 deletions src/modules/trip/trip.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { MapService } from '../map/map.service';
import { PrismaService } from '../prisma/prisma.service';
import { formatPrismaError, generateCode, generateUniqueCode } from '../../common/utilities';
import { CreateTripDto } from './dto/create-trip.dto';
import { AuthMessages, BadRequestMessages, NotificationMessages, TrackingMessages } from '../../common/enums/messages.enum';
import { AuthMessages, BadRequestMessages, TrackingMessages } from '../../common/enums/messages.enum';
import { MatchedRequest, Package, PackageStatusEnum, Prisma, RequestStatusEnum, TripStatusEnum, TripTypeEnum } from '../../../generated/prisma';
import { UpdateTripDto } from './dto/update-trip.dto';
import { UpdateRequestDto } from './dto/update-request.dto';
Expand All @@ -18,6 +18,7 @@ import { S3Service } from '../s3/s3.service';
import { TurfService } from '../turf/turf.service';
import { Location } from '../map/map.types';
import { NotificationService } from '../notification/notification.service';
import { getNotificationMessage, NotificationMessages } from '../notification/notification-messages';

@Injectable()
export class TripService {
Expand Down Expand Up @@ -104,7 +105,7 @@ export class TripService {
userId,
{
tripId: trip.id,
content: NotificationMessages.TripCreated
content: getNotificationMessage(NotificationMessages.TripCreated, { tripCode: trip.code })
},
tx
);
Expand Down Expand Up @@ -327,27 +328,37 @@ export class TripService {
if (status === RequestStatusEnum.rejected) {
return this.prisma.$transaction(async tx => {
const {
package: { senderId },
package: packageData,
trip,
...request
} = await this.prisma.tripRequest.update({
where: { id: requestId },
data: { status },
include: {
package: {
select: {
code: true,
senderId: true
}
},
trip: {
select: {
code: true
}
}
}
});

// Add reject request notification
await this.notificationService.create(
senderId,
packageData.senderId,
{
packageId: request.packageId,
tripId: request.tripId,
content: NotificationMessages.TripRequestRejected
content: getNotificationMessage(NotificationMessages.TripRequestRejected, {
packageCode: packageData.code,
tripCode: trip.code
})
},
tx
);
Expand Down Expand Up @@ -403,7 +414,7 @@ export class TripService {
const newTotalDeviationDistance = (totalDeviationDistanceKm ?? 0) + request.deviationDistanceKm;
const newTotalDeviationDuration = (totalDeviationDurationMin ?? 0) + request.deviationDurationMin;

await tx.trip.update({
const { code: tripCode } = await tx.trip.update({
where: { id: request.tripId },
data: {
totalDeviationDistanceKm: newTotalDeviationDistance,
Expand All @@ -415,6 +426,7 @@ export class TripService {
const packageData = await tx.package.findFirstOrThrow({
where: { id: request.packageId },
select: {
code: true,
breakdown: true,
senderId: true
}
Expand Down Expand Up @@ -452,7 +464,10 @@ export class TripService {
{
packageId: request.packageId,
tripId: request.tripId,
content: NotificationMessages.TripRequestAccepted
content: getNotificationMessage(NotificationMessages.TripRequestAccepted, {
packageCode: packageData.code,
tripCode
})
},
tx
);
Expand Down Expand Up @@ -676,6 +691,7 @@ export class TripService {
id: true,
package: {
select: {
code: true,
senderId: true,
status: true,
originAddress: true
Expand Down Expand Up @@ -734,7 +750,7 @@ export class TripService {
{
packageId,
tripId,
content: TrackingMessages.PackagePickedUp
content: getNotificationMessage(NotificationMessages.PackagePickedUp, { packageCode: packageData.code })
},
tx
);
Expand Down Expand Up @@ -765,6 +781,7 @@ export class TripService {
id: true,
package: {
select: {
code: true,
senderId: true,
status: true,
recipient: {
Expand Down Expand Up @@ -837,7 +854,7 @@ export class TripService {
{
packageId,
tripId,
content: TrackingMessages.PackageDelivered
content: getNotificationMessage(NotificationMessages.PackageDelivered, { packageCode: packageData.code })
},
tx
);
Expand Down Expand Up @@ -921,10 +938,21 @@ export class TripService {
include: {
package: {
select: {
code: true,
senderId: true
}
}
}
},
transporter: {
select: {
user: {
select: {
firstName: true,
lastName: true,
}
}
}
}
}
}).catch((error: Error) => {
Expand All @@ -949,7 +977,11 @@ export class TripService {
{
packageId: m.packageId,
tripId: m.tripId,
content: NotificationMessages.NewTransporterNote
content: getNotificationMessage(NotificationMessages.NewTransporterNote, {
packageCode: m.package.code,
tripCode: trip.code,
noteContent: note
})
},
tx
);
Expand Down
Loading