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
47 changes: 25 additions & 22 deletions src/controllers/authcontroller.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import bcrypt from 'bcrypt';
import jwt from 'jsonwebtoken';
import User from '../models/User.js';
import { createAndSendOTP, verifyOTP } from '../services/otp.service.js';
import bcrypt from "bcrypt";
import jwt from "jsonwebtoken";
import User from "../models/User.js";
import { createAndSendOTP, verifyOTP } from "../services/otp.service.js";

export const login = async (req, res) => {
try {
Expand All @@ -15,47 +15,52 @@ export const login = async (req, res) => {
}

const user = await User.findOne({
email: { $regex: new RegExp(`^${email}$`, 'i') },
role: { $regex: new RegExp(`^${role}$`, 'i') },
}).select('email role status password');
email: { $regex: new RegExp(`^${email}$`, "i") },
role: { $regex: new RegExp(`^${role}$`, "i") },
}).select("email role status password name");
if (!user) {
return res.status(401).json({ success: false, message: 'Invalid role or email' });
return res.status(401).json({ success: false, message: "Invalid role or email" });
}

const isMatch = await bcrypt.compare(password, user.password);
if (!isMatch) {
return res.status(401).json({ success: false, message: 'Invalid password' });
return res.status(401).json({ success: false, message: "Invalid password" });
}

// if (user.role.toLowerCase() === 'doctor' && user.status !== 'Active') {
// return res.status(403).json({ success: false, message: "Your account is currently inactive. Kindly reach out to the admin for support." });
// }

if (user.status !== 'Active') {
return res.status(403).json({ success: false, message: "Your account is currently inactive. Kindly reach out to the admin for support." });
if (user.status !== "Active") {
return res.status(403).json({
success: false,
message:
"Your account is currently inactive. Kindly reach out to the admin for support.",
});
}

const token = jwt.sign(
{ id: user._id, role: user.role, email: user.email },
process.env.JWT_SECRET,
{ expiresIn: '1h' }
{ expiresIn: "1h" },
);

res.status(200).json({
success: true,
message: 'Login successful',
message: "Login successful",
role: user.role,
token,
user: {
id: user._id,
email: user.email,
role: user.role,
status: user.status,
name: user.name,
},
});
} catch (error) {
console.error('Login error:', error);
res.status(500).json({ success: false, message: 'Server error' });
console.error("Login error:", error);
res.status(500).json({ success: false, message: "Server error" });
}
};

Expand All @@ -66,17 +71,16 @@ export const sendOTP = async (req, res, next) => {
if (!email) {
return res.status(400).json({
success: false,
message: 'Email is required'
message: "Email is required",
});
}

await createAndSendOTP(email);

res.status(200).json({
success: true,
message: 'OTP sent successfully'
message: "OTP sent successfully",
});

} catch (error) {
next(error);
}
Expand All @@ -89,18 +93,17 @@ export const validateOTP = async (req, res, next) => {
if (!email || !otp) {
return res.status(400).json({
success: false,
message: 'Email and OTP are required'
message: "Email and OTP are required",
});
}

await verifyOTP(email, otp);

res.status(200).json({
success: true,
message: 'OTP verified successfully'
message: "OTP verified successfully",
});

} catch (error) {
next(error);
}
};
};
82 changes: 51 additions & 31 deletions src/controllers/billing.controller.js
Original file line number Diff line number Diff line change
@@ -1,25 +1,36 @@
import Billing from '../models/billing.js';
import billingService from '../services/billing.service.js';
import mongoose from 'mongoose';
import { createOrder } from '../services/payment.service.js';
import razorpay from '../config/razorpay.js';
import crypto from 'crypto';
import Billing from "../models/billing.js";
import billingService from "../services/billing.service.js";
import mongoose from "mongoose";
import { createOrder } from "../services/payment.service.js";
import razorpay from "../config/razorpay.js";

Check warning on line 5 in src/controllers/billing.controller.js

View workflow job for this annotation

GitHub Actions / build (20.x)

'razorpay' is defined but never used
import crypto from "crypto";

const createBilling = async (req, res, next) => {
try {
const { patient, appointment, amount } = req.body;
const { patient, appointment, amount, paymentMethod, transactionId, status } =
req.body;

if (!patient || !amount) {
return res.status(400).json({
success: false,
message: "Patient and amount are required",
success: false,
message: "Patient and amount are required",
});
}

if (!paymentMethod || !["cash", "online"].includes(paymentMethod)) {
return res.status(400).json({
success: false,
message: "Valid payment method (cash or online) is required",
});
}

const billing = await Billing.create({
patient,
appointment,
appointment: appointment || undefined,
amount,
paymentMethod,
status: status || "pending",
transactionId: transactionId || undefined,
createdBy: req.user.id,
});

Expand All @@ -40,6 +51,13 @@

const bills = await Billing.find()
.populate("patient", "name email")
.populate({
path: "appointment",
populate: [
{ path: "doctor", select: "name spec" },
{ path: "dept", select: "dept" },
],
})
.sort({ createdAt: -1 })
.skip(skip)
.limit(limit);
Expand All @@ -62,18 +80,20 @@

const getMyBills = async (req, res, next) => {
try {
const patient = await mongoose.model('Patient').findOne({ email: req.user.email });
const patient = await mongoose.model("Patient").findOne({ email: req.user.email });
if (!patient) {
return res.status(404).json({ success: false, message: "Patient record not found" });
return res
.status(404)
.json({ success: false, message: "Patient record not found" });
}

const bills = await Billing.find({ patient: patient._id })
.populate({
path: 'appointment',
path: "appointment",
populate: [
{ path: 'doctor', select: 'name' },
{ path: 'dept', select: 'dept' }
]
{ path: "doctor", select: "name" },
{ path: "dept", select: "dept" },
],
})
.sort({ createdAt: -1 });

Expand All @@ -89,7 +109,7 @@
const createRazorpayOrder = async (req, res, next) => {
try {
const { amount, billId } = req.body;

// Check if bill exists
const bill = await Billing.findById(billId);
if (!bill) {
Expand All @@ -103,7 +123,7 @@
keyId: process.env.RAZORPAY_KEY_ID,
orderId: order.id,
amount: order.amount,
currency: order.currency
currency: order.currency,
});
} catch (error) {
next(error);
Expand Down Expand Up @@ -134,13 +154,13 @@
res.status(200).json({
success: true,
valid: true,
message: "Payment verified successfully"
message: "Payment verified successfully",
});
} else {
res.status(400).json({
success: false,
valid: false,
message: "Invalid signature"
message: "Invalid signature",
});
}
} catch (error) {
Expand Down Expand Up @@ -223,20 +243,21 @@
const billing = await billingService.createBillingStaff(req.body);
res.status(201).json(billing);
} catch (error) {
next(error)
next(error);
}
};

const changePassword = async (req, res, next) => {
try {
const { oldPassword, newPassword } = req.body;
const result = await billingService.changePassword(
req.user.id,
oldPassword,
newPassword);
req.user.id,
oldPassword,
newPassword,
);
res.status(200).json(result);
} catch (err) {
next(err)
next(err);
}
};

Expand All @@ -245,7 +266,7 @@
const billing = await billingService.getAllBillingStaff();
res.json(billing);
} catch (err) {
next(err)
next(err);
}
};

Expand All @@ -255,7 +276,7 @@
const billing = await billingService.updateBillingStaff(id, req.body);
res.json(billing);
} catch (err) {
next(err)
next(err);
}
};

Expand All @@ -265,7 +286,7 @@
const result = await billingService.deleteBillingStaff(id);
res.json(result);
} catch (err) {
next(err)
next(err);
}
};

Expand All @@ -277,13 +298,12 @@
deleteBilling,

// Staff CRUD for admin

createBillingStaff,
changePassword,
getAllBillingStaff,
updateBillingStaff,
deleteBillingStaff,
getMyBills,
createRazorpayOrder,
verifyRazorpayPayment
}
verifyRazorpayPayment,
};
3 changes: 2 additions & 1 deletion src/controllers/patient.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,8 @@

if (normalizedEmail) {
try {
await createPatientPortalAccount(normalizedEmail);
const patientName = req.body.name || patient.name || "";

Check warning on line 40 in src/controllers/patient.js

View workflow job for this annotation

GitHub Actions / build (20.x)

'patientName' is assigned a value but never used
await createPatientPortalAccount(normalizedEmail, patient.name);
} catch (portalErr) {
console.error(
`Patient saved but portal creation failed for ${normalizedEmail}:`,
Expand Down
3 changes: 2 additions & 1 deletion src/services/patientPortal.service.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import User from "../models/User.js";
import { generateRandomPassword } from "../utils/password.utils.js";
import { sendCredentialsEmail } from "./email.service.js";

export const createPatientPortalAccount = async (email) => {
export const createPatientPortalAccount = async (email, name) => {
const existingUser = await User.findOne({ email });

if (existingUser) {
Expand All @@ -20,6 +20,7 @@ export const createPatientPortalAccount = async (email) => {
role: "patient",
status: "Active",
mustChangePassword: true,
name: name || "",
});

await user.save();
Expand Down
Loading