Skip to content

Commit

Permalink
chore: make all DB update/create operations atomic (#59)
Browse files Browse the repository at this point in the history
  • Loading branch information
alcaprar authored Jul 26, 2024
1 parent a398420 commit 4f372a1
Show file tree
Hide file tree
Showing 9 changed files with 218 additions and 167 deletions.
Binary file modified backend/.tmp/dev.data.db
Binary file not shown.
54 changes: 29 additions & 25 deletions backend/src/api/client/controllers/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,39 +9,43 @@ export default factories.createCoreController('api::client.client', {
const { data } = ctx.request.body
const shopId = data.shop;

const clientEntity = await strapi.entityService.create('api::client.client', {
data: data
})

// If there is already a sale open we should create the order for this new client
const now = new Date();
const saleOpenNow = await strapi.db.query('api::sale.sale').findOne({
where: { shop: shopId, startDate: { $lt: now }, endDate: { $gt: now } },
orderBy: { endDate: 'desc' }
});

if (saleOpenNow != null) {
let orderEntity = await strapi.entityService.create('api::order.order', {
data: {
sale: saleOpenNow.id,
client: clientEntity.id
}
return await strapi.db.transaction(async ({ trx, rollback, commit, onCommit, onRollback }) => {
const clientEntity = await strapi.entityService.create('api::client.client', {
data: data
})

let productsSaleEntity = await strapi.db.query('api::product-sale.product-sale').findMany({
where: { sale: saleOpenNow.id }
// If there is already a sale open we should create the order for this new client
const now = new Date();
const saleOpenNow = await strapi.db.query('api::sale.sale').findOne({
where: { shop: shopId, startDate: { $lt: now }, endDate: { $gt: now } },
orderBy: { endDate: 'desc' }
});
for (let productSale of productsSaleEntity) {
await strapi.entityService.create('api::order-item.order-item', {

if (saleOpenNow != null) {
let orderEntity = await strapi.entityService.create('api::order.order', {
data: {
product_sale: productSale.id,
quantity: 0,
order: orderEntity.id
sale: saleOpenNow.id,
client: clientEntity.id
}
})

let productsSaleEntity = await strapi.db.query('api::product-sale.product-sale').findMany({
where: { sale: saleOpenNow.id }
});
for (let productSale of productsSaleEntity) {
await strapi.entityService.create('api::order-item.order-item', {
data: {
product_sale: productSale.id,
quantity: 0,
order: orderEntity.id
}
})
}
}
}

return { data: clientEntity }
await commit();
return { data: clientEntity }
})
}
})
107 changes: 58 additions & 49 deletions backend/src/api/order-item/controllers/order-item.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,36 +14,41 @@ export default factories.createCoreController('api::order-item.order-item', {
})
}

const orderItemEntity = await strapi.db
.query('api::order-item.order-item')
.findOne({ where: { id: orderItemId }, populate: ['product_sale'] })
strapi.log.info('orderItemEntity', orderItemEntity)

if (orderItemEntity.product_sale.current_available == 0) {
return ctx.badRequest('current_available is 0', {
product_sale: orderItemEntity.product_sale
})
}
return await strapi.db.transaction(async ({ trx, rollback, commit, onCommit, onRollback }) => {
const orderItemEntity = await strapi.db
.query('api::order-item.order-item')
.findOne({ where: { id: orderItemId }, populate: ['product_sale'] })
strapi.log.info('orderItemEntity', orderItemEntity)

let orderItem = await strapi.entityService.update('api::order-item.order-item', orderItemId, {
data: {
quantity: orderItemEntity.quantity + 1
if (orderItemEntity.product_sale.current_available == 0) {
return ctx.badRequest('current_available is 0', {
product_sale: orderItemEntity.product_sale
})
}
})
let productSale = await strapi.entityService.update(
'api::product-sale.product-sale',
orderItemEntity.product_sale.id,
{

let orderItem = await strapi.entityService.update('api::order-item.order-item', orderItemId, {
data: {
current_available: orderItemEntity.product_sale.current_available - 1
quantity: orderItemEntity.quantity + 1
}
}
)
})
let productSale = await strapi.entityService.update(
'api::product-sale.product-sale',
orderItemEntity.product_sale.id,
{
data: {
current_available: orderItemEntity.product_sale.current_available - 1
}
}
)

return {
orderItem,
productSale
}
await commit();

return {
orderItem,
productSale
}
})
},

async decrement(ctx, next) {
Expand All @@ -55,35 +60,39 @@ export default factories.createCoreController('api::order-item.order-item', {
})
}

const orderItemEntity = await strapi.db
.query('api::order-item.order-item')
.findOne({ where: { id: orderItemId }, populate: ['product_sale'] })
strapi.log.info('orderItemEntity', orderItemEntity)
return await strapi.db.transaction(async ({ trx, rollback, commit, onCommit, onRollback }) => {
const orderItemEntity = await strapi.db
.query('api::order-item.order-item')
.findOne({ where: { id: orderItemId }, populate: ['product_sale'] })
strapi.log.info('orderItemEntity', orderItemEntity)

if (orderItemEntity.quantity == 0) {
return ctx.badRequest('quantity is already 0', {
order_item: orderItemEntity
})
}

let orderItem = await strapi.entityService.update('api::order-item.order-item', orderItemId, {
data: {
quantity: orderItemEntity.quantity - 1
if (orderItemEntity.quantity == 0) {
return ctx.badRequest('quantity is already 0', {
order_item: orderItemEntity
})
}
})
let productSale = await strapi.entityService.update(
'api::product-sale.product-sale',
orderItemEntity.product_sale.id,
{

let orderItem = await strapi.entityService.update('api::order-item.order-item', orderItemId, {
data: {
current_available: orderItemEntity.product_sale.current_available + 1
quantity: orderItemEntity.quantity - 1
}
}
)
})
let productSale = await strapi.entityService.update(
'api::product-sale.product-sale',
orderItemEntity.product_sale.id,
{
data: {
current_available: orderItemEntity.product_sale.current_available + 1
}
}
)

return {
orderItem,
productSale
}
await commit();

return {
orderItem,
productSale
}
})
}
})
33 changes: 21 additions & 12 deletions backend/src/api/order/controllers/order.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,18 @@ export default factories.createCoreController('api::order.order', {
}
let notes = JSON.parse(ctx.request.body).notes || ''

let order = await strapi.entityService.update('api::order.order', order_id, {
data: {
notes
}
})

return order
return await strapi.db.transaction(async ({ trx, rollback, commit, onCommit, onRollback }) => {
let order = await strapi.entityService.update('api::order.order', order_id, {
data: {
notes
}
})

await commit();

return order
})
},
async confirm(ctx, next) {
strapi.log.info('confirm', ctx.params)
Expand All @@ -44,12 +49,16 @@ export default factories.createCoreController('api::order.order', {
return ctx.badRequest('Missing or invalid id', { orderId })
}

let order = await strapi.entityService.update('api::order.order', orderId, {
data: {
last_confirmed_at: new Date()
}
})
return await strapi.db.transaction(async ({ trx, rollback, commit, onCommit, onRollback }) => {
let order = await strapi.entityService.update('api::order.order', orderId, {
data: {
last_confirmed_at: new Date()
}
})

await commit();

return order
return order
})
}
})
55 changes: 32 additions & 23 deletions backend/src/api/product-sale/controllers/product-sale.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,37 +10,46 @@ export default factories.createCoreController('api::product-sale.product-sale',
const { data } = ctx.request.body;
const amountInMinor = data.amount_in_minor;

let productSale = await strapi.entityService.update('api::product-sale.product-sale', productSaleId, {
data: {
amount_in_minor: amountInMinor
}
})
return await strapi.db.transaction(async ({ trx, rollback, commit, onCommit, onRollback }) => {
let productSale = await strapi.entityService.update('api::product-sale.product-sale', productSaleId, {
data: {
amount_in_minor: amountInMinor
}
})

await commit();

return productSale
return productSale
})
},
async updateTotalAvailable(ctx) {
let productSaleId = ctx.params.id;
const { data } = ctx.request.body;
const newTotalAvailable = data.total_available;

strapi.log.info(`[controllers][product-sale][updateTotalAvailability] productSaleId '${productSaleId}' newTotalAvailable: '${newTotalAvailable}'`);
let productSaleEntity = await strapi.db.query('api::product-sale.product-sale').findOne({
where: { id: productSaleId }
});
strapi.log.info('[controllers][product-sale][updateTotalAvailability] productSaleEntity', productSaleEntity);

const delta = productSaleEntity.total_available - newTotalAvailable;
if (newTotalAvailable < productSaleEntity.total_available && (delta) < productSaleEntity.current_available) {
return ctx.badRequest('The product will get to a negative available_quantity')
}

const productSaleEntityUpdated = await strapi.entityService.update('api::product-sale.product-sale', productSaleId, {
data: {
total_available: newTotalAvailable,
current_available: productSaleEntity.current_available - delta

return await strapi.db.transaction(async ({ trx, rollback, commit, onCommit, onRollback }) => {
strapi.log.info(`[controllers][product-sale][updateTotalAvailability] productSaleId '${productSaleId}' newTotalAvailable: '${newTotalAvailable}'`);
let productSaleEntity = await strapi.db.query('api::product-sale.product-sale').findOne({
where: { id: productSaleId }
});
strapi.log.info('[controllers][product-sale][updateTotalAvailability] productSaleEntity', productSaleEntity);

const delta = productSaleEntity.total_available - newTotalAvailable;
if (newTotalAvailable < productSaleEntity.total_available && (delta) < productSaleEntity.current_available) {
return ctx.badRequest('The product will get to a negative available_quantity')
}
})

return productSaleEntityUpdated
const productSaleEntityUpdated = await strapi.entityService.update('api::product-sale.product-sale', productSaleId, {
data: {
total_available: newTotalAvailable,
current_available: productSaleEntity.current_available - delta
}
})

await commit()

return productSaleEntityUpdated
})
}
})
12 changes: 9 additions & 3 deletions backend/src/api/product/controllers/product.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,16 @@ export default factories.createCoreController('api::product.product', {
async create(ctx) {
const { data } = ctx.request.body

const response = await strapi.entityService.create('api::product.product', {
data: data

return await strapi.db.transaction(async ({ trx, rollback, commit, onCommit, onRollback }) => {
const response = await strapi.entityService.create('api::product.product', {
data: data
})

await commit();

return { response }
})

return { response }
}
})
Loading

0 comments on commit 4f372a1

Please sign in to comment.