@hed-hog/operations 0.0.338 → 0.0.349

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 (61) hide show
  1. package/dist/controllers/operations-collaborators.controller.d.ts +73 -0
  2. package/dist/controllers/operations-collaborators.controller.d.ts.map +1 -1
  3. package/dist/controllers/operations-collaborators.controller.js +100 -0
  4. package/dist/controllers/operations-collaborators.controller.js.map +1 -1
  5. package/dist/controllers/operations-contracts.controller.d.ts +15 -15
  6. package/dist/controllers/operations-projects.controller.d.ts +3 -0
  7. package/dist/controllers/operations-projects.controller.d.ts.map +1 -1
  8. package/dist/dto/create-collaborator-invoice.dto.d.ts +11 -0
  9. package/dist/dto/create-collaborator-invoice.dto.d.ts.map +1 -0
  10. package/dist/dto/create-collaborator-invoice.dto.js +55 -0
  11. package/dist/dto/create-collaborator-invoice.dto.js.map +1 -0
  12. package/dist/dto/create-collaborator-payment.dto.d.ts +10 -0
  13. package/dist/dto/create-collaborator-payment.dto.d.ts.map +1 -0
  14. package/dist/dto/create-collaborator-payment.dto.js +50 -0
  15. package/dist/dto/create-collaborator-payment.dto.js.map +1 -0
  16. package/dist/dto/list-collaborator-invoice.dto.d.ts +4 -0
  17. package/dist/dto/list-collaborator-invoice.dto.d.ts.map +1 -0
  18. package/dist/dto/list-collaborator-invoice.dto.js +8 -0
  19. package/dist/dto/list-collaborator-invoice.dto.js.map +1 -0
  20. package/dist/dto/list-collaborator-payment.dto.d.ts +4 -0
  21. package/dist/dto/list-collaborator-payment.dto.d.ts.map +1 -0
  22. package/dist/dto/list-collaborator-payment.dto.js +8 -0
  23. package/dist/dto/list-collaborator-payment.dto.js.map +1 -0
  24. package/dist/dto/update-collaborator-invoice.dto.d.ts +6 -0
  25. package/dist/dto/update-collaborator-invoice.dto.d.ts.map +1 -0
  26. package/dist/dto/update-collaborator-invoice.dto.js +9 -0
  27. package/dist/dto/update-collaborator-invoice.dto.js.map +1 -0
  28. package/dist/dto/update-collaborator-payment.dto.d.ts +6 -0
  29. package/dist/dto/update-collaborator-payment.dto.d.ts.map +1 -0
  30. package/dist/dto/update-collaborator-payment.dto.js +9 -0
  31. package/dist/dto/update-collaborator-payment.dto.js.map +1 -0
  32. package/dist/operations.service.d.ts +98 -0
  33. package/dist/operations.service.d.ts.map +1 -1
  34. package/dist/operations.service.js +226 -3
  35. package/dist/operations.service.js.map +1 -1
  36. package/hedhog/data/menu.yaml +32 -11
  37. package/hedhog/data/route.yaml +72 -0
  38. package/hedhog/frontend/app/_components/collaborator-form-screen.tsx.ejs +38 -0
  39. package/hedhog/frontend/app/_components/collaborator-invoices-tab.tsx.ejs +443 -0
  40. package/hedhog/frontend/app/_components/collaborator-payment-history-tab.tsx.ejs +429 -0
  41. package/hedhog/frontend/app/_components/project-assignments-tab.tsx.ejs +212 -10
  42. package/hedhog/frontend/app/_components/project-details-screen.tsx.ejs +668 -11
  43. package/hedhog/frontend/app/_components/project-form-screen.tsx.ejs +182 -28
  44. package/hedhog/frontend/app/_components/task-detail-sheet.tsx.ejs +28 -7
  45. package/hedhog/frontend/app/_lib/api.ts.ejs +151 -0
  46. package/hedhog/frontend/app/_lib/types.ts.ejs +1 -0
  47. package/hedhog/frontend/app/_lib/utils/task-ui.ts.ejs +18 -0
  48. package/hedhog/frontend/app/tasks-gantt/page.tsx.ejs +953 -0
  49. package/hedhog/frontend/messages/en.json +96 -2
  50. package/hedhog/frontend/messages/pt.json +96 -2
  51. package/hedhog/table/operations_collaborator_invoice.yaml +35 -0
  52. package/hedhog/table/operations_collaborator_payment.yaml +32 -0
  53. package/package.json +4 -4
  54. package/src/controllers/operations-collaborators.controller.ts +109 -0
  55. package/src/dto/create-collaborator-invoice.dto.ts +39 -0
  56. package/src/dto/create-collaborator-payment.dto.ts +35 -0
  57. package/src/dto/list-collaborator-invoice.dto.ts +3 -0
  58. package/src/dto/list-collaborator-payment.dto.ts +3 -0
  59. package/src/dto/update-collaborator-invoice.dto.ts +6 -0
  60. package/src/dto/update-collaborator-payment.dto.ts +6 -0
  61. package/src/operations.service.ts +318 -4
@@ -2695,6 +2695,262 @@ export class OperationsService {
2695
2695
  );
2696
2696
  }
2697
2697
 
2698
+ async getCollaboratorPaymentHistory(
2699
+ userId: number,
2700
+ collaboratorId: number,
2701
+ ) {
2702
+ const actor = await this.getActorContext(userId);
2703
+ this.ensureDirector(actor);
2704
+ await this.getCollaboratorById(collaboratorId);
2705
+
2706
+ const rows = await this.prisma.operations_collaborator_payment.findMany({
2707
+ where: { collaborator_id: collaboratorId },
2708
+ orderBy: { payment_date: 'desc' },
2709
+ });
2710
+
2711
+ return rows.map((r) => ({
2712
+ id: r.id,
2713
+ collaboratorId: r.collaborator_id,
2714
+ amount: r.amount.toString(),
2715
+ paymentDate: r.payment_date,
2716
+ referenceMonth: r.reference_month,
2717
+ paymentMethod: r.payment_method,
2718
+ notes: r.notes,
2719
+ createdAt: r.created_at,
2720
+ }));
2721
+ }
2722
+
2723
+ async getCollaboratorInvoices(userId: number, collaboratorId: number) {
2724
+ const actor = await this.getActorContext(userId);
2725
+ this.ensureDirector(actor);
2726
+ await this.getCollaboratorById(collaboratorId);
2727
+
2728
+ const rows = await this.prisma.operations_collaborator_invoice.findMany({
2729
+ where: { collaborator_id: collaboratorId },
2730
+ orderBy: { issue_date: 'desc' },
2731
+ });
2732
+
2733
+ return rows.map((r) => ({
2734
+ id: r.id,
2735
+ collaboratorId: r.collaborator_id,
2736
+ invoiceNumber: r.invoice_number,
2737
+ amount: r.amount.toString(),
2738
+ issueDate: r.issue_date,
2739
+ dueDate: r.due_date,
2740
+ status: r.status,
2741
+ description: r.description,
2742
+ createdAt: r.created_at,
2743
+ }));
2744
+ }
2745
+
2746
+ async createCollaboratorPayment(
2747
+ userId: number,
2748
+ collaboratorId: number,
2749
+ data: {
2750
+ amount: number;
2751
+ paymentDate: string;
2752
+ referenceMonth?: string | null;
2753
+ paymentMethod?: string;
2754
+ notes?: string | null;
2755
+ },
2756
+ ) {
2757
+ const actor = await this.getActorContext(userId);
2758
+ this.ensureDirector(actor);
2759
+ await this.getCollaboratorById(collaboratorId);
2760
+
2761
+ const created = await this.prisma.operations_collaborator_payment.create({
2762
+ data: {
2763
+ collaborator_id: collaboratorId,
2764
+ amount: data.amount,
2765
+ payment_date: new Date(data.paymentDate),
2766
+ reference_month: data.referenceMonth ?? null,
2767
+ payment_method: (data.paymentMethod ?? 'pix') as any,
2768
+ notes: data.notes ?? null,
2769
+ },
2770
+ });
2771
+
2772
+ return {
2773
+ id: created.id,
2774
+ collaboratorId: created.collaborator_id,
2775
+ amount: created.amount.toString(),
2776
+ paymentDate: created.payment_date,
2777
+ referenceMonth: created.reference_month,
2778
+ paymentMethod: created.payment_method,
2779
+ notes: created.notes,
2780
+ createdAt: created.created_at,
2781
+ };
2782
+ }
2783
+
2784
+ async updateCollaboratorPayment(
2785
+ userId: number,
2786
+ collaboratorId: number,
2787
+ paymentId: number,
2788
+ data: Partial<{
2789
+ amount: number;
2790
+ paymentDate: string;
2791
+ referenceMonth: string | null;
2792
+ paymentMethod: string;
2793
+ notes: string | null;
2794
+ }>,
2795
+ ) {
2796
+ const actor = await this.getActorContext(userId);
2797
+ this.ensureDirector(actor);
2798
+
2799
+ const payment = await this.prisma.operations_collaborator_payment.findFirst({
2800
+ where: { id: paymentId, collaborator_id: collaboratorId },
2801
+ });
2802
+ if (!payment) throw new NotFoundException('Payment record not found.');
2803
+
2804
+ const updated = await this.prisma.operations_collaborator_payment.update({
2805
+ where: { id: paymentId },
2806
+ data: {
2807
+ ...(data.amount !== undefined && { amount: data.amount }),
2808
+ ...(data.paymentDate !== undefined && { payment_date: new Date(data.paymentDate) }),
2809
+ ...('referenceMonth' in data && { reference_month: data.referenceMonth }),
2810
+ ...(data.paymentMethod !== undefined && { payment_method: data.paymentMethod as any }),
2811
+ ...('notes' in data && { notes: data.notes }),
2812
+ },
2813
+ });
2814
+
2815
+ return {
2816
+ id: updated.id,
2817
+ collaboratorId: updated.collaborator_id,
2818
+ amount: updated.amount.toString(),
2819
+ paymentDate: updated.payment_date,
2820
+ referenceMonth: updated.reference_month,
2821
+ paymentMethod: updated.payment_method,
2822
+ notes: updated.notes,
2823
+ createdAt: updated.created_at,
2824
+ };
2825
+ }
2826
+
2827
+ async deleteCollaboratorPayment(
2828
+ userId: number,
2829
+ collaboratorId: number,
2830
+ paymentId: number,
2831
+ ) {
2832
+ const actor = await this.getActorContext(userId);
2833
+ this.ensureDirector(actor);
2834
+
2835
+ const payment = await this.prisma.operations_collaborator_payment.findFirst({
2836
+ where: { id: paymentId, collaborator_id: collaboratorId },
2837
+ });
2838
+ if (!payment) throw new NotFoundException('Payment record not found.');
2839
+
2840
+ await this.prisma.operations_collaborator_payment.delete({
2841
+ where: { id: paymentId },
2842
+ });
2843
+
2844
+ return { success: true };
2845
+ }
2846
+
2847
+ async createCollaboratorInvoice(
2848
+ userId: number,
2849
+ collaboratorId: number,
2850
+ data: {
2851
+ invoiceNumber?: string | null;
2852
+ amount: number;
2853
+ issueDate: string;
2854
+ dueDate?: string | null;
2855
+ status?: string;
2856
+ description?: string | null;
2857
+ },
2858
+ ) {
2859
+ const actor = await this.getActorContext(userId);
2860
+ this.ensureDirector(actor);
2861
+ await this.getCollaboratorById(collaboratorId);
2862
+
2863
+ const created = await this.prisma.operations_collaborator_invoice.create({
2864
+ data: {
2865
+ collaborator_id: collaboratorId,
2866
+ invoice_number: data.invoiceNumber ?? null,
2867
+ amount: data.amount,
2868
+ issue_date: new Date(data.issueDate),
2869
+ due_date: data.dueDate ? new Date(data.dueDate) : null,
2870
+ status: (data.status ?? 'pending') as any,
2871
+ description: data.description ?? null,
2872
+ },
2873
+ });
2874
+
2875
+ return {
2876
+ id: created.id,
2877
+ collaboratorId: created.collaborator_id,
2878
+ invoiceNumber: created.invoice_number,
2879
+ amount: created.amount.toString(),
2880
+ issueDate: created.issue_date,
2881
+ dueDate: created.due_date,
2882
+ status: created.status,
2883
+ description: created.description,
2884
+ createdAt: created.created_at,
2885
+ };
2886
+ }
2887
+
2888
+ async updateCollaboratorInvoice(
2889
+ userId: number,
2890
+ collaboratorId: number,
2891
+ invoiceId: number,
2892
+ data: Partial<{
2893
+ invoiceNumber: string | null;
2894
+ amount: number;
2895
+ issueDate: string;
2896
+ dueDate: string | null;
2897
+ status: string;
2898
+ description: string | null;
2899
+ }>,
2900
+ ) {
2901
+ const actor = await this.getActorContext(userId);
2902
+ this.ensureDirector(actor);
2903
+
2904
+ const invoice = await this.prisma.operations_collaborator_invoice.findFirst({
2905
+ where: { id: invoiceId, collaborator_id: collaboratorId },
2906
+ });
2907
+ if (!invoice) throw new NotFoundException('Invoice not found.');
2908
+
2909
+ const updated = await this.prisma.operations_collaborator_invoice.update({
2910
+ where: { id: invoiceId },
2911
+ data: {
2912
+ ...('invoiceNumber' in data && { invoice_number: data.invoiceNumber }),
2913
+ ...(data.amount !== undefined && { amount: data.amount }),
2914
+ ...(data.issueDate !== undefined && { issue_date: new Date(data.issueDate) }),
2915
+ ...('dueDate' in data && { due_date: data.dueDate ? new Date(data.dueDate) : null }),
2916
+ ...(data.status !== undefined && { status: data.status as any }),
2917
+ ...('description' in data && { description: data.description }),
2918
+ },
2919
+ });
2920
+
2921
+ return {
2922
+ id: updated.id,
2923
+ collaboratorId: updated.collaborator_id,
2924
+ invoiceNumber: updated.invoice_number,
2925
+ amount: updated.amount.toString(),
2926
+ issueDate: updated.issue_date,
2927
+ dueDate: updated.due_date,
2928
+ status: updated.status,
2929
+ description: updated.description,
2930
+ createdAt: updated.created_at,
2931
+ };
2932
+ }
2933
+
2934
+ async deleteCollaboratorInvoice(
2935
+ userId: number,
2936
+ collaboratorId: number,
2937
+ invoiceId: number,
2938
+ ) {
2939
+ const actor = await this.getActorContext(userId);
2940
+ this.ensureDirector(actor);
2941
+
2942
+ const invoice = await this.prisma.operations_collaborator_invoice.findFirst({
2943
+ where: { id: invoiceId, collaborator_id: collaboratorId },
2944
+ });
2945
+ if (!invoice) throw new NotFoundException('Invoice not found.');
2946
+
2947
+ await this.prisma.operations_collaborator_invoice.delete({
2948
+ where: { id: invoiceId },
2949
+ });
2950
+
2951
+ return { success: true };
2952
+ }
2953
+
2698
2954
  async listDepartments(
2699
2955
  userId: number,
2700
2956
  filters: {
@@ -3118,6 +3374,17 @@ export class OperationsService {
3118
3374
  AND LOWER(TRIM(p2.name)) = LOWER(TRIM(p.client_name))
3119
3375
  LIMIT 1)
3120
3376
  ) AS "clientAvatarId",
3377
+ COALESCE(
3378
+ client_user.photo_id,
3379
+ (SELECT u2.photo_id
3380
+ FROM person p2
3381
+ JOIN person_user pu2 ON pu2.person_id = p2.id
3382
+ JOIN "user" u2 ON u2.id = pu2.user_id
3383
+ WHERE p.client_person_id IS NULL
3384
+ AND LOWER(TRIM(p2.name)) = LOWER(TRIM(p.client_name))
3385
+ ORDER BY pu2.id ASC
3386
+ LIMIT 1)
3387
+ ) AS "clientUserPhotoId",
3121
3388
  p.summary,
3122
3389
  p.status,
3123
3390
  p.progress_percent AS "progressPercent",
@@ -3136,12 +3403,20 @@ export class OperationsService {
3136
3403
  LEFT JOIN operations_collaborator m ON m.id = p.manager_collaborator_id
3137
3404
  LEFT JOIN person cp ON cp.id = p.client_person_id
3138
3405
  LEFT JOIN person mp ON mp.id = m.person_id
3406
+ LEFT JOIN LATERAL (
3407
+ SELECT u.photo_id
3408
+ FROM person_user pu
3409
+ JOIN "user" u ON u.id = pu.user_id
3410
+ WHERE pu.person_id = p.client_person_id
3411
+ ORDER BY pu.id ASC
3412
+ LIMIT 1
3413
+ ) client_user ON TRUE
3139
3414
  LEFT JOIN operations_project_assignment pa
3140
3415
  ON pa.project_id = p.id
3141
3416
  AND pa.deleted_at IS NULL
3142
3417
  AND pa.status IN ('planned', 'active')
3143
3418
  WHERE ${whereClause}
3144
- GROUP BY p.id, c.id, m.id, cp.id, mp.id`;
3419
+ GROUP BY p.id, c.id, m.id, cp.id, mp.id, client_user.photo_id`;
3145
3420
 
3146
3421
  if (!pagination) {
3147
3422
  return this.queryRows(`${baseQuery} ORDER BY p.name ASC`, params);
@@ -8608,6 +8883,7 @@ export class OperationsService {
8608
8883
  managerCollaboratorId: number | null;
8609
8884
  clientPersonId: number | null;
8610
8885
  clientAvatarId: number | null;
8886
+ clientUserPhotoId: number | null;
8611
8887
  code: string;
8612
8888
  name: string;
8613
8889
  clientName: string | null;
@@ -8637,6 +8913,17 @@ export class OperationsService {
8637
8913
  AND LOWER(TRIM(p2.name)) = LOWER(TRIM(p.client_name))
8638
8914
  LIMIT 1)
8639
8915
  ) AS "clientAvatarId",
8916
+ COALESCE(
8917
+ client_user.photo_id,
8918
+ (SELECT u2.photo_id
8919
+ FROM person p2
8920
+ JOIN person_user pu2 ON pu2.person_id = p2.id
8921
+ JOIN "user" u2 ON u2.id = pu2.user_id
8922
+ WHERE p.client_person_id IS NULL
8923
+ AND LOWER(TRIM(p2.name)) = LOWER(TRIM(p.client_name))
8924
+ ORDER BY pu2.id ASC
8925
+ LIMIT 1)
8926
+ ) AS "clientUserPhotoId",
8640
8927
  p.code,
8641
8928
  p.name,
8642
8929
  p.client_name AS "clientName",
@@ -8658,6 +8945,14 @@ export class OperationsService {
8658
8945
  LEFT JOIN operations_contract c ON c.id = p.contract_id
8659
8946
  LEFT JOIN operations_collaborator m ON m.id = p.manager_collaborator_id
8660
8947
  LEFT JOIN person client_person ON client_person.id = p.client_person_id
8948
+ LEFT JOIN LATERAL (
8949
+ SELECT u.photo_id
8950
+ FROM person_user pu
8951
+ JOIN "user" u ON u.id = pu.user_id
8952
+ WHERE pu.person_id = p.client_person_id
8953
+ ORDER BY pu.id ASC
8954
+ LIMIT 1
8955
+ ) client_user ON TRUE
8661
8956
  LEFT JOIN operations_project_assignment pa
8662
8957
  ON pa.project_id = p.id
8663
8958
  AND pa.deleted_at IS NULL
@@ -8673,7 +8968,7 @@ export class OperationsService {
8673
8968
  ) project_role_locale ON TRUE
8674
8969
  WHERE p.id = $1
8675
8970
  AND p.deleted_at IS NULL
8676
- GROUP BY p.id, c.id, m.id, client_person.id`,
8971
+ GROUP BY p.id, c.id, m.id, client_person.id, client_user.photo_id`,
8677
8972
  [projectId, actorCollaboratorId ?? null],
8678
8973
  );
8679
8974
 
@@ -12556,6 +12851,17 @@ export class OperationsService {
12556
12851
  AND LOWER(TRIM(p2.name)) = LOWER(TRIM(p.client_name))
12557
12852
  LIMIT 1)
12558
12853
  ) AS "clientAvatarId",
12854
+ COALESCE(
12855
+ client_user.photo_id,
12856
+ (SELECT u2.photo_id
12857
+ FROM person p2
12858
+ JOIN person_user pu2 ON pu2.person_id = p2.id
12859
+ JOIN "user" u2 ON u2.id = pu2.user_id
12860
+ WHERE p.client_person_id IS NULL
12861
+ AND LOWER(TRIM(p2.name)) = LOWER(TRIM(p.client_name))
12862
+ ORDER BY pu2.id ASC
12863
+ LIMIT 1)
12864
+ ) AS "clientUserPhotoId",
12559
12865
  p.summary,
12560
12866
  p.status,
12561
12867
  p.progress_percent AS "progressPercent",
@@ -12569,12 +12875,20 @@ export class OperationsService {
12569
12875
  LEFT JOIN operations_contract c ON c.id = p.contract_id
12570
12876
  LEFT JOIN operations_collaborator m ON m.id = p.manager_collaborator_id
12571
12877
  LEFT JOIN person cp ON cp.id = p.client_person_id
12878
+ LEFT JOIN LATERAL (
12879
+ SELECT u.photo_id
12880
+ FROM person_user pu
12881
+ JOIN "user" u ON u.id = pu.user_id
12882
+ WHERE pu.person_id = p.client_person_id
12883
+ ORDER BY pu.id ASC
12884
+ LIMIT 1
12885
+ ) client_user ON TRUE
12572
12886
  LEFT JOIN operations_project_assignment pa
12573
12887
  ON pa.project_id = p.id
12574
12888
  AND pa.deleted_at IS NULL
12575
12889
  AND pa.status IN ('planned', 'active')
12576
12890
  WHERE ${whereClause}
12577
- GROUP BY p.id, c.id, m.id, cp.id`;
12891
+ GROUP BY p.id, c.id, m.id, cp.id, client_user.photo_id`;
12578
12892
 
12579
12893
  if (!pagination) {
12580
12894
  return this.queryRows(`${baseQuery} ORDER BY p.name ASC`, params);
@@ -15477,7 +15791,7 @@ export class OperationsService {
15477
15791
  FROM operations_project
15478
15792
  WHERE id = $1 AND deleted_at IS NULL
15479
15793
  LIMIT 1`,
15480
- [projectId],
15794
+ [projectId],
15481
15795
  );
15482
15796
  if (!project) {
15483
15797
  throw new NotFoundException("Project not found.");