Files
alrahma_sunday_school_api/apps/api/dist/modules/vehicles/vehicle.service.js
T
2026-06-11 03:22:12 -04:00

633 lines
26 KiB
JavaScript

"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.listVehicles = listVehicles;
exports.getVehicle = getVehicle;
exports.createVehicle = createVehicle;
exports.updateVehicle = updateVehicle;
exports.setStatus = setStatus;
exports.deleteVehicle = deleteVehicle;
exports.uploadPhotos = uploadPhotos;
exports.deletePhoto = deletePhoto;
exports.setPublished = setPublished;
exports.checkAvailability = checkAvailability;
exports.getCalendar = getCalendar;
exports.createCalendarBlock = createCalendarBlock;
exports.deleteCalendarBlock = deleteCalendarBlock;
exports.getMaintenanceLogs = getMaintenanceLogs;
exports.createMaintenanceLog = createMaintenanceLog;
exports.getVehiclePricing = getVehiclePricing;
exports.updateVehiclePricing = updateVehiclePricing;
exports.createVehiclePricingRule = createVehiclePricingRule;
exports.updateVehiclePricingRule = updateVehiclePricingRule;
exports.deleteVehiclePricingRule = deleteVehiclePricingRule;
const storage_1 = require("../../lib/storage");
const errors_1 = require("../../http/errors");
const vehicle_presenter_1 = require("./vehicle.presenter");
const repo = __importStar(require("./vehicle.repo"));
const DAY_MS = 24 * 60 * 60 * 1000;
const RULE_PRIORITY = {
MANUAL_OVERRIDE: 6,
HOLIDAY: 5,
SPECIAL_EVENT: 4,
SEASONAL: 3,
WEEKEND: 2,
DATE_RANGE: 1,
};
function isPricingStorageMissing(error) {
if (!error || typeof error !== 'object')
return false;
const candidate = error;
return (candidate.code === 'P2021' ||
candidate.message?.includes('vehicle_pricing_configurations') === true ||
candidate.message?.includes('vehicle_pricing_rules') === true ||
candidate.message?.includes('vehicle_price_history') === true);
}
function normalizeLocations(locations) {
if (!Array.isArray(locations))
return [];
const seen = new Set();
const normalized = [];
for (const entry of locations) {
if (typeof entry !== 'string')
continue;
const value = entry.trim();
const key = value.toLocaleLowerCase();
if (!value || seen.has(key))
continue;
seen.add(key);
normalized.push(value);
}
return normalized;
}
function applyLocationSettings(data) {
const patch = { ...data };
if (patch.pickupLocations !== undefined) {
patch.pickupLocations = normalizeLocations(patch.pickupLocations);
}
if (patch.dropoffLocations !== undefined) {
patch.dropoffLocations = normalizeLocations(patch.dropoffLocations);
}
if (patch.allowDifferentDropoff === false) {
patch.dropoffLocations = [];
}
if (patch.allowDifferentDropoff === true && patch.dropoffLocations !== undefined && patch.dropoffLocations.length === 0) {
throw new errors_1.ValidationError('Drop-off locations are required when different drop-off is enabled');
}
return patch;
}
function toStartOfDay(value) {
const date = new Date(value);
date.setHours(0, 0, 0, 0);
return date;
}
function toEndOfDay(value) {
const date = new Date(value);
date.setHours(23, 59, 59, 999);
return date;
}
function isWeekend(date) {
const day = date.getDay();
return day === 0 || day === 6;
}
function clampRate(value, min, max) {
if (min != null && value < min)
return min;
if (max != null && value > max)
return max;
return value;
}
function validateRateBounds(minimum, maximum, label = 'Daily') {
if (minimum != null && maximum != null && minimum > maximum) {
throw new errors_1.ValidationError(`${label} minimum rate must be less than or equal to the maximum rate`);
}
}
function normalizePricingConfigurationInput(data) {
const normalized = {
pricingMode: data.pricingMode,
baseDailyRate: data.baseDailyRate,
weeklyRate: data.weeklyRate ?? null,
weekendRate: data.weekendRate ?? null,
holidayRate: data.holidayRate ?? null,
monthlyRate: data.monthlyRate ?? null,
longTermDailyRate: data.longTermDailyRate ?? null,
minimumDailyRate: data.minimumDailyRate ?? null,
maximumDailyRate: data.maximumDailyRate ?? null,
maxDailyPriceMovementPct: data.maxDailyPriceMovementPct,
automaticPricingEnabled: data.automaticPricingEnabled,
approvalRequired: data.approvalRequired,
};
validateRateBounds(normalized.minimumDailyRate, normalized.maximumDailyRate);
validateRateBounds(normalized.baseDailyRate, normalized.maximumDailyRate, 'Base');
return normalized;
}
function normalizePricingRuleInput(data) {
const normalized = {
name: data.name,
ruleType: data.ruleType,
startDate: toStartOfDay(data.startDate),
endDate: toEndOfDay(data.endDate),
dailyRate: data.dailyRate ?? null,
weeklyRate: data.weeklyRate ?? null,
weekendRate: data.weekendRate ?? null,
monthlyRate: data.monthlyRate ?? null,
minDailyRate: data.minDailyRate ?? null,
maxDailyRate: data.maxDailyRate ?? null,
automaticAdjustmentPct: data.automaticAdjustmentPct ?? null,
priceAdjustment: data.priceAdjustment ?? null,
isActive: data.isActive,
sortOrder: data.sortOrder,
};
if (normalized.endDate < normalized.startDate) {
throw new errors_1.ValidationError('Rule end date must be on or after the start date');
}
validateRateBounds(normalized.minDailyRate, normalized.maxDailyRate);
const hasPricingEffect = [
normalized.dailyRate,
normalized.weeklyRate,
normalized.weekendRate,
normalized.monthlyRate,
normalized.minDailyRate,
normalized.maxDailyRate,
normalized.automaticAdjustmentPct,
normalized.priceAdjustment,
].some((value) => value != null);
if (!hasPricingEffect) {
throw new errors_1.ValidationError('Pricing rules must define at least one rate, bound, or adjustment');
}
return normalized;
}
async function ensurePricingConfigurationForVehicle(vehicleId, companyId) {
const vehicle = await repo.findById(vehicleId, companyId);
if (!vehicle)
throw new errors_1.NotFoundError('Vehicle not found');
let configuration = null;
let persistenceAvailable = true;
try {
configuration = await repo.findPricingConfiguration(vehicleId);
}
catch (error) {
if (!isPricingStorageMissing(error))
throw error;
persistenceAvailable = false;
}
if (!persistenceAvailable) {
return {
vehicle,
persistenceAvailable,
configuration: {
id: `transient-${vehicle.id}`,
vehicleId: vehicle.id,
pricingMode: 'MANUAL',
baseDailyRate: vehicle.dailyRate,
weeklyRate: vehicle.dailyRate * 7,
weekendRate: null,
holidayRate: null,
monthlyRate: null,
longTermDailyRate: null,
minimumDailyRate: null,
maximumDailyRate: null,
maxDailyPriceMovementPct: 10,
automaticPricingEnabled: false,
approvalRequired: false,
rules: [],
history: [],
createdAt: vehicle.createdAt,
updatedAt: vehicle.updatedAt,
},
};
}
if (!configuration) {
configuration = await repo.createPricingConfiguration({
vehicleId,
pricingMode: 'MANUAL',
baseDailyRate: vehicle.dailyRate,
weeklyRate: vehicle.dailyRate * 7,
automaticPricingEnabled: false,
approvalRequired: false,
maxDailyPriceMovementPct: 10,
});
}
return { vehicle, configuration, persistenceAvailable };
}
async function syncPricingBaseRateFromVehicle(vehicleId, previousDailyRate, nextDailyRate) {
const configuration = await repo.findPricingConfiguration(vehicleId);
if (!configuration)
return;
const currentBaseRate = configuration.baseDailyRate ?? previousDailyRate;
if (currentBaseRate === nextDailyRate)
return;
await repo.updatePricingConfiguration(configuration.id, { baseDailyRate: nextDailyRate });
await repo.createPriceHistory({
configurationId: configuration.id,
vehicleId,
source: 'CONFIG_UPDATE',
previousDailyRate: currentBaseRate,
nextDailyRate,
previousWeeklyRate: configuration.weeklyRate ?? null,
nextWeeklyRate: configuration.weeklyRate ?? null,
note: 'Base daily rate synced from vehicle details',
});
}
function buildPricePreview(vehicle, configuration) {
const baseDailyRate = configuration.baseDailyRate ?? vehicle.dailyRate;
const activeRules = (configuration.rules ?? []).filter((rule) => rule.isActive);
const items = Array.from({ length: 14 }, (_, index) => {
const date = new Date(Date.now() + (index * DAY_MS));
date.setHours(12, 0, 0, 0);
let dailyRate = baseDailyRate;
let pricingType = configuration.pricingMode === 'AUTOMATIC' && configuration.automaticPricingEnabled
? 'AUTOMATIC_BASE'
: 'MANUAL_BASE';
if (isWeekend(date) && configuration.weekendRate != null) {
dailyRate = configuration.weekendRate;
pricingType = 'WEEKEND_RATE';
}
const matchingRule = activeRules
.filter((rule) => date >= new Date(rule.startDate) && date <= new Date(rule.endDate))
.sort((a, b) => {
const priorityDiff = (RULE_PRIORITY[b.ruleType] ?? 0) - (RULE_PRIORITY[a.ruleType] ?? 0);
if (priorityDiff !== 0)
return priorityDiff;
if (a.sortOrder !== b.sortOrder)
return b.sortOrder - a.sortOrder;
return new Date(b.startDate).getTime() - new Date(a.startDate).getTime();
})[0];
if (matchingRule) {
if (matchingRule.dailyRate != null) {
dailyRate = matchingRule.dailyRate;
}
else {
if (matchingRule.weekendRate != null && isWeekend(date)) {
dailyRate = matchingRule.weekendRate;
}
if (matchingRule.priceAdjustment != null) {
dailyRate += matchingRule.priceAdjustment;
}
if (matchingRule.automaticAdjustmentPct != null) {
dailyRate = Math.round(dailyRate * (100 + matchingRule.automaticAdjustmentPct) / 100);
}
}
pricingType = configuration.pricingMode === 'AUTOMATIC' ? 'AUTOMATIC_RULE' : 'RULE_RATE';
dailyRate = clampRate(dailyRate, matchingRule.minDailyRate ?? configuration.minimumDailyRate, matchingRule.maxDailyRate ?? configuration.maximumDailyRate);
}
else {
dailyRate = clampRate(dailyRate, configuration.minimumDailyRate, configuration.maximumDailyRate);
}
return {
date: date.toISOString().slice(0, 10),
dailyRate,
pricingType,
matchedRuleName: matchingRule?.name ?? null,
};
});
return {
today: items[0],
next14Days: items,
};
}
function presentVehiclePricing(vehicle, configuration) {
return {
configuration: {
id: configuration.id,
vehicleId: configuration.vehicleId,
pricingMode: configuration.pricingMode,
baseDailyRate: configuration.baseDailyRate ?? vehicle.dailyRate,
weeklyRate: configuration.weeklyRate ?? null,
weekendRate: configuration.weekendRate ?? null,
holidayRate: configuration.holidayRate ?? null,
monthlyRate: configuration.monthlyRate ?? null,
longTermDailyRate: configuration.longTermDailyRate ?? null,
minimumDailyRate: configuration.minimumDailyRate ?? null,
maximumDailyRate: configuration.maximumDailyRate ?? null,
maxDailyPriceMovementPct: configuration.maxDailyPriceMovementPct,
automaticPricingEnabled: configuration.automaticPricingEnabled,
approvalRequired: configuration.approvalRequired,
createdAt: configuration.createdAt,
updatedAt: configuration.updatedAt,
},
rules: (configuration.rules ?? []).map((rule) => ({
id: rule.id,
name: rule.name,
ruleType: rule.ruleType,
startDate: rule.startDate,
endDate: rule.endDate,
dailyRate: rule.dailyRate,
weeklyRate: rule.weeklyRate,
weekendRate: rule.weekendRate,
monthlyRate: rule.monthlyRate,
minDailyRate: rule.minDailyRate,
maxDailyRate: rule.maxDailyRate,
automaticAdjustmentPct: rule.automaticAdjustmentPct,
priceAdjustment: rule.priceAdjustment,
isActive: rule.isActive,
sortOrder: rule.sortOrder,
createdAt: rule.createdAt,
updatedAt: rule.updatedAt,
})),
history: (configuration.history ?? []).map((entry) => ({
id: entry.id,
source: entry.source,
changedByEmployeeId: entry.changedByEmployeeId,
previousDailyRate: entry.previousDailyRate,
nextDailyRate: entry.nextDailyRate,
previousWeeklyRate: entry.previousWeeklyRate,
nextWeeklyRate: entry.nextWeeklyRate,
note: entry.note,
effectiveFrom: entry.effectiveFrom,
createdAt: entry.createdAt,
})),
preview: buildPricePreview(vehicle, configuration),
};
}
async function listVehicles(companyId, query) {
const page = query.page ?? 1;
const pageSize = query.pageSize ?? 20;
const { status, category, published } = query;
const where = { companyId };
if (status)
where.status = status;
if (category)
where.category = category;
if (published !== undefined)
where.isPublished = published === 'true';
const [vehicles, total] = await repo.findMany(where, (page - 1) * pageSize, pageSize);
return (0, vehicle_presenter_1.presentVehicleList)(vehicles.map(vehicle_presenter_1.presentVehicle), { total, page, pageSize, totalPages: Math.ceil(total / pageSize) });
}
async function getVehicle(id, companyId) {
const vehicle = await repo.findById(id, companyId);
if (!vehicle)
throw new errors_1.NotFoundError('Vehicle not found');
return (0, vehicle_presenter_1.presentVehicle)(vehicle);
}
async function createVehicle(data, companyId) {
return (0, vehicle_presenter_1.presentVehicle)(await repo.create({
dailyRate: 0,
...applyLocationSettings(data),
companyId,
}));
}
const PUBLISHED_STATUSES = new Set(['AVAILABLE', 'RESERVED', 'READY', 'RENTED']);
async function updateVehicle(id, companyId, data) {
const patch = applyLocationSettings(data);
if (patch.status) {
patch.isPublished = PUBLISHED_STATUSES.has(patch.status);
}
const existing = await repo.findFirst(id, companyId);
if (!existing)
throw new errors_1.NotFoundError('Vehicle not found');
const updated = await repo.updateById(id, patch);
if (patch.dailyRate !== undefined && typeof patch.dailyRate === 'number') {
await syncPricingBaseRateFromVehicle(id, existing.dailyRate, patch.dailyRate);
}
return (0, vehicle_presenter_1.presentVehicle)(updated);
}
async function setStatus(id, companyId, status) {
const existing = await repo.findFirst(id, companyId);
if (!existing)
throw new errors_1.NotFoundError('Vehicle not found');
const isPublished = PUBLISHED_STATUSES.has(status);
return (0, vehicle_presenter_1.presentVehicle)(await repo.updateById(id, { status, isPublished }));
}
async function deleteVehicle(id, companyId) {
return repo.softDelete(id, companyId);
}
async function uploadPhotos(id, companyId, files) {
const vehicle = await repo.findById(id, companyId);
if (!vehicle)
throw new errors_1.NotFoundError('Vehicle not found');
const urls = await Promise.all(files.map((f) => (0, storage_1.uploadImage)(f.buffer, `companies/${companyId}/vehicles`)));
return (0, vehicle_presenter_1.presentVehicle)(await repo.updateById(id, { photos: [...vehicle.photos, ...urls] }));
}
async function deletePhoto(id, companyId, idx) {
const vehicle = await repo.findById(id, companyId);
if (!vehicle)
throw new errors_1.NotFoundError('Vehicle not found');
const photos = vehicle.photos.filter((_, i) => i !== idx);
return (0, vehicle_presenter_1.presentVehicle)(await repo.updateById(id, { photos }));
}
async function setPublished(id, companyId, isPublished) {
await repo.setPublished(id, companyId, isPublished);
}
async function checkAvailability(id, companyId, startDate, endDate) {
const start = new Date(startDate);
const end = new Date(endDate);
const [conflicts, blocks] = await Promise.all([
repo.findReservationConflicts(id, companyId, start, end),
repo.findCalendarBlockConflicts(id, start, end),
]);
return { available: conflicts.length === 0 && blocks.length === 0, conflicts, blocks };
}
async function getCalendar(id, companyId, year, month) {
const vehicle = await repo.findById(id, companyId);
if (!vehicle)
throw new errors_1.NotFoundError('Vehicle not found');
const rangeStart = new Date(year, month - 1, 1);
const rangeEnd = new Date(year, month, 1);
const [reservations, blocks] = await repo.findCalendarEvents(id, companyId, rangeStart, rangeEnd);
return [
...reservations.map((r) => ({
id: r.id,
type: 'RESERVATION',
startDate: r.startDate,
endDate: r.endDate,
status: r.status,
label: r.customer ? `${r.customer.firstName} ${r.customer.lastName}` : 'Reserved',
})),
...blocks.map((b) => ({
id: b.id,
type: b.type === 'MAINTENANCE' ? 'MAINTENANCE' : 'BLOCK',
startDate: b.startDate,
endDate: b.endDate,
status: null,
label: b.reason ?? (b.type === 'MAINTENANCE' ? 'Maintenance' : 'Blocked'),
})),
];
}
async function createCalendarBlock(id, companyId, data) {
const start = new Date(data.startDate);
const end = new Date(data.endDate);
if (end <= start)
throw new errors_1.ValidationError('endDate must be after startDate');
const vehicle = await repo.findById(id, companyId);
if (!vehicle)
throw new errors_1.NotFoundError('Vehicle not found');
return repo.createCalendarBlock({ vehicleId: id, startDate: start, endDate: end, reason: data.reason, type: data.type ?? 'MANUAL' });
}
async function deleteCalendarBlock(vehicleId, companyId, blockId) {
const vehicle = await repo.findById(vehicleId, companyId);
if (!vehicle)
throw new errors_1.NotFoundError('Vehicle not found');
await repo.deleteCalendarBlock(blockId, vehicleId);
}
async function getMaintenanceLogs(id, companyId) {
const vehicle = await repo.findById(id, companyId);
if (!vehicle)
throw new errors_1.NotFoundError('Vehicle not found');
return repo.findMaintenanceLogs(id);
}
async function createMaintenanceLog(id, companyId, data) {
const vehicle = await repo.findById(id, companyId);
if (!vehicle)
throw new errors_1.NotFoundError('Vehicle not found');
return repo.createMaintenanceLog({
...data,
vehicleId: id,
performedAt: new Date(data.performedAt),
nextDueAt: data.nextDueAt ? new Date(data.nextDueAt) : undefined,
});
}
async function getVehiclePricing(id, companyId) {
const { vehicle, configuration } = await ensurePricingConfigurationForVehicle(id, companyId);
return presentVehiclePricing(vehicle, configuration);
}
async function updateVehiclePricing(id, companyId, employeeId, data) {
const { vehicle, configuration, persistenceAvailable } = await ensurePricingConfigurationForVehicle(id, companyId);
if (!persistenceAvailable) {
throw new errors_1.AppError('Vehicle pricing tables are not available yet. Run the latest database migration, then retry.', 503, 'pricing_migration_required');
}
const nextConfig = normalizePricingConfigurationInput(data);
const currentBaseDailyRate = configuration.baseDailyRate ?? vehicle.dailyRate;
const currentWeeklyRate = configuration.weeklyRate ?? null;
const changed = [
'pricingMode',
'baseDailyRate',
'weeklyRate',
'weekendRate',
'holidayRate',
'monthlyRate',
'longTermDailyRate',
'minimumDailyRate',
'maximumDailyRate',
'maxDailyPriceMovementPct',
'automaticPricingEnabled',
'approvalRequired',
].some((key) => (configuration[key] ?? null) !== (nextConfig[key] ?? null));
await repo.updatePricingConfiguration(configuration.id, nextConfig);
if (vehicle.dailyRate !== nextConfig.baseDailyRate) {
await repo.updateById(id, { dailyRate: nextConfig.baseDailyRate });
}
if (changed) {
await repo.createPriceHistory({
configurationId: configuration.id,
vehicleId: id,
source: 'CONFIG_UPDATE',
changedByEmployeeId: employeeId,
previousDailyRate: currentBaseDailyRate,
nextDailyRate: nextConfig.baseDailyRate,
previousWeeklyRate: currentWeeklyRate,
nextWeeklyRate: nextConfig.weeklyRate ?? null,
note: data.note,
});
}
return getVehiclePricing(id, companyId);
}
async function createVehiclePricingRule(id, companyId, employeeId, data) {
const { configuration, persistenceAvailable } = await ensurePricingConfigurationForVehicle(id, companyId);
if (!persistenceAvailable) {
throw new errors_1.AppError('Vehicle pricing tables are not available yet. Run the latest database migration, then retry.', 503, 'pricing_migration_required');
}
const payload = normalizePricingRuleInput(data);
const rule = await repo.createPricingRule({
configurationId: configuration.id,
...payload,
});
await repo.createPriceHistory({
configurationId: configuration.id,
vehicleId: id,
source: payload.ruleType === 'MANUAL_OVERRIDE' ? 'MANUAL_OVERRIDE' : 'RULE_CREATED',
changedByEmployeeId: employeeId,
previousDailyRate: configuration.baseDailyRate ?? null,
nextDailyRate: payload.dailyRate,
previousWeeklyRate: configuration.weeklyRate ?? null,
nextWeeklyRate: payload.weeklyRate,
note: `Created pricing rule: ${rule.name}`,
effectiveFrom: rule.startDate,
});
return getVehiclePricing(id, companyId);
}
async function updateVehiclePricingRule(id, companyId, ruleId, employeeId, data) {
const { configuration, persistenceAvailable } = await ensurePricingConfigurationForVehicle(id, companyId);
if (!persistenceAvailable) {
throw new errors_1.AppError('Vehicle pricing tables are not available yet. Run the latest database migration, then retry.', 503, 'pricing_migration_required');
}
const existingRule = await repo.findPricingRule(ruleId, configuration.id);
if (!existingRule)
throw new errors_1.NotFoundError('Pricing rule not found');
const mergedRule = normalizePricingRuleInput({
...existingRule,
...data,
startDate: data.startDate ?? existingRule.startDate,
endDate: data.endDate ?? existingRule.endDate,
});
const updatedRule = await repo.updatePricingRule(ruleId, mergedRule);
await repo.createPriceHistory({
configurationId: configuration.id,
vehicleId: id,
source: mergedRule.ruleType === 'MANUAL_OVERRIDE' ? 'MANUAL_OVERRIDE' : 'RULE_UPDATED',
changedByEmployeeId: employeeId,
previousDailyRate: existingRule.dailyRate,
nextDailyRate: updatedRule.dailyRate,
previousWeeklyRate: existingRule.weeklyRate,
nextWeeklyRate: updatedRule.weeklyRate,
note: `Updated pricing rule: ${updatedRule.name}`,
effectiveFrom: updatedRule.startDate,
});
return getVehiclePricing(id, companyId);
}
async function deleteVehiclePricingRule(id, companyId, ruleId, employeeId) {
const { configuration, persistenceAvailable } = await ensurePricingConfigurationForVehicle(id, companyId);
if (!persistenceAvailable) {
throw new errors_1.AppError('Vehicle pricing tables are not available yet. Run the latest database migration, then retry.', 503, 'pricing_migration_required');
}
const existingRule = await repo.findPricingRule(ruleId, configuration.id);
if (!existingRule)
throw new errors_1.NotFoundError('Pricing rule not found');
await repo.deletePricingRule(ruleId, configuration.id);
await repo.createPriceHistory({
configurationId: configuration.id,
vehicleId: id,
source: existingRule.ruleType === 'MANUAL_OVERRIDE' ? 'MANUAL_OVERRIDE' : 'RULE_DELETED',
changedByEmployeeId: employeeId,
previousDailyRate: existingRule.dailyRate,
nextDailyRate: configuration.baseDailyRate ?? null,
previousWeeklyRate: existingRule.weeklyRate,
nextWeeklyRate: configuration.weeklyRate ?? null,
note: `Deleted pricing rule: ${existingRule.name}`,
effectiveFrom: existingRule.startDate,
});
return getVehiclePricing(id, companyId);
}
//# sourceMappingURL=vehicle.service.js.map