Skip to content

Commit

Permalink
feat: get all products in organisation by super admin
Browse files Browse the repository at this point in the history
  • Loading branch information
SamixYasuke committed Aug 10, 2024
1 parent b09641c commit d4a2c37
Show file tree
Hide file tree
Showing 6 changed files with 259 additions and 16 deletions.
144 changes: 143 additions & 1 deletion src/controllers/OrgController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,9 @@ import {
} from "../middleware";
import { OrgService } from "../services/org.services";
import log from "../utils/logger";
import isSuperAdmin from "../utils/isSuperAdmin";

export class OrgController {
class OrgController {
private orgService: OrgService;
constructor() {
this.orgService = new OrgService();
Expand Down Expand Up @@ -1605,4 +1606,145 @@ export class OrgController {
);
}
}

/**
* @swagger
* /api/v1/organizations/{org_id}/products:
* get:
* summary: Get all products for an organization
* tags: [Products]
* parameters:
* - in: path
* name: org_id
* required: true
* description: The ID of the organization
* schema:
* type: string
* example: "org-12345"
* responses:
* 200:
* description: Product retrieved successfully
* content:
* application/json:
* schema:
* type: object
* properties:
* status_code:
* type: integer
* example: 200
* message:
* type: string
* example: "Product retrieved successfully"
* data:
* type: object
* properties:
* products:
* type: array
* items:
* type: object
* properties:
* id:
* type: string
* example: "prod-12345"
* name:
* type: string
* example: "Product Name"
* description:
* type: string
* example: "Product Description"
* price:
* type: number
* example: 100.50
* quantity:
* type: integer
* example: 10
* category:
* type: string
* example: "Electronics"
* image:
* type: string
* example: "https://example.com/product-image.jpg"
* stock_status:
* type: string
* example: "In Stock"
* 401:
* description: User not authenticated
* content:
* application/json:
* schema:
* type: object
* properties:
* status_code:
* type: integer
* example: 401
* message:
* type: string
* example: "User not authenticated"
* 403:
* description: User is not authorized to fetch all products
* content:
* application/json:
* schema:
* type: object
* properties:
* status_code:
* type: integer
* example: 403
* message:
* type: string
* example: "User is not authorized to fetch all products"
* 500:
* description: Internal Server Error - An unexpected error has occurred
* content:
* application/json:
* schema:
* type: object
* properties:
* status_code:
* type: integer
* example: 500
* message:
* type: string
* example: "An unexpected error has occurred"
*/
public getAllOrgProducts = async (
req: Request,
res: Response,
next: NextFunction,
) => {
try {
const { org_id } = req.params;
const userId = req.user?.id;
if (!userId) {
return res.status(401).json({
status_code: 401,
success: false,
message: "User not authenticated",
});
}

const isAdmin = await isSuperAdmin(userId);
if (!isAdmin) {
return res.status(403).json({
status_code: 403,
success: false,
message: "User is not authorized to fetch all products",
});
}

const products = await this.orgService.getAllOrgProducts(org_id);
return res.status(200).json({
status_code: 200,
message: "Product retrieved successfully",
data: { products },
});
} catch (error) {
res.status(500).json({
status_code: 500,
message: error.message || "An unexpected error has occurred",
});
}
};
}

export { OrgController };
3 changes: 3 additions & 0 deletions src/models/product.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@ export class Product extends ExtendedBaseEntity {
@Column()
price: number;

@Column()
cost_price: number;

@Column({ default: 1 })
quantity: number;

Expand Down
32 changes: 19 additions & 13 deletions src/routes/organisation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,60 +14,60 @@ const orgRouter = Router();
const orgController = new OrgController();

orgRouter.get(
"/organizations/invites",
"/organisations/invites",
authMiddleware,
checkPermissions([UserRole.SUPER_ADMIN, UserRole.ADMIN]),
orgController.getAllInvite.bind(orgController),
);
orgRouter.get(
"/organizations/:org_id",
"/organisations/:org_id",
authMiddleware,
validateOrgId,
orgController.getSingleOrg.bind(orgController),
);
orgRouter.delete(
"/organizations/:org_id/user/:user_id",
"/organisations/:org_id/user/:user_id",
authMiddleware,
validateOrgId,
orgController.removeUser.bind(orgController),
);

orgRouter.post(
"/organizations",
"/organisations",
authMiddleware,
organizationValidation,
orgController.createOrganisation.bind(orgController),
);

orgRouter.get(
"/organizations/:org_id/invite",
"/organisations/:org_id/invite",
authMiddleware,
checkPermissions([UserRole.ADMIN, UserRole.SUPER_ADMIN]),
orgController.generateGenericInviteLink.bind(orgController),
);

orgRouter.post(
"organizations/:org_id/roles",
"organisations/:org_id/roles",
authMiddleware,
validateOrgRole,
checkPermissions([UserRole.SUPER_ADMIN, UserRole.ADMIN]),
orgController.createOrganizationRole.bind(orgController),
);

orgRouter.post(
"/organizations/:org_id/send-invite",
"/organisations/:org_id/send-invite",
authMiddleware,
checkPermissions([UserRole.SUPER_ADMIN, UserRole.ADMIN]),
orgController.generateAndSendInviteLinks.bind(orgController),
);
orgRouter.post(
"/organizations/accept-invite",
"/organisations/accept-invite",
authMiddleware,
orgController.addUserToOrganizationWithInvite.bind(orgController),
);

orgRouter.get(
"/users/:id/organizations",
"/users/:id/organisations",
authMiddleware,
orgController.getOrganizations.bind(orgController),
);
Expand All @@ -79,30 +79,36 @@ orgRouter.get(
);

orgRouter.put(
"/organizations/:organization_id",
"/organisations/:organization_id",
authMiddleware,
validateUpdateOrg,
checkPermissions([UserRole.SUPER_ADMIN, UserRole.USER]),
orgController.updateOrganisation.bind(orgController),
);

orgRouter.get(
"/organizations/:org_id/roles/:role_id",
"/organisations/:org_id/roles/:role_id",
authMiddleware,
orgController.getSingleRole.bind(orgController),
);

orgRouter.get(
"/organizations/:org_id/roles",
"/organisations/:org_id/roles",
authMiddleware,
orgController.getAllOrganizationRoles.bind(orgController),
);

orgRouter.put(
"/organizations/:org_id/roles/:role_id/permissions",
"/organisations/:org_id/roles/:role_id/permissions",
authMiddleware,
checkPermissions([UserRole.ADMIN]),
orgController.updateOrganizationRolePermissions.bind(orgController),
);

orgRouter.get(
"/organisations/:org_id/products",
authMiddleware,
orgController.getAllOrgProducts,
);

export { orgRouter };
1 change: 0 additions & 1 deletion src/routes/product.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import { adminOnly } from "../middleware";
const productRouter = Router();
const productController = new ProductController();

// route
productRouter.post(
"/organizations/:org_id/products",
validateProductDetails,
Expand Down
15 changes: 14 additions & 1 deletion src/services/org.services.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import {
} from "../middleware";
import { Organization, Invitation, UserOrganization } from "../models";
import { OrganizationRole } from "../models/organization-role.entity";
import { User } from "../models/user";
import { User, Product } from "../models";
import { ICreateOrganisation, ICreateOrgRole, IOrgService } from "../types";
import log from "../utils/logger";

Expand Down Expand Up @@ -528,4 +528,17 @@ export class OrgService implements IOrgService {
throw error;
}
}

public getAllOrgProducts = async (org_id: string) => {
try {
const productRepository = AppDataSource.getRepository(Product);
const products = await productRepository.find({
where: { org: { id: org_id } },
order: { created_at: "DESC" },
});
return products;
} catch (error) {
throw new Error("Unable to retrieve products. Please try again later.");
}
};
}
Loading

0 comments on commit d4a2c37

Please sign in to comment.