Add stock quantity calculation to listing variant schema and enhance tests
This commit introduces a new utility function, `toId`, to handle ID conversions in the `listingvarient.schema.js` file. The `recalculate` method is updated to compute and update the stock quantity for listing variants based on product SKU and stock location. Additionally, a new test case is added in `stockQuantity.recalculate.test.js` to verify the correct behavior of stock quantity calculations before rolling up, ensuring comprehensive test coverage for this functionality.
This commit is contained in:
parent
e0f2870af3
commit
8cd8ee6f94
@ -39,6 +39,7 @@ describe('listingVarient.recalculate', () => {
|
|||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
aggregateRollups.mockReset();
|
aggregateRollups.mockReset();
|
||||||
editObject.mockReset();
|
editObject.mockReset();
|
||||||
|
jest.restoreAllMocks();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('sums sibling listing varient stock quantities onto the listing', async () => {
|
it('sums sibling listing varient stock quantities onto the listing', async () => {
|
||||||
@ -61,6 +62,52 @@ describe('listingVarient.recalculate', () => {
|
|||||||
recalculate: false,
|
recalculate: false,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('writes the product sku stock total onto the listing varient before rolling up', async () => {
|
||||||
|
jest.spyOn(listingVarientModel, 'exists').mockResolvedValue({ _id: varientId });
|
||||||
|
aggregateRollups.mockImplementation(async ({ model }) => {
|
||||||
|
if (model === productStockModel) {
|
||||||
|
return { stockQuantity: { sum: 9 } };
|
||||||
|
}
|
||||||
|
return { stockQuantity: { sum: 12 } };
|
||||||
|
});
|
||||||
|
editObject.mockResolvedValue({});
|
||||||
|
|
||||||
|
await listingVarientModel.recalculate(
|
||||||
|
{
|
||||||
|
_id: varientId,
|
||||||
|
listing: { _id: listingId, stockLocation: stockLocationId, product: productId },
|
||||||
|
product: productId,
|
||||||
|
productSku: productSkuId,
|
||||||
|
stockQuantity: 0,
|
||||||
|
},
|
||||||
|
'user-1'
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(aggregateRollups).toHaveBeenCalledWith(
|
||||||
|
expect.objectContaining({
|
||||||
|
model: productStockModel,
|
||||||
|
baseFilter: {
|
||||||
|
productSku: productSkuId,
|
||||||
|
stockLocation: stockLocationId,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
);
|
||||||
|
expect(editObject).toHaveBeenCalledWith({
|
||||||
|
model: listingVarientModel,
|
||||||
|
id: varientId,
|
||||||
|
updateData: { stockQuantity: 9 },
|
||||||
|
user: 'user-1',
|
||||||
|
recalculate: false,
|
||||||
|
});
|
||||||
|
expect(editObject).toHaveBeenCalledWith({
|
||||||
|
model: listingModel,
|
||||||
|
id: listingId,
|
||||||
|
updateData: { stockQuantity: 12 },
|
||||||
|
user: 'user-1',
|
||||||
|
recalculate: false,
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('productStock.recalculate', () => {
|
describe('productStock.recalculate', () => {
|
||||||
|
|||||||
@ -3,6 +3,12 @@ import { generateId } from '../../utils.js';
|
|||||||
import { aggregateRollups, editObject } from '../../database.js';
|
import { aggregateRollups, editObject } from '../../database.js';
|
||||||
const { Schema } = mongoose;
|
const { Schema } = mongoose;
|
||||||
|
|
||||||
|
const toId = (value) => {
|
||||||
|
if (value == null) return null;
|
||||||
|
if (typeof value === 'object' && value._id) return String(value._id);
|
||||||
|
return String(value);
|
||||||
|
};
|
||||||
|
|
||||||
const listingVarientSchema = new Schema(
|
const listingVarientSchema = new Schema(
|
||||||
{
|
{
|
||||||
_reference: { type: String, default: () => generateId()() },
|
_reference: { type: String, default: () => generateId()() },
|
||||||
@ -48,6 +54,46 @@ listingVarientSchema.set('toJSON', {
|
|||||||
|
|
||||||
listingVarientSchema.statics.recalculate = async function (listingVarient, user) {
|
listingVarientSchema.statics.recalculate = async function (listingVarient, user) {
|
||||||
const listingId = listingVarient?.listing?._id || listingVarient?.listing;
|
const listingId = listingVarient?.listing?._id || listingVarient?.listing;
|
||||||
|
const varientId = listingVarient?._id;
|
||||||
|
const productSkuId = toId(listingVarient?.productSku);
|
||||||
|
|
||||||
|
if (varientId && productSkuId && (await this.exists({ _id: varientId }))) {
|
||||||
|
let listing = listingVarient.listing;
|
||||||
|
if (!listing?.stockLocation) {
|
||||||
|
listing = await mongoose
|
||||||
|
.model('listing')
|
||||||
|
.findById(listingId)
|
||||||
|
.select('stockLocation product')
|
||||||
|
.lean();
|
||||||
|
}
|
||||||
|
const stockLocationId = toId(listing?.stockLocation);
|
||||||
|
if (stockLocationId) {
|
||||||
|
const stockRollup = await aggregateRollups({
|
||||||
|
model: mongoose.model('productStock'),
|
||||||
|
baseFilter: {
|
||||||
|
productSku: new mongoose.Types.ObjectId(productSkuId),
|
||||||
|
stockLocation: new mongoose.Types.ObjectId(stockLocationId),
|
||||||
|
},
|
||||||
|
rollupConfigs: [
|
||||||
|
{
|
||||||
|
name: 'stockQuantity',
|
||||||
|
rollups: [{ name: 'stockQuantity', property: 'currentQuantity', operation: 'sum' }],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
const stockQuantity = stockRollup.stockQuantity?.sum || 0;
|
||||||
|
if (listingVarient.stockQuantity !== stockQuantity) {
|
||||||
|
await editObject({
|
||||||
|
model: this,
|
||||||
|
id: varientId,
|
||||||
|
updateData: { stockQuantity },
|
||||||
|
user,
|
||||||
|
recalculate: false,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!listingId) {
|
if (!listingId) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user