@hasna/microservices 0.0.4 → 0.0.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (57) hide show
  1. package/bin/index.js +9 -1
  2. package/bin/mcp.js +9 -1
  3. package/dist/index.js +9 -1
  4. package/microservices/microservice-ads/src/cli/index.ts +198 -0
  5. package/microservices/microservice-ads/src/db/campaigns.ts +304 -0
  6. package/microservices/microservice-ads/src/mcp/index.ts +160 -0
  7. package/microservices/microservice-company/package.json +27 -0
  8. package/microservices/microservice-company/src/cli/index.ts +1126 -0
  9. package/microservices/microservice-company/src/db/company.ts +854 -0
  10. package/microservices/microservice-company/src/db/database.ts +93 -0
  11. package/microservices/microservice-company/src/db/migrations.ts +214 -0
  12. package/microservices/microservice-company/src/db/workflow-migrations.ts +44 -0
  13. package/microservices/microservice-company/src/index.ts +60 -0
  14. package/microservices/microservice-company/src/lib/audit.ts +168 -0
  15. package/microservices/microservice-company/src/lib/finance.ts +299 -0
  16. package/microservices/microservice-company/src/lib/settings.ts +85 -0
  17. package/microservices/microservice-company/src/lib/workflows.ts +698 -0
  18. package/microservices/microservice-company/src/mcp/index.ts +991 -0
  19. package/microservices/microservice-contracts/src/cli/index.ts +410 -23
  20. package/microservices/microservice-contracts/src/db/contracts.ts +430 -1
  21. package/microservices/microservice-contracts/src/db/migrations.ts +83 -0
  22. package/microservices/microservice-contracts/src/mcp/index.ts +312 -3
  23. package/microservices/microservice-domains/src/cli/index.ts +673 -0
  24. package/microservices/microservice-domains/src/db/domains.ts +613 -0
  25. package/microservices/microservice-domains/src/index.ts +21 -0
  26. package/microservices/microservice-domains/src/lib/brandsight.ts +285 -0
  27. package/microservices/microservice-domains/src/lib/godaddy.ts +328 -0
  28. package/microservices/microservice-domains/src/lib/namecheap.ts +474 -0
  29. package/microservices/microservice-domains/src/lib/registrar.ts +355 -0
  30. package/microservices/microservice-domains/src/mcp/index.ts +413 -0
  31. package/microservices/microservice-hiring/src/cli/index.ts +318 -8
  32. package/microservices/microservice-hiring/src/db/hiring.ts +503 -0
  33. package/microservices/microservice-hiring/src/db/migrations.ts +21 -0
  34. package/microservices/microservice-hiring/src/index.ts +29 -0
  35. package/microservices/microservice-hiring/src/lib/scoring.ts +206 -0
  36. package/microservices/microservice-hiring/src/mcp/index.ts +245 -0
  37. package/microservices/microservice-payments/src/cli/index.ts +255 -3
  38. package/microservices/microservice-payments/src/db/migrations.ts +18 -0
  39. package/microservices/microservice-payments/src/db/payments.ts +552 -0
  40. package/microservices/microservice-payments/src/mcp/index.ts +223 -0
  41. package/microservices/microservice-payroll/src/cli/index.ts +269 -0
  42. package/microservices/microservice-payroll/src/db/migrations.ts +26 -0
  43. package/microservices/microservice-payroll/src/db/payroll.ts +636 -0
  44. package/microservices/microservice-payroll/src/mcp/index.ts +246 -0
  45. package/microservices/microservice-shipping/src/cli/index.ts +211 -3
  46. package/microservices/microservice-shipping/src/db/migrations.ts +8 -0
  47. package/microservices/microservice-shipping/src/db/shipping.ts +453 -3
  48. package/microservices/microservice-shipping/src/mcp/index.ts +149 -1
  49. package/microservices/microservice-social/src/cli/index.ts +244 -2
  50. package/microservices/microservice-social/src/db/migrations.ts +33 -0
  51. package/microservices/microservice-social/src/db/social.ts +378 -4
  52. package/microservices/microservice-social/src/mcp/index.ts +221 -1
  53. package/microservices/microservice-subscriptions/src/cli/index.ts +315 -0
  54. package/microservices/microservice-subscriptions/src/db/migrations.ts +68 -0
  55. package/microservices/microservice-subscriptions/src/db/subscriptions.ts +567 -3
  56. package/microservices/microservice-subscriptions/src/mcp/index.ts +267 -1
  57. package/package.json +1 -1
@@ -17,6 +17,17 @@ import {
17
17
  getPaymentStats,
18
18
  getBalanceByProvider,
19
19
  listByProvider,
20
+ autoReconcile,
21
+ retryPayment,
22
+ listRetries,
23
+ getRetryStats,
24
+ convertCurrency,
25
+ feeAnalysis,
26
+ declineReport,
27
+ addDisputeEvidence,
28
+ splitPayment,
29
+ revenueForecast,
30
+ findReconciliationGaps,
20
31
  } from "../db/payments.js";
21
32
  import {
22
33
  createDispute,
@@ -447,6 +458,218 @@ server.registerTool(
447
458
  }
448
459
  );
449
460
 
461
+ // --- Auto-Reconciliation ---
462
+
463
+ server.registerTool(
464
+ "auto_reconcile",
465
+ {
466
+ title: "Auto Reconcile",
467
+ description: "Auto-reconcile payments to invoices by matching amount, customer email, and date (+-3 days tolerance).",
468
+ inputSchema: {
469
+ date_from: z.string().optional(),
470
+ date_to: z.string().optional(),
471
+ },
472
+ },
473
+ async ({ date_from, date_to }) => {
474
+ const result = autoReconcile(date_from, date_to);
475
+ return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
476
+ }
477
+ );
478
+
479
+ // --- Retry ---
480
+
481
+ server.registerTool(
482
+ "retry_payment",
483
+ {
484
+ title: "Retry Payment",
485
+ description: "Retry a failed payment. Creates a retry attempt record and re-processes the payment.",
486
+ inputSchema: { id: z.string() },
487
+ },
488
+ async ({ id }) => {
489
+ const attempt = retryPayment(id);
490
+ if (!attempt) {
491
+ return {
492
+ content: [{ type: "text", text: `Cannot retry payment '${id}' — not found or not failed.` }],
493
+ isError: true,
494
+ };
495
+ }
496
+ return { content: [{ type: "text", text: JSON.stringify(attempt, null, 2) }] };
497
+ }
498
+ );
499
+
500
+ server.registerTool(
501
+ "list_retries",
502
+ {
503
+ title: "List Retries",
504
+ description: "List all retry attempts for a payment.",
505
+ inputSchema: { payment_id: z.string() },
506
+ },
507
+ async ({ payment_id }) => {
508
+ const retries = listRetries(payment_id);
509
+ return {
510
+ content: [
511
+ { type: "text", text: JSON.stringify({ retries, count: retries.length }, null, 2) },
512
+ ],
513
+ };
514
+ }
515
+ );
516
+
517
+ server.registerTool(
518
+ "retry_stats",
519
+ {
520
+ title: "Retry Statistics",
521
+ description: "Get overall retry attempt statistics.",
522
+ inputSchema: {},
523
+ },
524
+ async () => {
525
+ const stats = getRetryStats();
526
+ return { content: [{ type: "text", text: JSON.stringify(stats, null, 2) }] };
527
+ }
528
+ );
529
+
530
+ // --- Currency Conversion ---
531
+
532
+ server.registerTool(
533
+ "convert_currency",
534
+ {
535
+ title: "Convert Currency",
536
+ description: "Convert an amount between currencies using built-in rates (USD/EUR/GBP/CAD/AUD).",
537
+ inputSchema: {
538
+ amount: z.number(),
539
+ from: z.string(),
540
+ to: z.string(),
541
+ },
542
+ },
543
+ async ({ amount, from, to }) => {
544
+ const result = convertCurrency(amount, from, to);
545
+ if (!result) {
546
+ return {
547
+ content: [{ type: "text", text: `Unsupported currency pair: ${from} -> ${to}` }],
548
+ isError: true,
549
+ };
550
+ }
551
+ return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
552
+ }
553
+ );
554
+
555
+ // --- Fee Analysis ---
556
+
557
+ server.registerTool(
558
+ "fee_analysis",
559
+ {
560
+ title: "Fee Analysis",
561
+ description: "Analyze processor fees per provider for a given month. Shows gross, fees, and net per provider.",
562
+ inputSchema: {
563
+ month: z.string().describe("Month in YYYY-MM format"),
564
+ },
565
+ },
566
+ async ({ month }) => {
567
+ const result = feeAnalysis(month);
568
+ return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
569
+ }
570
+ );
571
+
572
+ // --- Decline Analytics ---
573
+
574
+ server.registerTool(
575
+ "decline_analysis",
576
+ {
577
+ title: "Decline Analysis",
578
+ description: "Get decline analytics — groups failed payments by description/reason.",
579
+ inputSchema: {
580
+ provider: z.enum(["stripe", "square", "mercury", "manual"]).optional(),
581
+ },
582
+ },
583
+ async ({ provider }) => {
584
+ const report = declineReport(provider);
585
+ return { content: [{ type: "text", text: JSON.stringify(report, null, 2) }] };
586
+ }
587
+ );
588
+
589
+ // --- Dispute Evidence ---
590
+
591
+ server.registerTool(
592
+ "add_dispute_evidence",
593
+ {
594
+ title: "Add Dispute Evidence",
595
+ description: "Add evidence to an existing dispute. Appends to the evidence items array.",
596
+ inputSchema: {
597
+ dispute_id: z.string(),
598
+ description: z.string(),
599
+ file_ref: z.string().optional(),
600
+ },
601
+ },
602
+ async ({ dispute_id, description, file_ref }) => {
603
+ const dispute = addDisputeEvidence(dispute_id, description, file_ref);
604
+ if (!dispute) {
605
+ return {
606
+ content: [{ type: "text", text: `Dispute '${dispute_id}' not found.` }],
607
+ isError: true,
608
+ };
609
+ }
610
+ return { content: [{ type: "text", text: JSON.stringify(dispute, null, 2) }] };
611
+ }
612
+ );
613
+
614
+ // --- Payment Split ---
615
+
616
+ server.registerTool(
617
+ "split_payment",
618
+ {
619
+ title: "Split Payment",
620
+ description: "Record marketplace commission splits for a payment. Stores split percentages in payment metadata.",
621
+ inputSchema: {
622
+ payment_id: z.string(),
623
+ splits: z.record(z.number()).describe("Map of vendor name to percentage (e.g. {vendor1: 70, vendor2: 30})"),
624
+ },
625
+ },
626
+ async ({ payment_id, splits }) => {
627
+ const payment = splitPayment(payment_id, splits);
628
+ if (!payment) {
629
+ return {
630
+ content: [{ type: "text", text: `Payment '${payment_id}' not found.` }],
631
+ isError: true,
632
+ };
633
+ }
634
+ return { content: [{ type: "text", text: JSON.stringify(payment, null, 2) }] };
635
+ }
636
+ );
637
+
638
+ // --- Revenue Forecast ---
639
+
640
+ server.registerTool(
641
+ "revenue_forecast",
642
+ {
643
+ title: "Revenue Forecast",
644
+ description: "Project revenue for upcoming months based on last 3 months trend.",
645
+ inputSchema: {
646
+ months: z.number().describe("Number of months to forecast"),
647
+ },
648
+ },
649
+ async ({ months }) => {
650
+ const result = revenueForecast(months);
651
+ return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
652
+ }
653
+ );
654
+
655
+ // --- Reconciliation Gaps ---
656
+
657
+ server.registerTool(
658
+ "reconciliation_gaps",
659
+ {
660
+ title: "Reconciliation Gaps",
661
+ description: "Find payments without invoice_id and invoice IDs without a succeeded payment in a date range.",
662
+ inputSchema: {
663
+ date_from: z.string(),
664
+ date_to: z.string(),
665
+ },
666
+ },
667
+ async ({ date_from, date_to }) => {
668
+ const gaps = findReconciliationGaps(date_from, date_to);
669
+ return { content: [{ type: "text", text: JSON.stringify(gaps, null, 2) }] };
670
+ }
671
+ );
672
+
450
673
  // --- Start ---
451
674
  async function main() {
452
675
  const transport = new StdioServerTransport();
@@ -16,6 +16,17 @@ import {
16
16
  getPayrollReport,
17
17
  getYtdReport,
18
18
  getTaxSummary,
19
+ createBenefit,
20
+ listBenefits,
21
+ removeBenefit,
22
+ generateAchFile,
23
+ generateW2,
24
+ generate1099,
25
+ setSchedule,
26
+ getNextPayPeriod,
27
+ auditPayroll,
28
+ forecastPayroll,
29
+ checkOvertime,
19
30
  } from "../db/payroll.js";
20
31
 
21
32
  const program = new Command();
@@ -371,4 +382,262 @@ program
371
382
  }
372
383
  });
373
384
 
385
+ // --- Benefits ---
386
+
387
+ const benefitCmd = program
388
+ .command("benefit")
389
+ .description("Employee benefit management");
390
+
391
+ benefitCmd
392
+ .command("add")
393
+ .description("Add a benefit to an employee")
394
+ .requiredOption("--employee <id>", "Employee ID")
395
+ .requiredOption("--type <type>", "Benefit type: health, dental, vision, retirement, hsa, other")
396
+ .requiredOption("--amount <amount>", "Deduction amount")
397
+ .option("--description <desc>", "Description")
398
+ .option("--frequency <freq>", "Frequency: per_period, monthly, annual", "per_period")
399
+ .option("--json", "Output as JSON", false)
400
+ .action((opts) => {
401
+ try {
402
+ const benefit = createBenefit({
403
+ employee_id: opts.employee,
404
+ type: opts.type,
405
+ amount: parseFloat(opts.amount),
406
+ description: opts.description,
407
+ frequency: opts.frequency,
408
+ });
409
+
410
+ if (opts.json) {
411
+ console.log(JSON.stringify(benefit, null, 2));
412
+ } else {
413
+ console.log(`Created benefit: ${benefit.type} $${benefit.amount}/${benefit.frequency} (${benefit.id})`);
414
+ }
415
+ } catch (error) {
416
+ console.error(`Error: ${error instanceof Error ? error.message : String(error)}`);
417
+ process.exit(1);
418
+ }
419
+ });
420
+
421
+ benefitCmd
422
+ .command("list")
423
+ .description("List benefits")
424
+ .option("--employee <id>", "Filter by employee ID")
425
+ .option("--json", "Output as JSON", false)
426
+ .action((opts) => {
427
+ const benefits = listBenefits(opts.employee);
428
+
429
+ if (opts.json) {
430
+ console.log(JSON.stringify(benefits, null, 2));
431
+ } else {
432
+ if (benefits.length === 0) {
433
+ console.log("No benefits found.");
434
+ return;
435
+ }
436
+ for (const b of benefits) {
437
+ const status = b.active ? "" : " [INACTIVE]";
438
+ console.log(` ${b.type} — $${b.amount}/${b.frequency} (${b.employee_id})${status}`);
439
+ }
440
+ console.log(`\n${benefits.length} benefit(s)`);
441
+ }
442
+ });
443
+
444
+ benefitCmd
445
+ .command("remove")
446
+ .description("Deactivate a benefit")
447
+ .argument("<id>", "Benefit ID")
448
+ .option("--json", "Output as JSON", false)
449
+ .action((id, opts) => {
450
+ const removed = removeBenefit(id);
451
+ if (opts.json) {
452
+ console.log(JSON.stringify({ removed }));
453
+ } else {
454
+ console.log(removed ? `Benefit ${id} deactivated.` : `Benefit '${id}' not found.`);
455
+ }
456
+ });
457
+
458
+ // --- ACH File Generation ---
459
+
460
+ program
461
+ .command("generate-ach")
462
+ .description("Generate NACHA-format ACH file for a pay period")
463
+ .requiredOption("--period <id>", "Pay period ID")
464
+ .requiredOption("--routing <number>", "Bank routing number")
465
+ .requiredOption("--account <number>", "Bank account number")
466
+ .option("--company <name>", "Company name", "PAYROLL CO")
467
+ .action((opts) => {
468
+ try {
469
+ const achContent = generateAchFile(opts.period, opts.routing, opts.account, opts.company);
470
+ console.log(achContent);
471
+ } catch (error) {
472
+ console.error(`Error: ${error instanceof Error ? error.message : String(error)}`);
473
+ process.exit(1);
474
+ }
475
+ });
476
+
477
+ // --- W-2 Generation ---
478
+
479
+ program
480
+ .command("w2")
481
+ .description("Generate W-2 data for an employee")
482
+ .requiredOption("--year <year>", "Tax year")
483
+ .requiredOption("--employee <id>", "Employee ID")
484
+ .option("--json", "Output as JSON", false)
485
+ .action((opts) => {
486
+ const w2 = generateW2(opts.employee, parseInt(opts.year));
487
+ if (!w2) {
488
+ console.error("No W-2 data found (employee not found, is a contractor, or has no pay stubs).");
489
+ process.exit(1);
490
+ }
491
+
492
+ if (opts.json) {
493
+ console.log(JSON.stringify(w2, null, 2));
494
+ } else {
495
+ console.log(`W-2 for ${w2.employee_name} (${w2.year})`);
496
+ console.log(` Gross Wages: $${w2.gross}`);
497
+ console.log(` Federal Tax Withheld: $${w2.federal_withheld}`);
498
+ console.log(` State Tax Withheld: $${w2.state_withheld}`);
499
+ console.log(` Social Security: $${w2.social_security}`);
500
+ console.log(` Medicare: $${w2.medicare}`);
501
+ }
502
+ });
503
+
504
+ // --- 1099-NEC Generation ---
505
+
506
+ program
507
+ .command("1099")
508
+ .description("Generate 1099-NEC data for contractors")
509
+ .requiredOption("--year <year>", "Tax year")
510
+ .option("--employee <id>", "Specific contractor ID (optional)")
511
+ .option("--json", "Output as JSON", false)
512
+ .action((opts) => {
513
+ const forms = generate1099(opts.employee || null, parseInt(opts.year));
514
+
515
+ if (opts.json) {
516
+ console.log(JSON.stringify(forms, null, 2));
517
+ } else {
518
+ if (forms.length === 0) {
519
+ console.log("No 1099-NEC forms to generate (no contractors with >$600 compensation).");
520
+ return;
521
+ }
522
+ for (const f of forms) {
523
+ console.log(` ${f.employee_name}: $${f.total_compensation} (${f.year})`);
524
+ }
525
+ console.log(`\n${forms.length} form(s)`);
526
+ }
527
+ });
528
+
529
+ // --- Payroll Schedule ---
530
+
531
+ const scheduleCmd = program
532
+ .command("schedule")
533
+ .description("Payroll schedule management");
534
+
535
+ scheduleCmd
536
+ .command("set")
537
+ .description("Set the payroll schedule")
538
+ .requiredOption("--frequency <freq>", "Frequency: weekly, biweekly, semimonthly, monthly")
539
+ .requiredOption("--anchor <date>", "Anchor date (YYYY-MM-DD)")
540
+ .option("--json", "Output as JSON", false)
541
+ .action((opts) => {
542
+ const schedule = setSchedule(opts.frequency, opts.anchor);
543
+
544
+ if (opts.json) {
545
+ console.log(JSON.stringify(schedule, null, 2));
546
+ } else {
547
+ console.log(`Schedule set: ${schedule.frequency} starting ${schedule.anchor_date}`);
548
+ }
549
+ });
550
+
551
+ scheduleCmd
552
+ .command("next")
553
+ .description("Get the next pay period dates based on schedule")
554
+ .option("--json", "Output as JSON", false)
555
+ .action((opts) => {
556
+ const next = getNextPayPeriod();
557
+ if (!next) {
558
+ console.error("No payroll schedule configured. Use 'schedule set' first.");
559
+ process.exit(1);
560
+ }
561
+
562
+ if (opts.json) {
563
+ console.log(JSON.stringify(next, null, 2));
564
+ } else {
565
+ console.log(`Next pay period: ${next.start_date} to ${next.end_date}`);
566
+ }
567
+ });
568
+
569
+ // --- Audit ---
570
+
571
+ program
572
+ .command("audit")
573
+ .description("Audit a payroll period for issues")
574
+ .requiredOption("--period <id>", "Pay period ID")
575
+ .option("--json", "Output as JSON", false)
576
+ .action((opts) => {
577
+ try {
578
+ const result = auditPayroll(opts.period);
579
+
580
+ if (opts.json) {
581
+ console.log(JSON.stringify(result, null, 2));
582
+ } else {
583
+ if (result.passed) {
584
+ console.log("PASSED — No issues found.");
585
+ } else {
586
+ console.log(`FAILED — ${result.issues.length} issue(s):`);
587
+ for (const issue of result.issues) {
588
+ console.log(` - ${issue}`);
589
+ }
590
+ }
591
+ }
592
+ } catch (error) {
593
+ console.error(`Error: ${error instanceof Error ? error.message : String(error)}`);
594
+ process.exit(1);
595
+ }
596
+ });
597
+
598
+ // --- Forecast ---
599
+
600
+ program
601
+ .command("forecast")
602
+ .description("Forecast future payroll costs")
603
+ .option("--months <n>", "Number of months to forecast", "3")
604
+ .option("--json", "Output as JSON", false)
605
+ .action((opts) => {
606
+ const result = forecastPayroll(parseInt(opts.months));
607
+
608
+ if (opts.json) {
609
+ console.log(JSON.stringify(result, null, 2));
610
+ } else {
611
+ console.log(`Payroll Forecast (${result.months} months):`);
612
+ for (const p of result.periods) {
613
+ console.log(` ${p.month}: gross=$${p.estimated_gross} deductions=$${p.estimated_deductions} net=$${p.estimated_net}`);
614
+ }
615
+ console.log(`\nTotal: gross=$${result.total_estimated_gross} deductions=$${result.total_estimated_deductions} net=$${result.total_estimated_net}`);
616
+ }
617
+ });
618
+
619
+ // --- Overtime Check ---
620
+
621
+ program
622
+ .command("overtime-check")
623
+ .description("Check for employees exceeding weekly hours threshold")
624
+ .option("--threshold <hours>", "Hours threshold", "40")
625
+ .option("--json", "Output as JSON", false)
626
+ .action((opts) => {
627
+ const alerts = checkOvertime(parseFloat(opts.threshold));
628
+
629
+ if (opts.json) {
630
+ console.log(JSON.stringify(alerts, null, 2));
631
+ } else {
632
+ if (alerts.length === 0) {
633
+ console.log("No overtime alerts.");
634
+ return;
635
+ }
636
+ for (const a of alerts) {
637
+ console.log(` ${a.employee_name}: ${a.total_hours}h total (${a.overtime_hours}h over ${a.threshold}h threshold)`);
638
+ }
639
+ console.log(`\n${alerts.length} alert(s)`);
640
+ }
641
+ });
642
+
374
643
  program.parse(process.argv);
@@ -66,4 +66,30 @@ export const MIGRATIONS: MigrationEntry[] = [
66
66
  CREATE INDEX IF NOT EXISTS idx_payments_status ON payments(status);
67
67
  `,
68
68
  },
69
+ {
70
+ id: 2,
71
+ name: "benefits_and_schedule",
72
+ sql: `
73
+ CREATE TABLE IF NOT EXISTS benefits (
74
+ id TEXT PRIMARY KEY,
75
+ employee_id TEXT NOT NULL REFERENCES employees(id) ON DELETE CASCADE,
76
+ type TEXT NOT NULL CHECK (type IN ('health', 'dental', 'vision', 'retirement', 'hsa', 'other')),
77
+ description TEXT,
78
+ amount REAL NOT NULL,
79
+ frequency TEXT NOT NULL DEFAULT 'per_period' CHECK (frequency IN ('per_period', 'monthly', 'annual')),
80
+ active INTEGER NOT NULL DEFAULT 1,
81
+ created_at TEXT NOT NULL DEFAULT (datetime('now'))
82
+ );
83
+
84
+ CREATE TABLE IF NOT EXISTS payroll_schedule (
85
+ id TEXT PRIMARY KEY,
86
+ frequency TEXT NOT NULL CHECK (frequency IN ('weekly', 'biweekly', 'semimonthly', 'monthly')),
87
+ anchor_date TEXT NOT NULL,
88
+ created_at TEXT NOT NULL DEFAULT (datetime('now'))
89
+ );
90
+
91
+ CREATE INDEX IF NOT EXISTS idx_benefits_employee ON benefits(employee_id);
92
+ CREATE INDEX IF NOT EXISTS idx_benefits_active ON benefits(active);
93
+ `,
94
+ },
69
95
  ];