business-as-code
Version:
Primitives for expressing business logic and processes as code
140 lines • 4.16 kB
JavaScript
/**
* Service definition and management
*/
/**
* Define a service with pricing, SLA, and delivery information
*
* @example
* ```ts
* const service = Service({
* name: 'Widget Consulting',
* description: 'Expert widget implementation and optimization',
* category: 'Consulting',
* targetSegment: 'Enterprise',
* valueProposition: 'Get expert help implementing widgets in 2 weeks',
* pricingModel: 'fixed',
* price: 5000,
* currency: 'USD',
* deliveryTime: '2 weeks',
* sla: {
* uptime: 99.9,
* responseTime: '< 24 hours',
* supportHours: 'Business hours (9-5 EST)',
* penalties: '10% refund per day of delay',
* },
* })
* ```
*/
export function Service(definition) {
if (!definition.name) {
throw new Error('Service name is required');
}
return {
...definition,
pricingModel: definition.pricingModel || 'hourly',
currency: definition.currency || 'USD',
metadata: definition.metadata || {},
};
}
/**
* Calculate service price based on hours (for hourly pricing)
*/
export function calculateHourlyPrice(service, hours) {
if (service.pricingModel !== 'hourly' || !service.price) {
throw new Error('Service must use hourly pricing model');
}
return service.price * hours;
}
/**
* Calculate monthly retainer equivalent
*/
export function calculateMonthlyRetainer(service, hoursPerMonth) {
if (service.pricingModel !== 'hourly' || !service.price) {
throw new Error('Service must use hourly pricing model');
}
return service.price * hoursPerMonth;
}
/**
* Check if service meets SLA uptime requirement
*/
export function checkSLAUptime(service, actualUptime) {
if (!service.sla?.uptime)
return true;
return actualUptime >= service.sla.uptime;
}
/**
* Parse delivery time to days
*/
export function parseDeliveryTimeToDays(deliveryTime) {
if (!deliveryTime)
return 0;
const lower = deliveryTime.toLowerCase();
// Parse patterns like "2 weeks", "3 days", "1 month"
const match = lower.match(/(\d+)\s*(day|days|week|weeks|month|months|hour|hours)/);
if (!match)
return 0;
const value = parseInt(match[1] || '0', 10);
const unit = match[2];
switch (unit) {
case 'hour':
case 'hours':
return value / 24;
case 'day':
case 'days':
return value;
case 'week':
case 'weeks':
return value * 7;
case 'month':
case 'months':
return value * 30;
default:
return 0;
}
}
/**
* Estimate service completion date
*/
export function estimateCompletionDate(service, startDate) {
const start = startDate || new Date();
const days = parseDeliveryTimeToDays(service.deliveryTime);
const completion = new Date(start);
completion.setDate(completion.getDate() + days);
return completion;
}
/**
* Calculate service value (for value-based pricing)
*/
export function calculateValueBasedPrice(service, customerValue, valueSharePercentage) {
if (service.pricingModel !== 'value-based') {
throw new Error('Service must use value-based pricing model');
}
if (valueSharePercentage < 0 || valueSharePercentage > 100) {
throw new Error('Value share percentage must be between 0 and 100');
}
return customerValue * (valueSharePercentage / 100);
}
/**
* Validate service definition
*/
export function validateService(service) {
const errors = [];
if (!service.name) {
errors.push('Service name is required');
}
if (service.price && service.price < 0) {
errors.push('Service price cannot be negative');
}
if (service.sla?.uptime && (service.sla.uptime < 0 || service.sla.uptime > 100)) {
errors.push('SLA uptime must be between 0 and 100');
}
if (service.pricingModel &&
!['hourly', 'fixed', 'retainer', 'value-based'].includes(service.pricingModel)) {
errors.push('Invalid pricing model');
}
return {
valid: errors.length === 0,
errors,
};
}
//# sourceMappingURL=service.js.map