bench
This commit is contained in:
789
scripts/benchmark/workload.js
Normal file
789
scripts/benchmark/workload.js
Normal file
@@ -0,0 +1,789 @@
|
||||
import sharp from 'sharp';
|
||||
|
||||
/**
|
||||
* Creates sample PNG image buffer.
|
||||
*/
|
||||
async function makeSampleImage(width = 200, height = 200, color = { r: 50, g: 120, b: 220 }) {
|
||||
return sharp({
|
||||
create: {
|
||||
width,
|
||||
height,
|
||||
channels: 4,
|
||||
background: { ...color, alpha: 1 },
|
||||
},
|
||||
})
|
||||
.png()
|
||||
.toBuffer();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates sample AVIF thumbnail buffer.
|
||||
*/
|
||||
async function makeSampleThumb(width = 64, height = 64) {
|
||||
return sharp({
|
||||
create: {
|
||||
width,
|
||||
height,
|
||||
channels: 4,
|
||||
background: { r: 200, g: 60, b: 60, alpha: 1 },
|
||||
},
|
||||
})
|
||||
.avif()
|
||||
.toBuffer();
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes Phase 1: Database Population / Fill.
|
||||
* Systematically calls creation and write APIs to populate the database
|
||||
* with realistic entities and relationships according to the configured scale.
|
||||
*/
|
||||
export async function fillDatabase(store, options = {}) {
|
||||
const scale = options.scale || 'small';
|
||||
const counts = {
|
||||
small: { categories: 6, articles: 18, entities: 6, manifests: 6 },
|
||||
medium: { categories: 15, articles: 60, entities: 20, manifests: 20 },
|
||||
large: { categories: 30, articles: 200, entities: 50, manifests: 60 },
|
||||
}[scale] || { categories: 6, articles: 18, entities: 6, manifests: 6 };
|
||||
|
||||
const ctx = {
|
||||
googleAuthId: null,
|
||||
company: null,
|
||||
secondaryGoogleAuthId: null,
|
||||
secondaryCompany: null,
|
||||
categories: [],
|
||||
articles: [],
|
||||
fatherArticles: [],
|
||||
childArticles: [],
|
||||
customergroups: [],
|
||||
entities: [],
|
||||
suppliers: [],
|
||||
deliveries: [],
|
||||
orders: [],
|
||||
quotes: [],
|
||||
terminals: [],
|
||||
sampleImageHash: null,
|
||||
sampleImageThumbHash: null,
|
||||
attachments: [],
|
||||
};
|
||||
|
||||
const sampleImage = await makeSampleImage();
|
||||
const sampleThumb = await makeSampleThumb();
|
||||
|
||||
// 1. Google Auth setup
|
||||
const primaryEmail = `benchmark.admin.${Date.now()}@example.com`;
|
||||
const secEmail = `benchmark.secondary.${Date.now()}@example.com`;
|
||||
|
||||
ctx.googleAuthId = await store.google_auth.add(primaryEmail);
|
||||
await store.google_auth.setProfile(ctx.googleAuthId, {
|
||||
sub: `sub-${ctx.googleAuthId}`,
|
||||
picture: 'https://example.com/pic.png',
|
||||
});
|
||||
await store.google_auth.listAllowedEmails();
|
||||
|
||||
ctx.secondaryGoogleAuthId = await store.google_auth.add(secEmail);
|
||||
|
||||
// 2. Company setup
|
||||
ctx.company = await store.company.create({
|
||||
name: `Bench Corp ${Date.now()}`,
|
||||
iso639: 'de',
|
||||
taxrate: 19,
|
||||
reducedtaxrate: 7,
|
||||
googleAuthId: ctx.googleAuthId,
|
||||
});
|
||||
await store.google_auth.setSelectedCompany(ctx.googleAuthId, ctx.company.id);
|
||||
|
||||
ctx.secondaryCompany = await store.company.create({
|
||||
name: `Secondary Corp ${Date.now()}`,
|
||||
iso639: 'en',
|
||||
taxrate: 20,
|
||||
reducedtaxrate: 10,
|
||||
googleAuthId: ctx.secondaryGoogleAuthId,
|
||||
});
|
||||
await store.google_auth.setSelectedCompany(ctx.secondaryGoogleAuthId, ctx.secondaryCompany.id);
|
||||
|
||||
await store.company.update(ctx.company.id, {
|
||||
name: `Bench Corp Updated ${Date.now()}`,
|
||||
iso639: 'de',
|
||||
taxrate: 19,
|
||||
reducedtaxrate: 7,
|
||||
});
|
||||
await store.company.list(ctx.googleAuthId);
|
||||
|
||||
// 3. Company Users
|
||||
const compUserId = await store.companyuser.add(ctx.company.id, ctx.secondaryGoogleAuthId);
|
||||
ctx.compUserId = compUserId;
|
||||
await store.companyuser.getByEmail(secEmail);
|
||||
|
||||
// 4. Lang APIs
|
||||
await store.lang.ensure('en');
|
||||
await store.lang.ensure('fr');
|
||||
await store.lang.create('es');
|
||||
await store.lang.getByIso639('en');
|
||||
await store.lang.list();
|
||||
|
||||
// 5. Tax APIs
|
||||
await store.tax.ensure(19);
|
||||
await store.tax.ensure(7);
|
||||
const taxIdSample = await store.tax.create(5.5);
|
||||
ctx.taxSampleId = taxIdSample;
|
||||
await store.tax.getByRate(19);
|
||||
await store.tax.list();
|
||||
|
||||
// 6. Unit APIs
|
||||
await store.unit.upsert(ctx.googleAuthId, {
|
||||
si: 'kg',
|
||||
basesi: 'g',
|
||||
basesifactor: 1000,
|
||||
symbol: 'kg',
|
||||
name: 'Kilogramm',
|
||||
});
|
||||
await store.unit.upsert(ctx.googleAuthId, {
|
||||
si: 'stk',
|
||||
basesi: 'stk',
|
||||
basesifactor: 1,
|
||||
symbol: 'Stk',
|
||||
name: 'Stück',
|
||||
});
|
||||
await store.unit.list(ctx.googleAuthId);
|
||||
|
||||
// 7. Company Settings
|
||||
await store.companysetting.set(ctx.googleAuthId, {
|
||||
key: 'ui.theme',
|
||||
value: 'dark',
|
||||
frontend: true,
|
||||
writeonly: false,
|
||||
});
|
||||
await store.companysetting.set(ctx.googleAuthId, {
|
||||
key: 'labelprinter.type',
|
||||
value: 'zebra',
|
||||
frontend: false,
|
||||
writeonly: false,
|
||||
});
|
||||
await store.companysetting.get(ctx.googleAuthId, 'ui.theme');
|
||||
await store.companysetting.list(ctx.googleAuthId);
|
||||
|
||||
// 8. Brand APIs
|
||||
const brand1 = await store.brand.upsert(ctx.googleAuthId, {
|
||||
name: 'BenchBrand Pro',
|
||||
gsprpinfo: 'Manufacturer Pro GmbH',
|
||||
});
|
||||
const brand2 = await store.brand.upsert(ctx.googleAuthId, {
|
||||
name: 'BenchBrand Ultra',
|
||||
gsprpinfo: 'Manufacturer Ultra AG',
|
||||
});
|
||||
ctx.brands = [brand1, brand2];
|
||||
await store.brand.list(ctx.googleAuthId);
|
||||
|
||||
// 9. Customer Groups
|
||||
const cgVip = await store.customergroup.create(ctx.googleAuthId, { name: 'VIP Members' });
|
||||
const cgRetail = await store.customergroup.create(ctx.googleAuthId, { name: 'Retail Customers' });
|
||||
await store.customergroup.update(ctx.googleAuthId, cgVip.id, { name: 'VIP Gold Members' });
|
||||
const allCgs = await store.customergroup.list(ctx.googleAuthId);
|
||||
await store.customergroup.order(ctx.googleAuthId, {
|
||||
customergroupIds: allCgs.map((g) => g.id).reverse(),
|
||||
});
|
||||
await store.customergroup.list(ctx.googleAuthId);
|
||||
ctx.customergroups.push(cgRetail, cgVip);
|
||||
|
||||
// 10. Categories Hierarchy
|
||||
const rootCatId = ctx.company.rootCategoryId;
|
||||
const numCats = counts.categories;
|
||||
|
||||
for (let i = 1; i <= numCats; i++) {
|
||||
const parentId = i > 3 && ctx.categories.length > 0 ? ctx.categories[(i % 3)].id : rootCatId;
|
||||
const cat = await store.category.createUnderParent({
|
||||
googleAuthId: ctx.googleAuthId,
|
||||
parentId,
|
||||
name: `Category ${i}`,
|
||||
});
|
||||
ctx.categories.push(cat);
|
||||
}
|
||||
|
||||
// Ensure by path
|
||||
const deepCatId = await store.category.ensureByPath({
|
||||
googleAuthId: ctx.googleAuthId,
|
||||
parentId: rootCatId,
|
||||
path: 'Hardware / Components / Processors',
|
||||
});
|
||||
ctx.deepCatId = deepCatId;
|
||||
|
||||
// Category manipulation APIs
|
||||
if (ctx.categories.length >= 2) {
|
||||
await store.category.rename({
|
||||
googleAuthId: ctx.googleAuthId,
|
||||
id: ctx.categories[0].id,
|
||||
name: 'Main Catalog Category',
|
||||
});
|
||||
const orderParent = await store.category.createUnderParent({
|
||||
googleAuthId: ctx.googleAuthId,
|
||||
parentId: rootCatId,
|
||||
name: 'Order Test Parent',
|
||||
});
|
||||
const oChild1 = await store.category.createUnderParent({
|
||||
googleAuthId: ctx.googleAuthId,
|
||||
parentId: orderParent.id,
|
||||
name: 'Order Child 1',
|
||||
});
|
||||
const oChild2 = await store.category.createUnderParent({
|
||||
googleAuthId: ctx.googleAuthId,
|
||||
parentId: orderParent.id,
|
||||
name: 'Order Child 2',
|
||||
});
|
||||
await store.category.move({
|
||||
googleAuthId: ctx.googleAuthId,
|
||||
id: oChild2.id,
|
||||
parentId: orderParent.id,
|
||||
});
|
||||
await store.category.order({
|
||||
googleAuthId: ctx.googleAuthId,
|
||||
parentId: orderParent.id,
|
||||
categoryIds: [oChild2.id, oChild1.id],
|
||||
});
|
||||
}
|
||||
|
||||
// Category image
|
||||
await store.category.addImage(ctx.googleAuthId, ctx.categories[0].id, sampleImage);
|
||||
|
||||
// 11. Numbers APIs
|
||||
const numList = await store.numbers.list(ctx.googleAuthId);
|
||||
if (numList.length > 0) {
|
||||
await store.numbers.update(ctx.googleAuthId, numList[0].id, {
|
||||
prefix: 'BN-',
|
||||
padding: 6,
|
||||
next: 1001,
|
||||
});
|
||||
}
|
||||
|
||||
// 12. POS Terminals
|
||||
const term1 = await store.posterminal.upsert(ctx.googleAuthId, {
|
||||
name: 'Counter Terminal 1',
|
||||
pairingpin: '1234',
|
||||
});
|
||||
const term2 = await store.posterminal.upsert(ctx.googleAuthId, {
|
||||
name: 'Mobile Terminal 2',
|
||||
pairingpin: '5678',
|
||||
});
|
||||
ctx.terminals.push(term1, term2);
|
||||
|
||||
await store.posterminal.setOn(ctx.googleAuthId, term1.id, ctx.categories[0].id);
|
||||
await store.posterminal.setOff(ctx.googleAuthId, term1.id, ctx.categories[0].id);
|
||||
await store.posterminal.setOnAll(ctx.googleAuthId, term1.id);
|
||||
await store.posterminal.setOffAll(ctx.googleAuthId, term1.id);
|
||||
await store.posterminal.getCategoryPosterminalIds(ctx.googleAuthId, ctx.categories[0].id);
|
||||
await store.posterminal.list(ctx.googleAuthId);
|
||||
|
||||
// 13. Entities (Customers)
|
||||
const numEntities = counts.entities;
|
||||
for (let i = 1; i <= numEntities; i++) {
|
||||
const nextNum = await store.entity.peekNextNumber(ctx.googleAuthId);
|
||||
await store.entity.isNumberFree(ctx.googleAuthId, nextNum);
|
||||
const ent = await store.entity.create(ctx.googleAuthId, {
|
||||
customergroupId: ctx.customergroups[i % ctx.customergroups.length].id,
|
||||
name: `Customer Company ${i}`,
|
||||
firstName: `Firstname ${i}`,
|
||||
});
|
||||
ctx.entities.push(ent);
|
||||
|
||||
// Entity Address
|
||||
const addr = await store.entityaddress.create(ctx.googleAuthId, ent.id, {
|
||||
addressType: 'shipping',
|
||||
name: `Branch ${i}`,
|
||||
street: `Main Street ${i}`,
|
||||
streetNumber: `${i}`,
|
||||
zip: '10115',
|
||||
city: 'Berlin',
|
||||
county: 'Berlin',
|
||||
sort: 1,
|
||||
});
|
||||
await store.entityaddress.update(ctx.googleAuthId, ent.id, addr.id, {
|
||||
street: `Updated Street ${i}`,
|
||||
});
|
||||
|
||||
// Entity Contact
|
||||
const contact = await store.entitycontact.create(ctx.googleAuthId, ent.id, {
|
||||
contactType: 'email',
|
||||
contact: `contact${i}@benchmark.test`,
|
||||
sort: 1,
|
||||
});
|
||||
await store.entitycontact.update(ctx.googleAuthId, ent.id, contact.id, {
|
||||
contact: `updated-contact${i}@benchmark.test`,
|
||||
});
|
||||
}
|
||||
|
||||
// 14. Suppliers
|
||||
for (let i = 1; i <= 3; i++) {
|
||||
const sup = await store.supplier.create(ctx.googleAuthId, {
|
||||
name: `Supplier Express ${i}`,
|
||||
});
|
||||
await store.supplier.update(ctx.googleAuthId, sup.id, {
|
||||
name: `Supplier Express ${i} GmbH`,
|
||||
});
|
||||
ctx.suppliers.push(sup);
|
||||
}
|
||||
await store.supplier.list(ctx.googleAuthId);
|
||||
|
||||
// 15. Articles
|
||||
const numArticles = counts.articles;
|
||||
for (let i = 1; i <= numArticles; i++) {
|
||||
const targetCat = ctx.categories[i % ctx.categories.length];
|
||||
const isFather = i % 4 === 1;
|
||||
const art = await store.article.createUnderParent({
|
||||
googleAuthId: ctx.googleAuthId,
|
||||
parentId: targetCat.id,
|
||||
name: `Bench Article ${i}`,
|
||||
});
|
||||
|
||||
const sku = art.sku;
|
||||
ctx.articles.push(art);
|
||||
|
||||
// Update article details
|
||||
await store.article.updateBySku(ctx.googleAuthId, sku, {
|
||||
name: `Bench Article ${i} Pro`,
|
||||
unitSi: 'stk',
|
||||
unitamount: 1,
|
||||
});
|
||||
|
||||
// Prices
|
||||
await store.article.setPricesBySku(ctx.googleAuthId, sku, [
|
||||
{ price: 10 + i * 2.5, tax: 19, minmultiplier: 1 },
|
||||
{ price: 8 + i * 2.5, tax: 19, minmultiplier: 5 },
|
||||
]);
|
||||
|
||||
// EANs
|
||||
const ean = `4012345${String(i).padStart(6, '0')}`;
|
||||
await store.article.setEansBySku(ctx.googleAuthId, sku, [ean]);
|
||||
|
||||
// Brand
|
||||
await store.article.setBrandIdBySku(ctx.googleAuthId, sku, ctx.brands[i % ctx.brands.length].id);
|
||||
|
||||
// Weight
|
||||
await store.article.setWeightBySku(ctx.googleAuthId, sku, 0.25 * i);
|
||||
|
||||
// Categories
|
||||
await store.article.setCategoryIdsBySku(ctx.googleAuthId, sku, [
|
||||
targetCat.id,
|
||||
ctx.categories[(i + 1) % ctx.categories.length].id,
|
||||
]);
|
||||
|
||||
// V/K Father-Child hierarchy
|
||||
if (isFather) {
|
||||
ctx.fatherArticles.push(art);
|
||||
} else if (ctx.fatherArticles.length > 0) {
|
||||
const parentFather = ctx.fatherArticles[ctx.fatherArticles.length - 1];
|
||||
await store.article.setFatherBySku(ctx.googleAuthId, sku, parentFather.sku);
|
||||
ctx.childArticles.push(art);
|
||||
}
|
||||
|
||||
// Add image on select articles
|
||||
if (i <= 3) {
|
||||
const imgRes = await store.article.addImage(ctx.googleAuthId, sku, sampleImage);
|
||||
ctx.sampleImageHash = imgRes.fullHash;
|
||||
ctx.sampleImageThumbHash = imgRes.thumbHash;
|
||||
await store.article.orderImages(ctx.googleAuthId, sku, {
|
||||
fullHashes: [imgRes.fullHash],
|
||||
});
|
||||
}
|
||||
|
||||
// Article Suppliers
|
||||
if (ctx.suppliers.length > 0) {
|
||||
const sup = ctx.suppliers[i % ctx.suppliers.length];
|
||||
const artSup = await store.articlesupplier.create(ctx.googleAuthId, sku, {
|
||||
entityId: sup.id,
|
||||
sku: `SUP-SKU-${i}`,
|
||||
pu: 1,
|
||||
stock: 100,
|
||||
sort: 1,
|
||||
netPrice: 7.5 + i,
|
||||
taxId: ctx.company.taxrateId,
|
||||
});
|
||||
await store.articlesupplier.update(ctx.googleAuthId, sku, artSup.id, {
|
||||
stock: 120,
|
||||
pu: 2,
|
||||
});
|
||||
await store.articlesupplier.order(ctx.googleAuthId, sku, {
|
||||
ids: [artSup.id],
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// 16. Article Import Rows API
|
||||
const importRows = [
|
||||
{
|
||||
sku: `IMP-${Date.now()}-1`,
|
||||
name: 'Imported Keyboard Model X',
|
||||
vk: 'V',
|
||||
parentCategory: 'Hardware / Components / Processors',
|
||||
brand: 'BenchBrand Pro',
|
||||
net: '45,50',
|
||||
tax: 19,
|
||||
eans: [`4262557${String(Date.now()).slice(-6)}`],
|
||||
},
|
||||
{
|
||||
sku: `IMP-${Date.now()}-2`,
|
||||
name: 'Imported Keyboard Variant Black',
|
||||
vk: 'K',
|
||||
parentCategory: 'Hardware / Components / Processors',
|
||||
brand: 'BenchBrand Pro',
|
||||
net: '45,50',
|
||||
tax: 19,
|
||||
fatherSku: `IMP-${Date.now()}-1`,
|
||||
},
|
||||
];
|
||||
await store.article.importRows({
|
||||
googleAuthId: ctx.googleAuthId,
|
||||
rows: importRows,
|
||||
});
|
||||
|
||||
// 17. Manifests: Quotes, Orders, Deliveries
|
||||
const numManifests = counts.manifests;
|
||||
for (let i = 1; i <= numManifests; i++) {
|
||||
const ent = ctx.entities[i % ctx.entities.length];
|
||||
const sup = ctx.suppliers[i % ctx.suppliers.length];
|
||||
const art = ctx.articles[i % ctx.articles.length];
|
||||
|
||||
// Quote
|
||||
const quote = await store.quote.create(ctx.googleAuthId, {
|
||||
number: `QUO-${Date.now()}-${i}`,
|
||||
date: new Date().toISOString(),
|
||||
entityId: ent.id,
|
||||
externalNumber: `EXT-Q-${i}`,
|
||||
lines: [
|
||||
{
|
||||
sku: art.sku,
|
||||
name: `Item ${art.sku}`,
|
||||
amount: 2,
|
||||
net: 25.0,
|
||||
pu: 1,
|
||||
rebate: 0,
|
||||
taxrate: 19,
|
||||
comment: 'Standard quote item',
|
||||
},
|
||||
],
|
||||
});
|
||||
await store.quote.update(ctx.googleAuthId, quote.id, {
|
||||
externalNumber: `EXT-Q-${i}-UPDATED`,
|
||||
});
|
||||
ctx.quotes.push(quote);
|
||||
|
||||
// Order
|
||||
const order = await store.order.create(ctx.googleAuthId, {
|
||||
number: `ORD-${Date.now()}-${i}`,
|
||||
date: new Date().toISOString(),
|
||||
entityId: ent.id,
|
||||
externalNumber: `EXT-O-${i}`,
|
||||
lines: [
|
||||
{
|
||||
sku: art.sku,
|
||||
name: `Item ${art.sku}`,
|
||||
amount: 5,
|
||||
net: 25.0,
|
||||
pu: 1,
|
||||
rebate: 5,
|
||||
taxrate: 19,
|
||||
comment: 'Expedited delivery order',
|
||||
},
|
||||
],
|
||||
});
|
||||
await store.order.update(ctx.googleAuthId, order.id, {
|
||||
externalNumber: `EXT-O-${i}-CONFIRMED`,
|
||||
});
|
||||
ctx.orders.push(order);
|
||||
|
||||
// Delivery with attached files
|
||||
const delivery = await store.delivery.create(ctx.googleAuthId, {
|
||||
supplierId: sup.id,
|
||||
externalNumber: `DEL-${Date.now()}-${i}`,
|
||||
date: new Date().toISOString(),
|
||||
lines: [
|
||||
{
|
||||
sku: art.sku,
|
||||
name: `Delivery Item ${art.sku}`,
|
||||
amount: 50,
|
||||
net: 15.0,
|
||||
pu: 1,
|
||||
rebate: 0,
|
||||
taxrate: 19,
|
||||
comment: 'Warehouse receipt',
|
||||
},
|
||||
],
|
||||
files: i === 1 ? [
|
||||
{
|
||||
name: 'packing-slip.txt',
|
||||
mimetype: 'text/plain',
|
||||
content: Buffer.from(`Packing slip details for delivery ${i}`),
|
||||
},
|
||||
] : [],
|
||||
});
|
||||
await store.delivery.update(ctx.googleAuthId, delivery.id, {
|
||||
externalNumber: `DEL-${Date.now()}-${i}-STOCKED`,
|
||||
});
|
||||
ctx.deliveries.push(delivery);
|
||||
}
|
||||
|
||||
// 18. Manifest Attachments (file storage API)
|
||||
if (ctx.deliveries.length > 0) {
|
||||
const primaryManifest = ctx.deliveries[0];
|
||||
const attach1 = await store.manifestattachment.add(ctx.googleAuthId, primaryManifest.id, {
|
||||
name: 'invoice.pdf',
|
||||
mimetype: 'application/pdf',
|
||||
content: Buffer.from('%PDF-1.4 ... benchmark dummy pdf content ...'),
|
||||
thumbavif: sampleThumb,
|
||||
thumbw: 64,
|
||||
thumbh: 64,
|
||||
});
|
||||
const attach2 = await store.manifestattachment.add(ctx.googleAuthId, primaryManifest.id, {
|
||||
name: 'quality-report.txt',
|
||||
mimetype: 'text/plain',
|
||||
content: Buffer.from('Quality inspection passed successfully.'),
|
||||
});
|
||||
const currentList = await store.manifestattachment.listByManifestId(
|
||||
ctx.googleAuthId,
|
||||
primaryManifest.id,
|
||||
);
|
||||
await store.manifestattachment.order(ctx.googleAuthId, primaryManifest.id, {
|
||||
ids: currentList.map((a) => a.id).reverse(),
|
||||
});
|
||||
ctx.attachments.push({ manifestId: primaryManifest.id, ...attach1 });
|
||||
}
|
||||
|
||||
return ctx;
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes Phase 2: Filled Database Performance Benchmark.
|
||||
* Runs read, query, search, and lookup APIs against the populated database
|
||||
* over multiple iterations to measure realistic data access speeds.
|
||||
*/
|
||||
export async function benchmarkFilledDatabase(store, ctx, options = {}) {
|
||||
const iterations = options.iterations || 5;
|
||||
|
||||
for (let iter = 0; iter < iterations; iter++) {
|
||||
// 1. Category Tree & Articles
|
||||
await store.category.getTreeForCompany(ctx.googleAuthId);
|
||||
if (ctx.categories.length > 0) {
|
||||
await store.category.getCategoryArticles(ctx.googleAuthId, ctx.categories[0].id);
|
||||
}
|
||||
|
||||
// 2. Article Catalog Read APIs
|
||||
await store.article.listSearchIndex(ctx.googleAuthId);
|
||||
await store.article.listExport(ctx.googleAuthId);
|
||||
if (ctx.categories.length > 0) {
|
||||
await store.article.listExport(ctx.googleAuthId, ctx.categories[0].id);
|
||||
}
|
||||
|
||||
// Article SKU lookups & history
|
||||
if (ctx.articles.length > 0) {
|
||||
const sampleSku = ctx.articles[iter % ctx.articles.length].sku;
|
||||
await store.article.getBySku(ctx.googleAuthId, sampleSku);
|
||||
await store.article.getHistoryBySku(ctx.googleAuthId, sampleSku);
|
||||
}
|
||||
|
||||
// 3. Article Supplier Lookups
|
||||
if (ctx.articles.length > 0) {
|
||||
const sampleSku = ctx.articles[iter % ctx.articles.length].sku;
|
||||
await store.articlesupplier.listByArticleSku(ctx.googleAuthId, sampleSku);
|
||||
if (ctx.suppliers.length > 0) {
|
||||
await store.articlesupplier.listByEntityAndSkus(ctx.googleAuthId, {
|
||||
supplierId: ctx.suppliers[0].id,
|
||||
skus: [sampleSku],
|
||||
});
|
||||
await store.articlesupplier.listBySupplierAndSkus(ctx.googleAuthId, {
|
||||
supplierId: ctx.suppliers[0].id,
|
||||
skus: [sampleSku],
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// 4. Pic & Thumbnail Reads
|
||||
if (ctx.sampleImageHash) {
|
||||
await store.pic.getImageByHash(ctx.googleAuthId, ctx.sampleImageHash);
|
||||
await store.pic.getThumbByHash(ctx.googleAuthId, ctx.sampleImageHash);
|
||||
}
|
||||
|
||||
// 5. Entities (Customers) Lookups
|
||||
await store.entity.list(ctx.googleAuthId);
|
||||
if (ctx.customergroups.length > 0) {
|
||||
await store.entity.list(ctx.googleAuthId, { customergroupId: ctx.customergroups[0].id });
|
||||
}
|
||||
if (ctx.entities.length > 0) {
|
||||
const sampleEnt = ctx.entities[iter % ctx.entities.length];
|
||||
await store.entity.getById(ctx.googleAuthId, sampleEnt.id);
|
||||
await store.entityaddress.list(ctx.googleAuthId, sampleEnt.id);
|
||||
await store.entitycontact.list(ctx.googleAuthId, sampleEnt.id);
|
||||
}
|
||||
|
||||
// 6. Suppliers Lookups
|
||||
await store.supplier.list(ctx.googleAuthId);
|
||||
|
||||
// 7. Manifests Lookups (Delivery, Order, Quote)
|
||||
await store.delivery.list(ctx.googleAuthId);
|
||||
if (ctx.deliveries.length > 0) {
|
||||
const sampleDel = ctx.deliveries[iter % ctx.deliveries.length];
|
||||
await store.delivery.getById(ctx.googleAuthId, sampleDel.id);
|
||||
}
|
||||
|
||||
await store.order.list(ctx.googleAuthId);
|
||||
if (ctx.orders.length > 0) {
|
||||
const sampleOrd = ctx.orders[iter % ctx.orders.length];
|
||||
await store.order.getById(ctx.googleAuthId, sampleOrd.id);
|
||||
}
|
||||
|
||||
await store.quote.list(ctx.googleAuthId);
|
||||
if (ctx.quotes.length > 0) {
|
||||
const sampleQuo = ctx.quotes[iter % ctx.quotes.length];
|
||||
await store.quote.getById(ctx.googleAuthId, sampleQuo.id);
|
||||
}
|
||||
|
||||
// 8. Manifest Attachments
|
||||
if (ctx.attachments.length > 0) {
|
||||
const sampleAttach = ctx.attachments[0];
|
||||
await store.manifestattachment.listByManifestId(ctx.googleAuthId, sampleAttach.manifestId);
|
||||
await store.manifestattachment.getById(ctx.googleAuthId, sampleAttach.manifestId, sampleAttach.id);
|
||||
}
|
||||
|
||||
// 9. Auth & Admin Queries
|
||||
await store.google_auth.getById(ctx.googleAuthId);
|
||||
await store.google_auth.getByEmail(`benchmark.admin.${ctx.googleAuthId}`); // may return undefined or auth object
|
||||
await store.companysetting.list(ctx.googleAuthId);
|
||||
await store.posterminal.list(ctx.googleAuthId);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes Phase 3: Lifecycle & Deletion APIs.
|
||||
* Uses dedicated throwaway test items to exercise all delete and removal APIs
|
||||
* without destroying the core benchmarked dataset.
|
||||
*/
|
||||
export async function testLifecycleDeletions(store, ctx) {
|
||||
const sampleImage = await makeSampleImage(80, 80, { r: 180, g: 80, b: 80 });
|
||||
|
||||
// 1. Temporary Category with Image & Delete
|
||||
const tempCat = await store.category.createUnderParent({
|
||||
googleAuthId: ctx.googleAuthId,
|
||||
parentId: ctx.company.rootCategoryId,
|
||||
name: 'Temporary Cat for Delete',
|
||||
});
|
||||
await store.category.addImage(ctx.googleAuthId, tempCat.id, sampleImage);
|
||||
await store.category.deleteImage(ctx.googleAuthId, tempCat.id);
|
||||
await store.category.delete({ googleAuthId: ctx.googleAuthId, id: tempCat.id });
|
||||
|
||||
// 2. Temporary Article with Image & Delete
|
||||
const tempArt = await store.article.createUnderParent({
|
||||
googleAuthId: ctx.googleAuthId,
|
||||
parentId: ctx.categories[0].id,
|
||||
name: 'Temporary Article for Delete',
|
||||
});
|
||||
const artImg = await store.article.addImage(ctx.googleAuthId, tempArt.sku, sampleImage);
|
||||
await store.article.deleteImage(ctx.googleAuthId, tempArt.sku, artImg.fullHash);
|
||||
|
||||
// Article Supplier Delete
|
||||
if (ctx.suppliers.length > 0) {
|
||||
const tempArtSup = await store.articlesupplier.create(ctx.googleAuthId, tempArt.sku, {
|
||||
entityId: ctx.suppliers[0].id,
|
||||
sku: 'TEMP-SUP-SKU',
|
||||
});
|
||||
await store.articlesupplier.delete(ctx.googleAuthId, tempArt.sku, tempArtSup.id);
|
||||
}
|
||||
await store.article.delete(ctx.googleAuthId, tempArt.sku);
|
||||
|
||||
// 3. Manifest Attachment Remove
|
||||
if (ctx.deliveries.length > 0) {
|
||||
const tempAttach = await store.manifestattachment.add(ctx.googleAuthId, ctx.deliveries[0].id, {
|
||||
name: 'delete-me.txt',
|
||||
mimetype: 'text/plain',
|
||||
content: Buffer.from('temp file to remove'),
|
||||
});
|
||||
await store.manifestattachment.remove(ctx.googleAuthId, ctx.deliveries[0].id, tempAttach.id);
|
||||
}
|
||||
|
||||
// 4. Temporary Delivery, Order, Quote Delete
|
||||
if (ctx.suppliers.length > 0) {
|
||||
const tempDel = await store.delivery.create(ctx.googleAuthId, {
|
||||
supplierId: ctx.suppliers[0].id,
|
||||
date: new Date().toISOString(),
|
||||
lines: [{ name: 'Temp item', amount: 1, net: 10, taxrate: 19 }],
|
||||
});
|
||||
await store.delivery.delete(ctx.googleAuthId, tempDel.id);
|
||||
}
|
||||
|
||||
const tempOrd = await store.order.create(ctx.googleAuthId, {
|
||||
number: `TEMP-ORD-${Date.now()}`,
|
||||
date: new Date().toISOString(),
|
||||
lines: [{ name: 'Temp item', amount: 1, net: 10, taxrate: 19 }],
|
||||
});
|
||||
await store.order.delete(ctx.googleAuthId, tempOrd.id);
|
||||
|
||||
const tempQuo = await store.quote.create(ctx.googleAuthId, {
|
||||
number: `TEMP-QUO-${Date.now()}`,
|
||||
date: new Date().toISOString(),
|
||||
lines: [{ name: 'Temp item', amount: 1, net: 10, taxrate: 19 }],
|
||||
});
|
||||
await store.quote.delete(ctx.googleAuthId, tempQuo.id);
|
||||
|
||||
// 5. Temporary Entity with Contact & Address Delete
|
||||
const tempEnt = await store.entity.create(ctx.googleAuthId, {
|
||||
customergroupId: ctx.customergroups[0].id,
|
||||
name: 'Temporary Delete Entity',
|
||||
});
|
||||
const tempAddr = await store.entityaddress.create(ctx.googleAuthId, tempEnt.id, {
|
||||
addressType: 'billing',
|
||||
street: 'Temp St',
|
||||
});
|
||||
await store.entityaddress.delete(ctx.googleAuthId, tempEnt.id, tempAddr.id);
|
||||
|
||||
const tempContact = await store.entitycontact.create(ctx.googleAuthId, tempEnt.id, {
|
||||
contactType: 'phone',
|
||||
contact: '+4912345678',
|
||||
});
|
||||
await store.entitycontact.delete(ctx.googleAuthId, tempEnt.id, tempContact.id);
|
||||
await store.entity.delete(ctx.googleAuthId, tempEnt.id);
|
||||
|
||||
// 6. Temporary Supplier Delete
|
||||
const tempSup = await store.supplier.create(ctx.googleAuthId, { name: 'Temp Sup for Delete' });
|
||||
await store.supplier.delete(ctx.googleAuthId, tempSup.id);
|
||||
|
||||
// 7. Temporary Customergroup Delete
|
||||
const tempCg = await store.customergroup.create(ctx.googleAuthId, { name: 'Temp CG Delete' });
|
||||
await store.customergroup.delete(ctx.googleAuthId, tempCg.id);
|
||||
|
||||
// 8. Temporary Brand Delete
|
||||
const tempBrand = await store.brand.upsert(ctx.googleAuthId, { name: `TempBrand-${Date.now()}` });
|
||||
await store.brand.delete(ctx.googleAuthId, tempBrand.id);
|
||||
|
||||
// 9. Temporary Unit Delete
|
||||
const tempUnitSi = `tunit-${Date.now()}`.slice(0, 15);
|
||||
await store.unit.upsert(ctx.googleAuthId, {
|
||||
si: tempUnitSi,
|
||||
basesi: tempUnitSi,
|
||||
basesifactor: 1,
|
||||
symbol: 'tu',
|
||||
name: 'Temp Unit',
|
||||
});
|
||||
await store.unit.delete(ctx.googleAuthId, tempUnitSi);
|
||||
|
||||
// 10. Temporary Terminal Delete
|
||||
const tempTerm = await store.posterminal.upsert(ctx.googleAuthId, {
|
||||
name: 'Temp Terminal Delete',
|
||||
pairingpin: '9999',
|
||||
});
|
||||
await store.posterminal.delete(ctx.googleAuthId, tempTerm.id);
|
||||
|
||||
// 11. Company User Delete
|
||||
if (ctx.compUserId) {
|
||||
await store.companyuser.delete(ctx.compUserId);
|
||||
}
|
||||
|
||||
// 12. Allowed Email Remove
|
||||
const tempEmail = `bench.remove.${Date.now()}@example.com`;
|
||||
await store.google_auth.add(tempEmail);
|
||||
await store.google_auth.removeAllowedEmail(tempEmail);
|
||||
|
||||
// 13. Lang Delete
|
||||
const tempLangId = await store.lang.create('nl');
|
||||
await store.lang.delete(tempLangId);
|
||||
|
||||
// 14. Secondary Company Delete
|
||||
if (ctx.secondaryCompany) {
|
||||
await store.company.delete(ctx.secondaryCompany.id);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user