204 lines
7.5 KiB
TypeScript
204 lines
7.5 KiB
TypeScript
import { PrintJob } from '$lib/models/PrintJob';
|
|
import { Spool } from '$lib/models/Spool';
|
|
import { Printer } from '$lib/models/Printer';
|
|
import { connectDB } from '$lib/server/db';
|
|
import type { PageServerLoad, Actions } from './$types';
|
|
import { fail, redirect } from '@sveltejs/kit';
|
|
|
|
export const load: PageServerLoad = async ({ locals }) => {
|
|
if (!locals.user) throw redirect(303, '/login');
|
|
|
|
await connectDB();
|
|
|
|
// Fetch prints with populated fields (Spool and Printer) - filtered by user
|
|
const prints = await PrintJob.find({ user_id: locals.user.id })
|
|
.populate('spool_id', 'brand material color_hex')
|
|
.populate('printer_id', 'name model')
|
|
.sort({ date: -1 })
|
|
.lean();
|
|
|
|
// Fetch active spools and printers for the "Log Print" form - filtered by user
|
|
const [spools, printers] = await Promise.all([
|
|
Spool.find({ user_id: locals.user.id, is_active: true }).lean(),
|
|
Printer.find({ user_id: locals.user.id }).lean()
|
|
]);
|
|
|
|
return {
|
|
prints: JSON.parse(JSON.stringify(prints)),
|
|
spools: JSON.parse(JSON.stringify(spools)),
|
|
printers: JSON.parse(JSON.stringify(printers))
|
|
};
|
|
};
|
|
|
|
export const actions: Actions = {
|
|
log: async ({ request, locals }) => {
|
|
if (!locals.user) return fail(401, { unauthorized: true });
|
|
|
|
const formData = await request.formData();
|
|
const name = formData.get('name');
|
|
const spool_id = formData.get('spool_id');
|
|
const printer_id = formData.get('printer_id');
|
|
const duration_minutes = formData.get('duration_minutes');
|
|
const filament_used_g = formData.get('filament_used_g');
|
|
const status = formData.get('status');
|
|
const manual_cost = formData.get('manual_cost');
|
|
const elapsed_minutes = formData.get('elapsed_minutes');
|
|
|
|
if (!spool_id || !printer_id || !filament_used_g) {
|
|
return fail(400, { missing: true });
|
|
}
|
|
|
|
await connectDB();
|
|
|
|
try {
|
|
// 1. Get the spool to calculate cost and deduct weight
|
|
const spool = await Spool.findOne({ _id: spool_id, user_id: locals.user.id });
|
|
if (!spool) return fail(404, { spoolNotFound: true });
|
|
|
|
// Verify printer belongs to user
|
|
const printer = await Printer.findOne({ _id: printer_id, user_id: locals.user.id });
|
|
if (!printer) return fail(404, { printerNotFound: true });
|
|
|
|
const weightUsed = Number(filament_used_g);
|
|
|
|
// Calculate Cost: use manual if provided, otherwise calculate
|
|
let costFilament: number;
|
|
if (manual_cost && String(manual_cost).trim() !== '') {
|
|
costFilament = Number(manual_cost);
|
|
} else {
|
|
costFilament = (spool.price / spool.weight_initial_g) * weightUsed;
|
|
}
|
|
|
|
// 2. Create Print Job
|
|
const isInProgress = status === 'In Progress';
|
|
|
|
// Calculate started_at based on elapsed time
|
|
let startedAt: Date | null = null;
|
|
if (isInProgress) {
|
|
const elapsedMs = Number(elapsed_minutes || 0) * 60 * 1000;
|
|
startedAt = new Date(Date.now() - elapsedMs);
|
|
}
|
|
|
|
await PrintJob.create({
|
|
user_id: locals.user.id,
|
|
name: name || 'Untitled Print',
|
|
spool_id,
|
|
printer_id,
|
|
duration_minutes: Number(duration_minutes),
|
|
filament_used_g: weightUsed,
|
|
calculated_cost_filament: Number(costFilament.toFixed(2)),
|
|
status,
|
|
started_at: startedAt,
|
|
date: new Date()
|
|
});
|
|
|
|
// 3. Deduct Filament from Spool (only if not In Progress)
|
|
if (!isInProgress) {
|
|
spool.weight_remaining_g = Math.max(0, spool.weight_remaining_g - weightUsed);
|
|
await spool.save();
|
|
}
|
|
|
|
return { success: true };
|
|
} catch (error) {
|
|
console.error(error);
|
|
return fail(500, { dbError: true });
|
|
}
|
|
},
|
|
|
|
edit: async ({ request, locals }) => {
|
|
if (!locals.user) return fail(401, { unauthorized: true });
|
|
|
|
const formData = await request.formData();
|
|
const id = formData.get('id');
|
|
const name = formData.get('name');
|
|
const duration_minutes = formData.get('duration_minutes');
|
|
const filament_used_g = formData.get('filament_used_g');
|
|
const status = formData.get('status');
|
|
const manual_cost = formData.get('manual_cost');
|
|
const elapsed_minutes = formData.get('elapsed_minutes');
|
|
const printer_id = formData.get('printer_id');
|
|
const spool_id = formData.get('spool_id');
|
|
|
|
if (!id || !name) {
|
|
return fail(400, { missing: true });
|
|
}
|
|
|
|
await connectDB();
|
|
|
|
try {
|
|
const printJob = await PrintJob.findOne({ _id: id, user_id: locals.user.id }).populate('spool_id');
|
|
if (!printJob) return fail(404, { notFound: true });
|
|
|
|
const weightUsed = Number(filament_used_g);
|
|
|
|
// Calculate Cost: use manual if provided, otherwise calculate
|
|
let costFilament: number;
|
|
if (manual_cost && String(manual_cost).trim() !== '') {
|
|
costFilament = Number(manual_cost);
|
|
} else if (printJob.spool_id?.price && printJob.spool_id?.weight_initial_g) {
|
|
costFilament = (printJob.spool_id.price / printJob.spool_id.weight_initial_g) * weightUsed;
|
|
} else {
|
|
costFilament = printJob.calculated_cost_filament || 0;
|
|
}
|
|
|
|
// Calculate started_at based on elapsed time for In Progress
|
|
const isInProgress = status === 'In Progress';
|
|
let startedAt = printJob.started_at;
|
|
|
|
if (isInProgress && elapsed_minutes) {
|
|
const elapsedMs = Number(elapsed_minutes) * 60 * 1000;
|
|
startedAt = new Date(Date.now() - elapsedMs);
|
|
} else if (!isInProgress) {
|
|
startedAt = null;
|
|
}
|
|
|
|
// Build update object
|
|
const updateData: any = {
|
|
name,
|
|
duration_minutes: Number(duration_minutes),
|
|
filament_used_g: weightUsed,
|
|
calculated_cost_filament: Number(costFilament.toFixed(2)),
|
|
status,
|
|
started_at: startedAt
|
|
};
|
|
|
|
// Update printer/spool if provided (for In Progress)
|
|
if (printer_id) {
|
|
updateData.printer_id = printer_id;
|
|
}
|
|
if (spool_id) {
|
|
updateData.spool_id = spool_id;
|
|
}
|
|
|
|
await PrintJob.findOneAndUpdate(
|
|
{ _id: id, user_id: locals.user.id },
|
|
updateData
|
|
);
|
|
|
|
return { success: true };
|
|
} catch (error) {
|
|
console.error(error);
|
|
return fail(500, { dbError: true });
|
|
}
|
|
},
|
|
|
|
delete: async ({ request, locals }) => {
|
|
if (!locals.user) return fail(401, { unauthorized: true });
|
|
|
|
const formData = await request.formData();
|
|
const id = formData.get('id');
|
|
|
|
if (!id) return fail(400, { missing: true });
|
|
|
|
await connectDB();
|
|
|
|
try {
|
|
await PrintJob.findOneAndDelete({ _id: id, user_id: locals.user.id });
|
|
return { success: true };
|
|
} catch (error) {
|
|
console.error(error);
|
|
return fail(500, { dbError: true });
|
|
}
|
|
}
|
|
};
|