Add bulk vehicle repair functionality in Falukant module

- Implemented a new repairAllVehicles method in FalukantService to handle the repair of multiple vehicles at once, including cost calculation and precondition checks.
- Updated FalukantController to expose the repairAllVehicles endpoint, allowing users to initiate bulk repairs via the API.
- Enhanced FalukantRouter to include a new route for bulk vehicle repairs.
- Modified BranchView component to add UI elements for repairing all vehicles, including a dialog for confirmation and displaying repair details.
- Updated German localization files to include translations related to bulk vehicle repair actions, improving user experience for German-speaking users.
This commit is contained in:
Torsten Schulz (local)
2025-12-08 08:36:21 +01:00
parent b1d29f2083
commit fadc301d41
5 changed files with 263 additions and 10 deletions

View File

@@ -1212,6 +1212,108 @@ class FalukantService extends BaseService {
};
}
async repairAllVehicles(hashedUserId, vehicleIds) {
const user = await getFalukantUserOrFail(hashedUserId);
const now = new Date();
if (!vehicleIds || !Array.isArray(vehicleIds) || vehicleIds.length === 0) {
throw new Error('Keine Fahrzeuge zum Reparieren angegeben');
}
// Alle Fahrzeuge laden
const vehicles = await Vehicle.findAll({
where: {
id: { [Op.in]: vehicleIds },
falukantUserId: user.id,
},
include: [
{
model: VehicleType,
as: 'type',
required: true,
},
{
model: Transport,
as: 'transports',
required: false,
attributes: ['id'],
},
],
});
if (vehicles.length !== vehicleIds.length) {
throw new Error('Nicht alle angegebenen Fahrzeuge gefunden oder gehören nicht dem Benutzer');
}
// Prüfe alle Fahrzeuge
const repairableVehicles = [];
let totalCost = 0;
for (const vehicle of vehicles) {
// Prüfen, ob Fahrzeug in Benutzung ist
const hasActiveTransport = Array.isArray(vehicle.transports) && vehicle.transports.length > 0;
const isBuilding = vehicle.availableFrom && new Date(vehicle.availableFrom).getTime() > now.getTime();
if (hasActiveTransport || isBuilding) {
continue; // Überspringe Fahrzeuge in Benutzung
}
// Prüfen, ob Reparatur nötig ist (Zustand < 100)
if (vehicle.condition >= 100) {
continue; // Überspringe bereits perfekte Fahrzeuge
}
// Kosten berechnen: Baupreis * 0.8 * (100 - zustand) / 100
const baseCost = vehicle.type.cost;
const repairCost = Math.round(baseCost * 0.8 * (100 - vehicle.condition) / 100);
totalCost += repairCost;
repairableVehicles.push({ vehicle, repairCost });
}
if (repairableVehicles.length === 0) {
throw new PreconditionError('noVehiclesToRepair');
}
// 10% Rabatt für Reparatur aller Fahrzeuge
const discountedCost = Math.round(totalCost * 0.9);
if (user.money < discountedCost) {
throw new PreconditionError('insufficientFunds');
}
// Alle Reparaturen in einer Transaktion durchführen
await sequelize.transaction(async (tx) => {
// Geld abziehen
const moneyResult = await updateFalukantUserMoney(
user.id,
-discountedCost,
'repair_all_vehicles',
user.id
);
if (!moneyResult.success) {
throw new Error('Failed to update money');
}
// Alle Fahrzeuge reparieren
for (const { vehicle, repairCost } of repairableVehicles) {
const buildTimeMinutes = vehicle.type.buildTimeMinutes || 0;
const buildMs = buildTimeMinutes * 60 * 1000;
const availableFrom = new Date(now.getTime() + buildMs);
await vehicle.update({
condition: 100,
availableFrom: availableFrom,
}, { transaction: tx });
}
});
return {
success: true,
repairedCount: repairableVehicles.length,
totalCost: discountedCost,
};
}
async createStock(hashedUserId, branchId, stockData) {
const u = await getFalukantUserOrFail(hashedUserId);
const b = await getBranchOrFail(u.id, branchId);