Я не знаю, каким должен быть заголовок, но мне очень трудно рефакторинг кода.
Мне нужно понимание и помощь.
Вот бизнес-требования:
Заказ необходимо создать и обработать.
Заказ может иметь разные типы товаров, и их процесс будет отличаться.
По заказу будут выполняться некоторые базовые операции, такие как применение купона или применение монет.
Итак, я получу подробную информацию о заказе в API, например, код купона, следует ли использовать монеты, а также подробную информацию о заказываемых iStem, например, о комбинациях или услугах.
Для заказов типа комбо должна быть создана запись комбо-портфеля.
Для заказов типа услуги должно быть создано бронирование или запрос на услугу.
Итак, в OrderController ниже я сначала получаю все товары из корзины пользователя. Затем я применяю к ним купон после его проверки. OrderService.doApplyCoupon
Является ли это.
OrderService.doApplyCoupon
возвращается cartValue
который имеет,
{
subtotal,
total,
couponDiscount,
discount, // base dicount on each item
}
Если купон не передан, я рассчитываю стоимость корзины calculateCartValue
который возвращает тот же объект, что и выше.
После этого я применяю монеты, если пользователь не хотел их использовать, в противном случае.
Я храню как couponDiscount, так и usedCoins в примечаниях к заказу.
После этого создаю заказ OrderService.doCreateOrder
.
doCreateOrder
делает ниже вещей.
Он записывает детали в Order
таблица, а также создает запись в таблице счетов со значениями,
{
total,
total_due, // total- (couponDiscount + coinsUsed)
tax
}
В заказе или в счете может быть несколько позиций, поэтому,
Он создает запись в таблице сопоставления для orderItems
и invoices
который OrderItemInvoice
.
Теперь также должны быть добавлены предметы OrderItem
стол.
Наконец, я создаю транзакции для использованных купонов и монет.
Вот мой код, OrderController.js
const createOrder = async (req, res) => {
const orderData = {
combos: req.body.combos,
zoneId: req.body.zone_id,
services: req.body.services,
couponCode: req.body.combos,
isCoinsUsed: req.body.coins_used,
};
const notes = {};
let cartValue = {};
const userId = req.user.id;
const userDevice = req.device.type;
const cart = await CartService.doGetCartItemsByUserId(userId);
if (orderData.couponCode) {
const userCartValue = await OrderService.doApplyCoupon({
userId,
cartItems: cart.items,
zoneId: orderData.zoneId,
couponCode: orderData.couponCode,
slotId: safelyGet(() => orderData.services[0].slot_id),
bookingDate: safelyGet(() => orderData.services[0].bookingDate),
});
cartValue = userCartValue;
notes.couponCode = orderData.couponCode;
notes.couponDiscount = cartValue.coupon_discount;
} else {
cartValue = calculateCartValue(cart.items);
}
if (orderData.isCoinsUsed) {
const coins = await WalletService.getWalletBalance({ userId });
notes.coinsUsed = coins > cartValue.total ? cartValue.total : coins;
}
// create order and generate receipt
const order = await OrderService.doCreateOrder({
notes,
userId,
cartValue,
userDevice,
cartItems: cart.items,
});
if (orderData.services
&& orderData.services.length) {
order.bookings = await RequestService.doCreateServiceRequest({
userId,
orderId: order.id,
requestedServices: orderData.services,
});
}
if (orderData.combos
&& orderData.combos.length) {
order.combos = await ComboService.doCreateComboPurchase({
userId,
combos: orderData.combos,
orderId: order.order_id,
isActive: false,
});
}
return res.status(200).send(order);
};
OrderServic.js
const doCreateOrder = async ({
notes,
userId,
cartItems,
userDevice,
cartValue,
createdBy = 'system',
updatedBy = 'system',
}) => {
const { couponDiscount, coinsUsed } = notes;
let rzOrder = {};
const result = await sequelize.transaction(async
const {
tax,
subtotal: totalAmount,
total: totalDueAmount,
} = cartValue;
const netDueAmount = totalDueAmount - (coinsUsed || 0);
if (netDueAmount > 0) {
rzOrder = await RazorpayService.createRzOrder({
notes,
userId,
amount: netDueAmount,
});
}
const order = await Order.create(
{
user_id: userId,
status: ORDER_CREATED,
device_type: userDevice,
coins_used: coinsUsed || 0,
notes: JSON.stringify(notes),
coupon_discount: couponDiscount || 0,
order_number: `OD-${genRandomString(userId)}`,
created_by: createdBy,
updated_by: updatedBy,
invoices: [{
tax,
total_amount: totalAmount,
razorpay_order: rzOrder.id,
total_due_amount: netDueAmount,
}],
},
{
include: {
model: Invoice,
as: 'invoices',
},
transaction: t,
},
);
const orderData = order.toJSON();
const invoiceId = orderData.invoices[0].id;
cartItems.forEach((carItem) => {
carItem.order_id = order.id;
});
const orderItems = await OrderItem.bulkCreate(cartItems, { transaction: t });
const orderItemInvoices = JSON.parse(JSON.stringify(orderItems)).map(
(orderItem) => ({
customer_order_item_id: orderItem.id,
invoice_id: invoiceId,
}),
);
const invoiceItems = await OrderItemInvoice.bulkCreate(orderItemInvoices, { transaction: t });
orderData.orderItems = orderItems;
orderData.invoiceItems = invoiceItems;
if (coinsUsed && coinsUsed > 0) {
const walletDetail = await WalletService.deductFromWallet({
userId,
createdBy,
updatedBy,
transaction: t,
orderId: order.id,
amount: order.coins_used,
transactionComment: `Debited against order ${order.order_number}`,
});
orderData.walletDetail = walletDetail;
}
if (couponDiscount && couponDiscount > 0) {
await CouponService.doCreateCouponUse({
userId,
createdBy,
updatedBy,
transaction: t,
orderId: order.id,
couponCode: notes.couponCode,
couponDiscount: notes.couponDiscount,
});
}
return orderData;
});
return result;
};
Как видите, здесь много чего происходит, и я не могу найти простой способ его реорганизовать.
Я всегда сталкиваюсь с этой проблемой. Как сделать его лучше и читабельным? и разделить его на простые модули?