This commit is contained in:
2025-10-21 22:20:26 +02:00
parent 5809e6c44c
commit eb33f47071
10 changed files with 345 additions and 92 deletions

View File

@@ -1,8 +0,0 @@
# backend/Dockerfile
FROM node:18-alpine
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY . .
EXPOSE 3002
CMD ["node", "dist/server.js"]

View File

@@ -1,61 +0,0 @@
# Multi-stage Dockerfile for Node.js + Python application
FROM node:20-alpine AS node-base
# Install Python and build dependencies in Node stage
RUN apk add --no-cache \
python3 \
py3-pip \
build-base \
python3-dev
# Install Python dependencies
COPY python-scripts/requirements.txt /tmp/requirements.txt
RUN pip3 install --no-cache-dir -r /tmp/requirements.txt
# Set working directory
WORKDIR /app
# Copy package files
COPY package*.json ./
# Install Node.js dependencies
RUN npm ci --only=production
# Build stage
FROM node-base AS builder
# Install all dependencies (including dev dependencies)
RUN npm ci
# Copy source code
COPY . .
# Build the application
RUN npm run build
# Production stage
FROM node-base AS production
# Copy built application from builder stage
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/package*.json ./
# Copy Python scripts
COPY --from=builder /app/python-scripts ./python-scripts
# Create non-root user
RUN addgroup -g 1001 -S nodejs && \
adduser -S nextjs -u 1001
# Change to non-root user
USER nextjs
# Expose port
EXPOSE 3000
# Health check
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
CMD node dist/health-check.js
# Start the application
CMD ["npm", "start"]

View File

@@ -6,7 +6,11 @@
"dev": "npm run build && npx tsx src/server.ts",
"build": "tsc",
"start": "node dist/server.js",
"prestart": "npm run build"
"prestart": "npm run build",
"test": "jest",
"test:python": "python3 -c \"from ortools.sat.python import cp_model; print('OR-Tools OK')\"",
"docker:build": "docker build -t schichtplan-backend .",
"docker:run": "docker run -p 3001:3001 schichtplan-backend"
},
"dependencies": {
"@types/bcrypt": "^6.0.0",

View File

@@ -102,7 +102,6 @@ export const AVAILABILITY_PREFERENCES = {
} as const;
// Default availability for new employees (all shifts unavailable as level 3)
// UPDATED: Now uses shiftId instead of timeSlotId + dayOfWeek
export function createDefaultAvailabilities(employeeId: string, planId: string, shiftIds: string[]): Omit<EmployeeAvailability, 'id'>[] {
const availabilities: Omit<EmployeeAvailability, 'id'>[] = [];
@@ -120,7 +119,6 @@ export function createDefaultAvailabilities(employeeId: string, planId: string,
}
// Create complete manager availability for all days (default: only Mon-Tue available)
// NOTE: This function might need revision based on new schema requirements
export function createManagerDefaultSchedule(managerId: string, planId: string, timeSlotIds: string[]): Omit<ManagerAvailability, 'id'>[] {
const assignments: Omit<ManagerAvailability, 'id'>[] = [];

View File

@@ -0,0 +1,27 @@
import { spawn } from 'child_process';
import path from 'path';
export function runPythonScript(scriptPath, args = []) {
return new Promise((resolve, reject) => {
const pythonProcess = spawn('python3', [scriptPath, ...args]);
let stdout = '';
let stderr = '';
pythonProcess.stdout.on('data', (data) => {
stdout += data.toString();
});
pythonProcess.stderr.on('data', (data) => {
stderr += data.toString();
});
pythonProcess.on('close', (code) => {
if (code === 0) {
resolve(stdout);
} else {
reject(new Error(`Python script exited with code ${code}: ${stderr}`));
}
});
});
}