Skip to content

Commit

Permalink
feat: Add functionality to get Revenue
Browse files Browse the repository at this point in the history
  • Loading branch information
CFCIfe committed Aug 8, 2024
1 parent a61da57 commit 4318c1c
Show file tree
Hide file tree
Showing 26 changed files with 507 additions and 47 deletions.
2 changes: 2 additions & 0 deletions src/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ import { TeamsModule } from './modules/teams/teams.module';
import { FlutterwaveModule } from './modules/flutterwave/flutterwave.module';
import { BlogModule } from './modules/blogs/blogs.module';
import { SubscriptionsModule } from './modules/subscriptions/subscriptions.module';
import { RevenueModule } from './modules/revenue/revenue.module';

@Module({
providers: [
Expand Down Expand Up @@ -152,6 +153,7 @@ import { SubscriptionsModule } from './modules/subscriptions/subscriptions.modul
FlutterwaveModule,
BlogModule,
SubscriptionsModule,
RevenueModule,
],
controllers: [HealthController, ProbeController],
})
Expand Down
11 changes: 9 additions & 2 deletions src/database/seeding/seeding.controller.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import { Body, Controller, Get, Post } from '@nestjs/common';
import { SeedingService } from './seeding.service';
import { ApiOperation, ApiTags } from '@nestjs/swagger';
import { skipAuth } from '../../helpers/skipAuth';
import { CreateAdminDto } from './dto/admin.dto';
import { User } from '../../modules/user/entities/user.entity';
import { CreateAdminResponseDto } from './dto/create-admin-response.dto';
import { SeedingService } from './seeding.service';

@ApiTags('Seed')
@skipAuth()
@Controller('seed')
export class SeedingController {
Expand All @@ -25,4 +26,10 @@ export class SeedingController {
async seedSuperAdmin(@Body() adminDetails: CreateAdminDto): Promise<CreateAdminResponseDto> {
return this.seedingService.createSuperAdmin(adminDetails);
}

@Post('transactions')
@ApiOperation({ summary: 'Seed transactions' })
async seedTransactions() {
return this.seedingService.seedTransactions();
}
}
168 changes: 159 additions & 9 deletions src/database/seeding/seeding.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,21 +7,25 @@ import {
UnauthorizedException,
} from '@nestjs/common';
import { DataSource } from 'typeorm';
import { User, UserType } from '../../modules/user/entities/user.entity';
import { Organisation } from '../../modules/organisations/entities/organisations.entity';
import { v4 as uuidv4 } from 'uuid';
import { ADMIN_CREATED, INVALID_ADMIN_SECRET, SERVER_ERROR } from '../../helpers/SystemMessages';
import { Invite } from '../../modules/invite/entities/invite.entity';
import { Product, ProductSizeType } from '../../modules/products/entities/product.entity';
import { ProductCategory } from '../../modules/product-category/entities/product-category.entity';
import { Notification } from '../../modules/notifications/entities/notifications.entity';
import { DefaultPermissions } from '../../modules/organisation-permissions/entities/default-permissions.entity';
import { PermissionCategory } from '../../modules/organisation-permissions/helpers/PermissionCategory';
import { DefaultRole } from '../../modules/organisation-role/entities/role.entity';
import { RoleCategory, RoleCategoryDescriptions } from '../../modules/organisation-role/helpers/RoleCategory';
import { Organisation } from '../../modules/organisations/entities/organisations.entity';
import { ProductCategory } from '../../modules/product-category/entities/product-category.entity';
import { Product, ProductSizeType } from '../../modules/products/entities/product.entity';
import { Profile } from '../../modules/profile/entities/profile.entity';
import { Notification } from '../../modules/notifications/entities/notifications.entity';
import { v4 as uuidv4 } from 'uuid';
import { Cart } from '../../modules/revenue/entities/cart.entity';
import { OrderItem } from '../../modules/revenue/entities/order-items.entity';
import { Order } from '../../modules/revenue/entities/order.entity';
import { Transaction } from '../../modules/revenue/entities/transaction.entity';
import { User, UserType } from '../../modules/user/entities/user.entity';
import { CreateAdminDto } from './dto/admin.dto';
import { ADMIN_CREATED, INVALID_ADMIN_SECRET, SERVER_ERROR } from '../../helpers/SystemMessages';
import { CreateAdminResponseDto } from './dto/create-admin-response.dto';
import { RoleCategory, RoleCategoryDescriptions } from '../../modules/organisation-role/helpers/RoleCategory';
import { DefaultRole } from '../../modules/organisation-role/entities/role.entity';

@Injectable()
export class SeedingService {
Expand All @@ -37,6 +41,7 @@ export class SeedingService {
const defaultPermissionRepository = this.dataSource.getRepository(DefaultPermissions);
const notificationRepository = this.dataSource.getRepository(Notification);
const defaultRoleRepository = this.dataSource.getRepository(DefaultRole);

try {
const existingPermissions = await defaultPermissionRepository.count();
const existingRoles = await defaultRoleRepository.count();
Expand Down Expand Up @@ -93,6 +98,7 @@ export class SeedingService {
await userRepository.save([u1, u2]);

const savedUsers = await userRepository.find();

if (savedUsers.length !== 2) {
throw new Error('Failed to create all users');
}
Expand Down Expand Up @@ -299,4 +305,148 @@ export class SeedingService {
throw new InternalServerErrorException(SERVER_ERROR);
}
}

async seedTransactions() {
const cartRepository = this.dataSource.getRepository(Cart);
const orderRepository = this.dataSource.getRepository(Order);
const orderItemRepository = this.dataSource.getRepository(OrderItem);
const transactionRepository = this.dataSource.getRepository(Transaction);
const userRepository = this.dataSource.getRepository(User);
const productRepository = this.dataSource.getRepository(Product);

const queryRunner = this.dataSource.createQueryRunner();
await queryRunner.connect();
await queryRunner.startTransaction();

const savedUsers = await userRepository.find();
const savedProducts = await productRepository.find();

const orders = [
orderRepository.create({
user: savedUsers[0],
total_price: 1000,
}),
orderRepository.create({
user: savedUsers[1],
total_price: 1500,
}),
orderRepository.create({
user: savedUsers[0],
total_price: 750,
}),
orderRepository.create({
user: savedUsers[1],
total_price: 1250,
}),
orderRepository.create({
user: savedUsers[0],
total_price: 2000,
}),
];

await orderRepository.save(orders);

const orderItems = [
orderItemRepository.create({
order: orders[0],
product: savedProducts[0],
quantity: 2,
total_price: 500,
}),
orderItemRepository.create({
order: orders[1],
product: savedProducts[1],
quantity: 3,
total_price: 1500,
}),
orderItemRepository.create({
order: orders[2],
product: savedProducts[2],
quantity: 1,
total_price: 750,
}),
orderItemRepository.create({
order: orders[3],
product: savedProducts[0],
quantity: 5,
total_price: 1250,
}),
orderItemRepository.create({
order: orders[4],
product: savedProducts[1],
quantity: 4,
total_price: 2000,
}),
];

await orderItemRepository.save(orderItems);

const carts = [
cartRepository.create({
user: savedUsers[0],
product: savedProducts[0],
quantity: 1,
}),
cartRepository.create({
user: savedUsers[1],
product: savedProducts[1],
quantity: 2,
}),
cartRepository.create({
user: savedUsers[0],
product: savedProducts[2],
quantity: 1,
}),
cartRepository.create({
user: savedUsers[1],
product: savedProducts[0],
quantity: 3,
}),
cartRepository.create({
user: savedUsers[0],
product: savedProducts[1],
quantity: 2,
}),
];

await cartRepository.save(carts);

const currentMonth = new Date().getMonth();
const currentYear = new Date().getFullYear();

const currentMonthDate = (day: number) => new Date(currentYear, currentMonth, day);
const previousMonthDate = (day: number) => new Date(currentYear, currentMonth - 1, day);

const transactions = [
transactionRepository.create({
order: orders[0],
amount: 1000,
date: currentMonthDate(1),
}),
transactionRepository.create({
order: orders[1],
amount: 1500,
date: currentMonthDate(10),
}),
transactionRepository.create({
order: orders[2],
amount: 750,
date: currentMonthDate(20),
}),
transactionRepository.create({
order: orders[3],
amount: 1250,
date: previousMonthDate(1),
}),
transactionRepository.create({
order: orders[4],
amount: 2000,
date: previousMonthDate(15),
}),
];

await transactionRepository.save(transactions);

await queryRunner.commitTransaction();
}
}
1 change: 1 addition & 0 deletions src/helpers/SystemMessages.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,4 +65,5 @@ export const INVITE_NOT_FOUND = 'Invite link not found';
export const BLOG_DELETED = 'Blog post has been successfully deleted';
export const NO_USER_TESTIMONIALS = 'User has no testimonials';
export const USER_TESTIMONIALS_FETCHED = 'User testimonials retrieved successfully';
export const REVENUE_FETCHED_SUCCESSFULLY = 'Revenue Fetched';
export const QUESTION_ALREADY_EXISTS = 'This question already exists.';
1 change: 1 addition & 0 deletions src/modules/invite/mocks/mockUser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,4 +27,5 @@ export const mockUser: User = {
notification_settings: [],
notifications: [],
blogs: [],
cart: [],
};
Original file line number Diff line number Diff line change
Expand Up @@ -58,4 +58,5 @@ export const mockUser: User = {
phone: '1234-887-09',
jobs: [],
blogs: [],
cart: [],
};
6 changes: 3 additions & 3 deletions src/modules/organisations/tests/mocks/organisation.mock.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
import { v4 as uuidv4 } from 'uuid';
import { Organisation } from '../../entities/organisations.entity';
import { User } from '../../../user/entities/user.entity';
import { OrganisationRole } from '../../../organisation-role/entities/organisation-role.entity';
import { Profile } from '../../../profile/entities/profile.entity';
import { OrganisationMember } from '../../entities/org-members.entity';
import { OrganisationRole } from '../../../organisation-role/entities/organisation-role.entity';
import { Organisation } from '../../entities/organisations.entity';
import { mockUser } from './user.mock';

export enum UserType {
Expand Down Expand Up @@ -85,6 +84,7 @@ export const createMockOrganisation = (): Organisation => {
profile: profileMock,
organisationMembers: [orgMemberMock],
blogs: [],
cart: [],
};

return {
Expand Down
3 changes: 2 additions & 1 deletion src/modules/organisations/tests/mocks/user.mock.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { orgMemberMock } from './organisation-member.mock';
import { profileMock } from './profile.mock';
import { UserType } from './organisation.mock';
import { profileMock } from './profile.mock';

export const mockUser = {
id: 'user123',
Expand Down Expand Up @@ -33,4 +33,5 @@ export const mockUser = {
profile: profileMock,
organisationMembers: [orgMemberMock],
blogs: null,
cart: [],
};
15 changes: 13 additions & 2 deletions src/modules/products/entities/product.entity.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import { AbstractBaseEntity } from '../../../entities/base.entity';
import { Column, Entity, ManyToOne, OneToMany } from 'typeorm';
import { Organisation } from '../../../modules/organisations/entities/organisations.entity';
import { AbstractBaseEntity } from '../../../entities/base.entity';
import { Comment } from '../../../modules/comments/entities/comments.entity';
import { Organisation } from '../../../modules/organisations/entities/organisations.entity';
import { Cart } from '../../revenue/entities/cart.entity';
import { OrderItem } from '../../revenue/entities/order-items.entity';

export enum StockStatusType {
IN_STOCK = 'in stock',
Expand Down Expand Up @@ -32,6 +34,9 @@ export class Product extends AbstractBaseEntity {
@Column({ type: 'float', nullable: false, default: 0 })
price: number;

@Column({ type: 'float', nullable: false, default: 0 })
cost_price: number;

@Column({ type: 'int', nullable: false, default: 0 })
quantity: number;

Expand All @@ -57,4 +62,10 @@ export class Product extends AbstractBaseEntity {

@OneToMany(() => Comment, comment => comment.product)
comments?: Comment[];

@OneToMany(() => OrderItem, orderItem => orderItem.product)
orderItems: OrderItem[];

@OneToMany(() => Cart, cart => cart.product)
cart: Cart[];
}
18 changes: 12 additions & 6 deletions src/modules/products/products.module.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,22 @@
import { Module } from '@nestjs/common';
import { ProductsService } from './products.service';
import { ProductsController } from './products.controller';
import { TypeOrmModule } from '@nestjs/typeorm';
import { Product } from './entities/product.entity';
import { Organisation } from '../organisations/entities/organisations.entity';
import { ProductVariant } from './entities/product-variant.entity';
import { Comment } from '../comments/entities/comments.entity';
import { Organisation } from '../organisations/entities/organisations.entity';
import { Cart } from '../revenue/entities/cart.entity';
import { OrderItem } from '../revenue/entities/order-items.entity';
import { Order } from '../revenue/entities/order.entity';
import { User } from '../user/entities/user.entity';
import { UserModule } from '../user/user.module';
import { ProductVariant } from './entities/product-variant.entity';
import { Product } from './entities/product.entity';
import { ProductsController } from './products.controller';
import { ProductsService } from './products.service';

@Module({
imports: [TypeOrmModule.forFeature([Product, Organisation, ProductVariant, Comment, User]), UserModule],
imports: [
TypeOrmModule.forFeature([Product, Organisation, ProductVariant, Comment, User, Order, OrderItem, Cart]),
UserModule,
],
controllers: [ProductsController],
providers: [ProductsService],
})
Expand Down
Loading

0 comments on commit 4318c1c

Please sign in to comment.