@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
@@ -23,6 +23,17 @@ import {
23
23
  getPayrollReport,
24
24
  getYtdReport,
25
25
  getTaxSummary,
26
+ createBenefit,
27
+ listBenefits,
28
+ removeBenefit,
29
+ generateAchFile,
30
+ generateW2,
31
+ generate1099,
32
+ setSchedule,
33
+ getNextPayPeriod,
34
+ auditPayroll,
35
+ forecastPayroll,
36
+ checkOvertime,
26
37
  } from "../db/payroll.js";
27
38
 
28
39
  const server = new McpServer({
@@ -407,6 +418,241 @@ server.registerTool(
407
418
  }
408
419
  );
409
420
 
421
+ // --- Benefits ---
422
+
423
+ server.registerTool(
424
+ "create_benefit",
425
+ {
426
+ title: "Create Benefit",
427
+ description: "Add a benefit deduction to an employee (health, dental, vision, retirement, hsa, other).",
428
+ inputSchema: {
429
+ employee_id: z.string(),
430
+ type: z.enum(["health", "dental", "vision", "retirement", "hsa", "other"]),
431
+ description: z.string().optional(),
432
+ amount: z.number(),
433
+ frequency: z.enum(["per_period", "monthly", "annual"]).optional(),
434
+ },
435
+ },
436
+ async (params) => {
437
+ try {
438
+ const benefit = createBenefit(params);
439
+ return { content: [{ type: "text", text: JSON.stringify(benefit, null, 2) }] };
440
+ } catch (error) {
441
+ return {
442
+ content: [{ type: "text", text: `Error: ${error instanceof Error ? error.message : String(error)}` }],
443
+ isError: true,
444
+ };
445
+ }
446
+ }
447
+ );
448
+
449
+ server.registerTool(
450
+ "list_benefits",
451
+ {
452
+ title: "List Benefits",
453
+ description: "List benefit deductions, optionally filtered by employee.",
454
+ inputSchema: {
455
+ employee_id: z.string().optional(),
456
+ },
457
+ },
458
+ async ({ employee_id }) => {
459
+ const benefits = listBenefits(employee_id);
460
+ return {
461
+ content: [
462
+ { type: "text", text: JSON.stringify({ benefits, count: benefits.length }, null, 2) },
463
+ ],
464
+ };
465
+ }
466
+ );
467
+
468
+ server.registerTool(
469
+ "remove_benefit",
470
+ {
471
+ title: "Remove Benefit",
472
+ description: "Deactivate a benefit by ID.",
473
+ inputSchema: { id: z.string() },
474
+ },
475
+ async ({ id }) => {
476
+ const removed = removeBenefit(id);
477
+ if (!removed) {
478
+ return { content: [{ type: "text", text: `Benefit '${id}' not found.` }], isError: true };
479
+ }
480
+ return { content: [{ type: "text", text: JSON.stringify({ removed: true, id }) }] };
481
+ }
482
+ );
483
+
484
+ // --- ACH File Generation ---
485
+
486
+ server.registerTool(
487
+ "generate_ach_file",
488
+ {
489
+ title: "Generate ACH File",
490
+ description: "Generate a NACHA-format ACH file for a completed pay period.",
491
+ inputSchema: {
492
+ period_id: z.string(),
493
+ bank_routing: z.string(),
494
+ bank_account: z.string(),
495
+ company_name: z.string().optional(),
496
+ },
497
+ },
498
+ async ({ period_id, bank_routing, bank_account, company_name }) => {
499
+ try {
500
+ const content = generateAchFile(period_id, bank_routing, bank_account, company_name);
501
+ return { content: [{ type: "text", text: content }] };
502
+ } catch (error) {
503
+ return {
504
+ content: [{ type: "text", text: `Error: ${error instanceof Error ? error.message : String(error)}` }],
505
+ isError: true,
506
+ };
507
+ }
508
+ }
509
+ );
510
+
511
+ // --- W-2 ---
512
+
513
+ server.registerTool(
514
+ "generate_w2",
515
+ {
516
+ title: "Generate W-2",
517
+ description: "Generate W-2 data for an employee for a given tax year.",
518
+ inputSchema: {
519
+ employee_id: z.string(),
520
+ year: z.number(),
521
+ },
522
+ },
523
+ async ({ employee_id, year }) => {
524
+ const w2 = generateW2(employee_id, year);
525
+ if (!w2) {
526
+ return {
527
+ content: [{ type: "text", text: "No W-2 data found (employee not found, is a contractor, or has no pay stubs)." }],
528
+ isError: true,
529
+ };
530
+ }
531
+ return { content: [{ type: "text", text: JSON.stringify(w2, null, 2) }] };
532
+ }
533
+ );
534
+
535
+ // --- 1099-NEC ---
536
+
537
+ server.registerTool(
538
+ "generate_1099",
539
+ {
540
+ title: "Generate 1099-NEC",
541
+ description: "Generate 1099-NEC data for contractors with >$600 compensation in a given year.",
542
+ inputSchema: {
543
+ employee_id: z.string().optional(),
544
+ year: z.number(),
545
+ },
546
+ },
547
+ async ({ employee_id, year }) => {
548
+ const forms = generate1099(employee_id || null, year);
549
+ return {
550
+ content: [
551
+ { type: "text", text: JSON.stringify({ forms, count: forms.length }, null, 2) },
552
+ ],
553
+ };
554
+ }
555
+ );
556
+
557
+ // --- Payroll Schedule ---
558
+
559
+ server.registerTool(
560
+ "set_schedule",
561
+ {
562
+ title: "Set Payroll Schedule",
563
+ description: "Set the payroll schedule frequency and anchor date.",
564
+ inputSchema: {
565
+ frequency: z.enum(["weekly", "biweekly", "semimonthly", "monthly"]),
566
+ anchor_date: z.string(),
567
+ },
568
+ },
569
+ async ({ frequency, anchor_date }) => {
570
+ const schedule = setSchedule(frequency, anchor_date);
571
+ return { content: [{ type: "text", text: JSON.stringify(schedule, null, 2) }] };
572
+ }
573
+ );
574
+
575
+ server.registerTool(
576
+ "next_pay_period",
577
+ {
578
+ title: "Next Pay Period",
579
+ description: "Get the next pay period dates based on the configured payroll schedule.",
580
+ inputSchema: {},
581
+ },
582
+ async () => {
583
+ const next = getNextPayPeriod();
584
+ if (!next) {
585
+ return {
586
+ content: [{ type: "text", text: "No payroll schedule configured. Use set_schedule first." }],
587
+ isError: true,
588
+ };
589
+ }
590
+ return { content: [{ type: "text", text: JSON.stringify(next, null, 2) }] };
591
+ }
592
+ );
593
+
594
+ // --- Audit ---
595
+
596
+ server.registerTool(
597
+ "audit_payroll",
598
+ {
599
+ title: "Audit Payroll",
600
+ description: "Audit a payroll period for issues: missing stubs, bad net_pay, deduction mismatches, duplicates.",
601
+ inputSchema: {
602
+ period_id: z.string(),
603
+ },
604
+ },
605
+ async ({ period_id }) => {
606
+ try {
607
+ const result = auditPayroll(period_id);
608
+ return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
609
+ } catch (error) {
610
+ return {
611
+ content: [{ type: "text", text: `Error: ${error instanceof Error ? error.message : String(error)}` }],
612
+ isError: true,
613
+ };
614
+ }
615
+ }
616
+ );
617
+
618
+ // --- Forecast ---
619
+
620
+ server.registerTool(
621
+ "forecast_payroll",
622
+ {
623
+ title: "Forecast Payroll",
624
+ description: "Project future payroll costs for a given number of months.",
625
+ inputSchema: {
626
+ months: z.number().min(1).max(60),
627
+ },
628
+ },
629
+ async ({ months }) => {
630
+ const result = forecastPayroll(months);
631
+ return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
632
+ }
633
+ );
634
+
635
+ // --- Overtime ---
636
+
637
+ server.registerTool(
638
+ "check_overtime",
639
+ {
640
+ title: "Check Overtime",
641
+ description: "Flag employees exceeding a weekly hours threshold in the most recent completed period.",
642
+ inputSchema: {
643
+ threshold: z.number().optional(),
644
+ },
645
+ },
646
+ async ({ threshold }) => {
647
+ const alerts = checkOvertime(threshold);
648
+ return {
649
+ content: [
650
+ { type: "text", text: JSON.stringify({ alerts, count: alerts.length }, null, 2) },
651
+ ],
652
+ };
653
+ }
654
+ );
655
+
410
656
  // --- Start ---
411
657
  async function main() {
412
658
  const transport = new StdioServerTransport();
@@ -1,6 +1,7 @@
1
1
  #!/usr/bin/env bun
2
2
 
3
3
  import { Command } from "commander";
4
+ import { readFileSync } from "node:fs";
4
5
  import {
5
6
  createOrder,
6
7
  getOrder,
@@ -9,6 +10,9 @@ import {
9
10
  deleteOrder,
10
11
  searchOrders,
11
12
  listByStatus,
13
+ bulkImportOrders,
14
+ exportOrders,
15
+ getOrderTimeline,
12
16
  } from "../db/shipping.js";
13
17
  import {
14
18
  createShipment,
@@ -25,6 +29,11 @@ import {
25
29
  import {
26
30
  getShippingStats,
27
31
  getCostsByCarrier,
32
+ getDeliveryStats,
33
+ listOverdueShipments,
34
+ getCustomerHistory,
35
+ getCarrierPerformance,
36
+ optimizeCost,
28
37
  } from "../db/shipping.js";
29
38
 
30
39
  const program = new Command();
@@ -152,6 +161,61 @@ orderCmd
152
161
  }
153
162
  });
154
163
 
164
+ orderCmd
165
+ .command("import")
166
+ .description("Bulk import orders from a CSV file")
167
+ .requiredOption("--file <path>", "Path to CSV file")
168
+ .option("--json", "Output as JSON", false)
169
+ .action((opts) => {
170
+ const csvData = readFileSync(opts.file, "utf-8");
171
+ const result = bulkImportOrders(csvData);
172
+
173
+ if (opts.json) {
174
+ console.log(JSON.stringify(result, null, 2));
175
+ } else {
176
+ console.log(`Imported ${result.imported} order(s)`);
177
+ if (result.errors.length > 0) {
178
+ console.log(`Errors:`);
179
+ for (const err of result.errors) {
180
+ console.log(` Line ${err.line}: ${err.message}`);
181
+ }
182
+ }
183
+ }
184
+ });
185
+
186
+ orderCmd
187
+ .command("export")
188
+ .description("Export orders to CSV or JSON")
189
+ .option("--format <format>", "Output format (csv/json)", "csv")
190
+ .option("--from <date>", "Filter from date (YYYY-MM-DD)")
191
+ .option("--to <date>", "Filter to date (YYYY-MM-DD)")
192
+ .action((opts) => {
193
+ const output = exportOrders(opts.format as "csv" | "json", opts.from, opts.to);
194
+ console.log(output);
195
+ });
196
+
197
+ orderCmd
198
+ .command("timeline")
199
+ .description("Show full event timeline for an order")
200
+ .argument("<id>", "Order ID")
201
+ .option("--json", "Output as JSON", false)
202
+ .action((id, opts) => {
203
+ const timeline = getOrderTimeline(id);
204
+ if (timeline.length === 0) {
205
+ console.error(`No events found for order '${id}'.`);
206
+ process.exit(1);
207
+ }
208
+
209
+ if (opts.json) {
210
+ console.log(JSON.stringify(timeline, null, 2));
211
+ } else {
212
+ console.log(`Timeline for order ${id}:`);
213
+ for (const event of timeline) {
214
+ console.log(` [${event.timestamp}] ${event.type}: ${event.details}`);
215
+ }
216
+ }
217
+ });
218
+
155
219
  // --- Ship (create shipment) ---
156
220
 
157
221
  program
@@ -259,17 +323,20 @@ returnCmd
259
323
  .description("Create a return request")
260
324
  .requiredOption("--order <id>", "Order ID")
261
325
  .option("--reason <reason>", "Return reason")
326
+ .option("--auto-rma", "Auto-generate RMA code", false)
262
327
  .option("--json", "Output as JSON", false)
263
328
  .action((opts) => {
264
329
  const ret = createReturn({
265
330
  order_id: opts.order,
266
331
  reason: opts.reason,
332
+ auto_rma: opts.autoRma,
267
333
  });
268
334
 
269
335
  if (opts.json) {
270
336
  console.log(JSON.stringify(ret, null, 2));
271
337
  } else {
272
338
  console.log(`Created return: ${ret.id} for order ${ret.order_id} [${ret.status}]`);
339
+ if (ret.rma_code) console.log(` RMA Code: ${ret.rma_code}`);
273
340
  }
274
341
  });
275
342
 
@@ -347,9 +414,11 @@ program
347
414
 
348
415
  // --- Stats ---
349
416
 
350
- program
351
- .command("stats")
352
- .description("Show shipping statistics")
417
+ const statsCmd = program.command("stats").description("Shipping statistics and analytics");
418
+
419
+ statsCmd
420
+ .command("overview")
421
+ .description("Show overall shipping statistics")
353
422
  .option("--json", "Output as JSON", false)
354
423
  .action((opts) => {
355
424
  const stats = getShippingStats();
@@ -372,6 +441,56 @@ program
372
441
  }
373
442
  });
374
443
 
444
+ statsCmd
445
+ .command("delivery-times")
446
+ .description("Delivery timeline analytics per carrier/service")
447
+ .option("--carrier <carrier>", "Filter by carrier")
448
+ .option("--json", "Output as JSON", false)
449
+ .action((opts) => {
450
+ const stats = getDeliveryStats(opts.carrier);
451
+
452
+ if (opts.json) {
453
+ console.log(JSON.stringify(stats, null, 2));
454
+ } else {
455
+ if (stats.length === 0) {
456
+ console.log("No delivery data available (need shipments with shipped_at and delivered_at).");
457
+ return;
458
+ }
459
+ console.log("Delivery Timeline Analytics:");
460
+ for (const s of stats) {
461
+ console.log(` ${s.carrier.toUpperCase()}/${s.service}:`);
462
+ console.log(` Shipments: ${s.total_shipments} (${s.delivered_count} delivered)`);
463
+ console.log(` Avg delivery: ${s.avg_delivery_days.toFixed(1)} days`);
464
+ console.log(` On-time: ${s.on_time_pct.toFixed(1)}%, Late: ${s.late_pct.toFixed(1)}%`);
465
+ }
466
+ }
467
+ });
468
+
469
+ statsCmd
470
+ .command("carrier-performance")
471
+ .description("Rank carriers by on-time %, avg cost, avg delivery days")
472
+ .option("--json", "Output as JSON", false)
473
+ .action((opts) => {
474
+ const perf = getCarrierPerformance();
475
+
476
+ if (opts.json) {
477
+ console.log(JSON.stringify(perf, null, 2));
478
+ } else {
479
+ if (perf.length === 0) {
480
+ console.log("No carrier data available.");
481
+ return;
482
+ }
483
+ console.log("Carrier Performance (ranked by on-time %):");
484
+ for (const p of perf) {
485
+ console.log(` ${p.carrier.toUpperCase()}:`);
486
+ console.log(` Shipments: ${p.total_shipments} (${p.delivered_count} delivered)`);
487
+ console.log(` On-time: ${p.on_time_pct.toFixed(1)}%`);
488
+ console.log(` Avg cost: $${p.avg_cost.toFixed(2)}`);
489
+ console.log(` Avg delivery: ${p.avg_delivery_days.toFixed(1)} days`);
490
+ }
491
+ }
492
+ });
493
+
375
494
  // --- Costs ---
376
495
 
377
496
  program
@@ -395,4 +514,93 @@ program
395
514
  }
396
515
  });
397
516
 
517
+ // --- Late Delivery Alerts ---
518
+
519
+ program
520
+ .command("check-late")
521
+ .description("List overdue shipments past estimated delivery + grace days")
522
+ .option("--days <n>", "Grace days beyond estimated delivery", "0")
523
+ .option("--json", "Output as JSON", false)
524
+ .action((opts) => {
525
+ const overdue = listOverdueShipments(parseInt(opts.days));
526
+
527
+ if (opts.json) {
528
+ console.log(JSON.stringify(overdue, null, 2));
529
+ } else {
530
+ if (overdue.length === 0) {
531
+ console.log("No overdue shipments found.");
532
+ return;
533
+ }
534
+ console.log(`Overdue Shipments (grace: ${opts.days} day(s)):`);
535
+ for (const s of overdue) {
536
+ const tracking = s.tracking_number ? ` (${s.tracking_number})` : "";
537
+ console.log(` ${s.shipment_id.slice(0, 8)}... ${s.carrier}/${s.service}${tracking}`);
538
+ console.log(` ETA: ${s.estimated_delivery}, ${s.days_overdue} day(s) overdue [${s.status}]`);
539
+ }
540
+ console.log(`\n${overdue.length} overdue shipment(s)`);
541
+ }
542
+ });
543
+
544
+ // --- Customer History ---
545
+
546
+ program
547
+ .command("customer-history")
548
+ .description("Show all orders, shipments, and returns for a customer")
549
+ .argument("<email>", "Customer email")
550
+ .option("--json", "Output as JSON", false)
551
+ .action((email, opts) => {
552
+ const history = getCustomerHistory(email);
553
+
554
+ if (opts.json) {
555
+ console.log(JSON.stringify(history, null, 2));
556
+ } else {
557
+ console.log(`Customer History for ${email}:`);
558
+ console.log(` Orders: ${history.orders.length}`);
559
+ for (const o of history.orders) {
560
+ console.log(` [${o.status}] ${o.id.slice(0, 8)}... $${o.total_value} ${o.currency}`);
561
+ }
562
+ console.log(` Shipments: ${history.shipments.length}`);
563
+ for (const s of history.shipments) {
564
+ console.log(` [${s.status}] ${s.id.slice(0, 8)}... ${s.carrier}/${s.service}`);
565
+ }
566
+ console.log(` Returns: ${history.returns.length}`);
567
+ for (const r of history.returns) {
568
+ const rma = r.rma_code ? ` (${r.rma_code})` : "";
569
+ console.log(` [${r.status}] ${r.id.slice(0, 8)}...${rma}`);
570
+ }
571
+ }
572
+ });
573
+
574
+ // --- Cost Optimizer ---
575
+
576
+ program
577
+ .command("optimize-cost")
578
+ .description("Recommend cheapest carrier/service based on historical data")
579
+ .requiredOption("--weight <kg>", "Package weight in kg")
580
+ .option("--from <zip>", "Origin zip code")
581
+ .option("--to <zip>", "Destination zip code")
582
+ .option("--json", "Output as JSON", false)
583
+ .action((opts) => {
584
+ const recommendations = optimizeCost(
585
+ parseFloat(opts.weight),
586
+ opts.from,
587
+ opts.to
588
+ );
589
+
590
+ if (opts.json) {
591
+ console.log(JSON.stringify(recommendations, null, 2));
592
+ } else {
593
+ if (recommendations.length === 0) {
594
+ console.log("No historical shipping data found for the given weight range.");
595
+ return;
596
+ }
597
+ console.log(`Cost recommendations for ${opts.weight}kg package:`);
598
+ for (let i = 0; i < recommendations.length; i++) {
599
+ const r = recommendations[i];
600
+ const deliveryInfo = r.avg_delivery_days ? `, ~${r.avg_delivery_days.toFixed(1)} days` : "";
601
+ console.log(` ${i + 1}. ${r.carrier.toUpperCase()}/${r.service}: $${r.avg_cost.toFixed(2)} avg (${r.shipment_count} samples${deliveryInfo})`);
602
+ }
603
+ }
604
+ });
605
+
398
606
  program.parse(process.argv);
@@ -58,4 +58,12 @@ export const MIGRATIONS: MigrationEntry[] = [
58
58
  CREATE INDEX IF NOT EXISTS idx_returns_status ON returns(status);
59
59
  `,
60
60
  },
61
+ {
62
+ id: 2,
63
+ name: "add_rma_code",
64
+ sql: `
65
+ ALTER TABLE returns ADD COLUMN rma_code TEXT;
66
+ CREATE UNIQUE INDEX IF NOT EXISTS idx_returns_rma_code ON returns(rma_code);
67
+ `,
68
+ },
61
69
  ];