The Purchase Order form never reached the server. Creating a PO with two or more "Manual Entry" rows fired N parallel POSTs to /api/collections/stock_items/records via Promise.all. The PocketBase JS SDK auto-cancels any in-flight request whose method + path match a newer one, so the first POST was aborted with: ClientResponseError 0: The request was autocancelled. Promise.all then rejected before the PO create ever ran, so the PO was never created - only an orphan stock item per attempt. Confirmed against the production PB logs: two stock_items POSTs today, zero purchase_orders POSTs, and two orphan stock_items rows with no PO. Fixes: - src/lib/pocketbase.ts: pb.autoCancellation(false) on the browser client. Every server-side client in this repo already did this (scripts/*.mjs, server/po-api.mjs) - the browser client was the one place it was missing. - PurchaseOrderForm: resolve rows sequentially instead of Promise.all, and build the snapshot in the same pass so manual rows carry the real stock item id instead of "". - PurchaseOrderForm: disable the submit button while submitting, so a double click cannot create two POs. - PurchaseOrderForm: compare SKUs trimmed, so a stray trailing space does not create a duplicate stock item. - po-photo-ingest.mjs, jei_skill.ts, setup-users.js: same autoCancellation(false) guard.
104 lines
3.1 KiB
JavaScript
104 lines
3.1 KiB
JavaScript
import PocketBase from 'pocketbase';
|
||
|
||
const pb = new PocketBase(process.env.VITE_PB_URL || 'http://127.0.0.1:8090');
|
||
// Never let the SDK auto-cancel a request (see src/lib/pocketbase.ts).
|
||
pb.autoCancellation(false);
|
||
|
||
async function ensureUsersCollection() {
|
||
try {
|
||
// If it exists, this will succeed
|
||
await pb.collections.getOne('users');
|
||
console.log('ℹ️ Users collection already exists');
|
||
return;
|
||
} catch (_) {
|
||
// Try create if not exists
|
||
try {
|
||
const usersCollection = await pb.collections.create({
|
||
name: 'users',
|
||
type: 'auth',
|
||
schema: [
|
||
{ name: 'name', type: 'text', required: false, options: { max: 100 } },
|
||
{ name: 'role', type: 'select', required: false, options: { maxSelect: 1, values: ['admin', 'manager', 'employee'] } },
|
||
{ name: 'active', type: 'bool', required: false },
|
||
],
|
||
// keep open for setup; tighten later in UI
|
||
listRule: null,
|
||
viewRule: null,
|
||
createRule: null,
|
||
updateRule: null,
|
||
deleteRule: null,
|
||
});
|
||
console.log('✅ Users collection created:', usersCollection.name);
|
||
} catch (err) {
|
||
console.error('❌ Error creating users collection:', err?.message || err);
|
||
}
|
||
}
|
||
}
|
||
|
||
async function ensureUser(email, data) {
|
||
try {
|
||
const existing = await pb.collection('users').getFirstListItem(`email = "${email}"`);
|
||
if (existing) {
|
||
console.log(`ℹ️ User already exists: ${email}`);
|
||
return existing;
|
||
}
|
||
} catch (_) {
|
||
// not found -> proceed to create
|
||
}
|
||
|
||
try {
|
||
const record = await pb.collection('users').create(data);
|
||
console.log(`✅ Created user: ${email}`);
|
||
return record;
|
||
} catch (err) {
|
||
// Double-check if created despite error
|
||
try {
|
||
const created = await pb.collection('users').getFirstListItem(`email = "${email}"`);
|
||
if (created) {
|
||
console.log(`✅ User is present after error (treated as success): ${email}`);
|
||
return created;
|
||
}
|
||
} catch (_) {}
|
||
console.error(`❌ Error creating user ${email}:`, err?.message || err);
|
||
throw err;
|
||
}
|
||
}
|
||
|
||
async function setupDemoUser() {
|
||
try {
|
||
console.log('🔐 Setting up demo user...');
|
||
|
||
// First authenticate as admin
|
||
await pb.admins.authWithPassword('david@wfsales.co.za', '1234567890');
|
||
console.log('✅ Admin authenticated');
|
||
|
||
await ensureUsersCollection();
|
||
|
||
await ensureUser('admin@jei.com', {
|
||
email: 'admin@jei.com',
|
||
password: 'password123',
|
||
passwordConfirm: 'password123',
|
||
name: 'Admin User',
|
||
role: 'admin',
|
||
active: true,
|
||
});
|
||
|
||
await ensureUser('manager@jei.com', {
|
||
email: 'manager@jei.com',
|
||
password: 'password123',
|
||
passwordConfirm: 'password123',
|
||
name: 'Manager User',
|
||
role: 'manager',
|
||
active: true,
|
||
});
|
||
|
||
console.log('\n🎉 Setup complete! You can now login with:');
|
||
console.log('Admin: admin@jei.com / password123');
|
||
console.log('Manager: manager@jei.com / password123');
|
||
|
||
} catch (error) {
|
||
console.error('❌ Setup failed:', error.message);
|
||
}
|
||
}
|
||
|
||
setupDemoUser();
|