From 926a05aa27f9a77feab8355942ee420eea2dc227 Mon Sep 17 00:00:00 2001 From: nael Date: Mon, 8 Jul 2024 01:05:48 +0200 Subject: [PATCH] :bug: Fix things --- ngrok.yml | 4 +- packages/api/prisma/schema.prisma | 708 ++++++++++++++++-- .../api/src/@core/utils/types/interface.ts | 10 + .../accounting/address/sync/sync.service.ts | 13 + .../attachment/sync/sync.service.ts | 13 + .../balancesheet/sync/sync.service.ts | 11 +- .../cashflowstatement/sync/sync.service.ts | 11 + .../companyinfo/sync/sync.service.ts | 11 + .../accounting/contact/sync/sync.service.ts | 11 + .../creditnote/sync/sync.service.ts | 11 + .../accounting/expense/sync/sync.service.ts | 11 + .../incomestatement/sync/sync.service.ts | 10 + .../accounting/invoice/sync/sync.service.ts | 11 +- .../src/accounting/item/sync/sync.service.ts | 10 + .../journalentry/sync/sync.service.ts | 10 + .../accounting/payment/sync/sync.service.ts | 10 + .../phonenumber/sync/sync.service.ts | 10 + .../purchaseorder/sync/sync.service.ts | 11 +- .../accounting/taxrate/sync/sync.service.ts | 11 +- .../trackingcategory/sync/sync.service.ts | 11 +- .../transaction/sync/sync.service.ts | 10 + .../vendorcredit/sync/sync.service.ts | 11 +- .../ats/activity/services/activity.service.ts | 10 +- .../api/src/ats/activity/sync/sync.service.ts | 2 +- .../src/ats/activity/types/model.unified.ts | 7 +- packages/api/src/ats/ats.module.ts | 3 - .../ats/attachment/services/ashby/mappers.ts | 1 - .../attachment/services/attachment.service.ts | 9 +- .../src/ats/attachment/sync/sync.service.ts | 2 +- .../src/ats/attachment/types/model.unified.ts | 7 +- .../src/ats/eeocs/services/eeocs.service.ts | 24 +- .../api/src/ats/eeocs/types/model.unified.ts | 35 +- .../ats/interview/services/ashby/mappers.ts | 3 +- .../interview/services/interview.service.ts | 5 +- .../src/ats/interview/types/model.unified.ts | 4 +- .../api/src/ats/job/services/ashby/mappers.ts | 3 +- .../api/src/ats/job/services/job.service.ts | 10 +- .../api/src/ats/job/types/model.unified.ts | 6 +- .../src/ats/offer/services/ashby/mappers.ts | 3 +- .../src/ats/offer/services/offer.service.ts | 6 +- .../api/src/ats/offer/types/model.unified.ts | 12 +- .../scorecard/services/scorecard.service.ts | 11 +- .../src/ats/scorecard/types/model.unified.ts | 8 +- .../api/src/ats/tag/services/tag.service.ts | 28 +- .../src/ats/user/services/ashby/mappers.ts | 3 +- .../api/src/ats/user/services/user.service.ts | 6 +- .../api/src/ats/user/types/model.unified.ts | 9 +- .../api/src/crm/@webhook/handler.module.ts | 1 + .../crm/company/services/company.service.ts | 6 +- .../crm/company/services/pipedrive/mappers.ts | 2 +- .../src/crm/company/services/zoho/mappers.ts | 3 +- .../src/crm/company/types/model.unified.ts | 2 +- .../api/src/crm/contact/contact.controller.ts | 13 - .../engagement/services/engagement.service.ts | 10 +- .../engagement/services/zendesk/mappers.ts | 2 +- .../src/crm/engagement/types/model.unified.ts | 7 +- .../api/src/crm/task/services/task.service.ts | 10 +- .../api/src/crm/task/services/zoho/mappers.ts | 6 +- .../api/src/crm/task/types/model.unified.ts | 3 +- .../filestorage/file/services/file.service.ts | 14 +- .../folder/services/folder.service.ts | 12 +- .../permission/services/permission.service.ts | 10 +- .../permission/types/model.unified.ts | 7 +- .../api/src/ticketing/@lib/@utils/index.ts | 15 + .../attachment/attachment.controller.ts | 4 +- .../collection/services/collection.service.ts | 9 +- .../collection/services/jira/mappers.ts | 2 +- .../collection/services/jira/types.ts | 6 +- .../collection/types/model.unified.ts | 4 +- .../comment/services/comment.service.ts | 65 +- .../comment/services/front/mappers.ts | 2 +- .../comment/services/gorgias/index.ts | 36 +- .../comment/services/gorgias/mappers.ts | 35 +- .../comment/services/jira/mappers.ts | 2 +- .../comment/services/zendesk/mappers.ts | 3 +- .../ticketing/comment/types/model.unified.ts | 4 +- .../src/ticketing/tag/services/jira/index.ts | 24 +- .../ticketing/tag/services/jira/mappers.ts | 2 +- .../ticket/services/front/mappers.ts | 9 +- .../ticket/services/gitlab/mappers.ts | 2 +- .../ticket/services/gorgias/index.ts | 4 +- .../ticket/services/gorgias/mappers.ts | 8 +- .../ticket/services/hubspot/mappers.ts | 3 +- .../ticketing/ticket/services/jira/index.ts | 53 +- .../ticketing/ticket/services/jira/mappers.ts | 27 +- .../ticketing/ticket/services/jira/types.ts | 3 +- .../ticket/services/ticket.service.ts | 49 +- .../ticket/services/zendesk/mappers.ts | 2 +- .../ticketing/ticket/types/model.unified.ts | 14 +- 89 files changed, 1357 insertions(+), 284 deletions(-) diff --git a/ngrok.yml b/ngrok.yml index e0f328e08..f0fb1a0c6 100644 --- a/ngrok.yml +++ b/ngrok.yml @@ -1,5 +1,5 @@ version: 2 -authtoken: NGROK_TOKEN +authtoken: 2huTZnkO3YRlTiOAQCGT8BnN6LH_kq8QUdFZN7KDimhvj3K8 log_level: debug log: stdout @@ -7,4 +7,4 @@ tunnels: api-tunnel: proto: http addr: 3000 - domain: NGROK_DOMAIN \ No newline at end of file + domain: prepared-wildcat-infinitely.ngrok-free.app \ No newline at end of file diff --git a/packages/api/prisma/schema.prisma b/packages/api/prisma/schema.prisma index 76e14358d..df18fead5 100644 --- a/packages/api/prisma/schema.prisma +++ b/packages/api/prisma/schema.prisma @@ -65,7 +65,7 @@ model api_keys { /// This model or at least one of its fields has comments in the database, and requires an additional setup for migrations: Read more: https://pris.ly/d/database-comments model attribute { - id_attribute String @id(map: "pk_attribute") @db.Uuid + id_attribute String @id(map: "pk_attribute") @db.Uuid status String ressource_owner_type String slug String @@ -73,11 +73,13 @@ model attribute { data_type String remote_id String source String - id_entity String? @db.Uuid - id_project String @db.Uuid + id_entity String? @db.Uuid + id_project String @db.Uuid scope String - id_consumer String? @db.Uuid - entity entity? @relation(fields: [id_entity], references: [id_entity], onDelete: NoAction, onUpdate: NoAction, map: "fk_32") + id_consumer String? @db.Uuid + created_at DateTime @db.Timestamptz(6) + modified_at DateTime @db.Timestamptz(6) + entity entity? @relation(fields: [id_entity], references: [id_entity], onDelete: NoAction, onUpdate: NoAction, map: "fk_32") value value[] @@index([id_entity], map: "fk_attribute_entityid") @@ -123,11 +125,12 @@ model crm_addresses { postal_code String? country String? address_type String? + id_crm_company String? @db.Uuid + id_crm_contact String? @db.Uuid + id_connection String @db.Uuid created_at DateTime @db.Timestamp(6) modified_at DateTime @db.Timestamp(6) owner_type String - id_crm_company String? @db.Uuid - id_crm_contact String? @db.Uuid crm_contacts crm_contacts? @relation(fields: [id_crm_contact], references: [id_crm_contact], onDelete: NoAction, onUpdate: NoAction, map: "fk_14") crm_companies crm_companies? @relation(fields: [id_crm_company], references: [id_crm_company], onDelete: NoAction, onUpdate: NoAction, map: "fk_15") @@ -146,6 +149,7 @@ model crm_companies { remote_platform String? id_crm_user String? @db.Uuid id_linked_user String? @db.Uuid + id_connection String @db.Uuid crm_addresses crm_addresses[] crm_users crm_users? @relation(fields: [id_crm_user], references: [id_crm_user], onDelete: NoAction, onUpdate: NoAction, map: "fk_24") crm_deals crm_deals[] @@ -161,14 +165,15 @@ model crm_companies { /// This model or at least one of its fields has comments in the database, and requires an additional setup for migrations: Read more: https://pris.ly/d/database-comments model crm_contacts { id_crm_contact String @id(map: "pk_crm_contacts") @db.Uuid - first_name String - last_name String - created_at DateTime @db.Timestamp(6) - modified_at DateTime @db.Timestamp(6) - remote_id String - remote_platform String + first_name String? + last_name String? + created_at DateTime? @db.Timestamp(6) + modified_at DateTime? @db.Timestamp(6) + remote_id String? + remote_platform String? id_crm_user String? @db.Uuid id_linked_user String? @db.Uuid + id_connection String @db.Uuid crm_addresses crm_addresses[] crm_users crm_users? @relation(fields: [id_crm_user], references: [id_crm_user], onDelete: NoAction, onUpdate: NoAction, map: "fk_23") crm_email_addresses crm_email_addresses[] @@ -192,6 +197,7 @@ model crm_deals { id_crm_deals_stage String? @db.Uuid id_linked_user String? @db.Uuid id_crm_company String? @db.Uuid + id_connection String @db.Uuid crm_deals_stages crm_deals_stages? @relation(fields: [id_crm_deals_stage], references: [id_crm_deals_stage], onDelete: NoAction, onUpdate: NoAction, map: "fk_21") crm_users crm_users? @relation(fields: [id_crm_user], references: [id_crm_user], onDelete: NoAction, onUpdate: NoAction, map: "fk_22") crm_companies crm_companies? @relation(fields: [id_crm_company], references: [id_crm_company], onDelete: NoAction, onUpdate: NoAction, map: "fk_47_1") @@ -211,6 +217,7 @@ model crm_deals_stages { id_linked_user String? @db.Uuid remote_id String? remote_platform String? + id_connection String @db.Uuid crm_deals crm_deals[] } @@ -224,6 +231,7 @@ model crm_email_addresses { modified_at DateTime @db.Timestamp(6) id_crm_company String? @db.Uuid id_crm_contact String? @db.Uuid + id_connection String @db.Uuid crm_companies crm_companies? @relation(fields: [id_crm_company], references: [id_crm_company], onDelete: NoAction, onUpdate: NoAction, map: "fk_16") crm_contacts crm_contacts? @relation(fields: [id_crm_contact], references: [id_crm_contact], onDelete: NoAction, onUpdate: NoAction, map: "fk_3") @@ -235,6 +243,7 @@ model crm_engagement_contacts { id_crm_engagement_contact String @id(map: "pk_crm_engagement_contact") @db.Uuid id_crm_contact String? @db.Uuid id_crm_engagement String @db.Uuid + id_connection String @db.Uuid crm_engagements crm_engagements @relation(fields: [id_crm_engagement], references: [id_crm_engagement], onDelete: NoAction, onUpdate: NoAction, map: "fk_30") @@index([id_crm_engagement], map: "fk_crm_engagement_contacts_crmengagementid") @@ -257,6 +266,7 @@ model crm_engagements { remote_platform String? id_crm_company String? @db.Uuid id_crm_user String? @db.Uuid + id_connection String @db.Uuid crm_engagement_contacts crm_engagement_contacts[] crm_companies crm_companies? @relation(fields: [id_crm_company], references: [id_crm_company], onDelete: NoAction, onUpdate: NoAction, map: "fk_29") crm_users crm_users? @relation(fields: [id_crm_user], references: [id_crm_user], onDelete: NoAction, onUpdate: NoAction, map: "fk_crm_engagement_crm_user") @@ -277,6 +287,7 @@ model crm_notes { remote_id String? remote_platform String? id_crm_user String? @db.Uuid + id_connection String @db.Uuid crm_companies crm_companies? @relation(fields: [id_crm_company], references: [id_crm_company], onDelete: NoAction, onUpdate: NoAction, map: "fk_18") crm_contacts crm_contacts? @relation(fields: [id_crm_contact], references: [id_crm_contact], onDelete: NoAction, onUpdate: NoAction, map: "fk_19") crm_deals crm_deals? @relation(fields: [id_crm_deal], references: [id_crm_deal], onDelete: NoAction, onUpdate: NoAction, map: "fk_20") @@ -290,13 +301,14 @@ model crm_notes { /// This model or at least one of its fields has comments in the database, and requires an additional setup for migrations: Read more: https://pris.ly/d/database-comments model crm_phone_numbers { id_crm_phone_number String @id(map: "pk_crm_contacts_phone_numbers") @db.Uuid - phone_number String - phone_type String - owner_type String + phone_number String? + phone_type String? + owner_type String? created_at DateTime @db.Timestamp(6) modified_at DateTime @db.Timestamp(6) id_crm_company String? @db.Uuid id_crm_contact String? @db.Uuid + id_connection String @db.Uuid crm_companies crm_companies? @relation(fields: [id_crm_company], references: [id_crm_company], onDelete: NoAction, onUpdate: NoAction, map: "fk_17") crm_contacts crm_contacts? @relation(fields: [id_crm_contact], references: [id_crm_contact], onDelete: NoAction, onUpdate: NoAction, map: "fk_phonenumber_crm_contactid") @@ -319,6 +331,7 @@ model crm_tasks { id_linked_user String? @db.Uuid remote_id String? remote_platform String? + id_connection String @db.Uuid crm_users crm_users? @relation(fields: [id_crm_user], references: [id_crm_user], onDelete: NoAction, onUpdate: NoAction, map: "fk_25") crm_companies crm_companies? @relation(fields: [id_crm_company], references: [id_crm_company], onDelete: NoAction, onUpdate: NoAction, map: "fk_26") crm_deals crm_deals? @relation(fields: [id_crm_deal], references: [id_crm_deal], onDelete: NoAction, onUpdate: NoAction, map: "fk_27") @@ -337,6 +350,7 @@ model crm_users { id_linked_user String? @db.Uuid remote_id String? remote_platform String? + id_connection String @db.Uuid crm_companies crm_companies[] crm_contacts crm_contacts[] crm_deals crm_deals[] @@ -366,6 +380,8 @@ model cs_values { model entity { id_entity String @id(map: "pk_entity") @db.Uuid ressource_owner_id String @db.Uuid + created_at DateTime @db.Timestamptz(6) + modified_at DateTime @db.Timestamptz(6) attribute attribute[] value value[] } @@ -461,6 +477,7 @@ model tcg_accounts { created_at DateTime @db.Timestamp(6) modified_at DateTime @db.Timestamp(6) id_linked_user String? @db.Uuid + id_connection String @db.Uuid tcg_contacts tcg_contacts[] } @@ -477,6 +494,7 @@ model tcg_attachments { id_linked_user String? @db.Uuid id_tcg_ticket String? @db.Uuid id_tcg_comment String? @db.Uuid + id_connection String @db.Uuid tcg_tickets tcg_tickets? @relation(fields: [id_tcg_ticket], references: [id_tcg_ticket], onDelete: NoAction, onUpdate: NoAction, map: "fk_50") tcg_comments tcg_comments? @relation(fields: [id_tcg_comment], references: [id_tcg_comment], onDelete: NoAction, onUpdate: NoAction, map: "fk_51") @@ -495,6 +513,7 @@ model tcg_collections { created_at DateTime @db.Timestamp(6) modified_at DateTime @db.Timestamp(6) id_linked_user String @db.Uuid + id_connection String @db.Uuid } /// This model or at least one of its fields has comments in the database, and requires an additional setup for migrations: Read more: https://pris.ly/d/database-comments @@ -513,6 +532,7 @@ model tcg_comments { id_tcg_contact String? @db.Uuid id_tcg_user String? @db.Uuid id_linked_user String? @db.Uuid + id_connection String @db.Uuid tcg_attachments tcg_attachments[] tcg_tickets tcg_tickets? @relation(fields: [id_tcg_ticket], references: [id_tcg_ticket], onDelete: NoAction, onUpdate: NoAction, map: "fk_40_1") tcg_contacts tcg_contacts? @relation(fields: [id_tcg_contact], references: [id_tcg_contact], onDelete: NoAction, onUpdate: NoAction, map: "fk_41") @@ -535,6 +555,7 @@ model tcg_contacts { modified_at DateTime? @db.Timestamp(6) id_tcg_account String? @db.Uuid id_linked_user String? @db.Uuid + id_connection String @db.Uuid tcg_comments tcg_comments[] tcg_accounts tcg_accounts? @relation(fields: [id_tcg_account], references: [id_tcg_account], onDelete: NoAction, onUpdate: NoAction, map: "fk_49") @@ -546,10 +567,11 @@ model tcg_tags { name String? remote_id String? remote_platform String? + id_tcg_ticket String? @db.Uuid created_at DateTime @db.Timestamp(6) modified_at DateTime @db.Timestamp(6) - id_tcg_ticket String? @db.Uuid id_linked_user String? @db.Uuid + id_connection String @db.Uuid tcg_tickets tcg_tickets? @relation(fields: [id_tcg_ticket], references: [id_tcg_ticket], onDelete: NoAction, onUpdate: NoAction, map: "fk_48") @@index([id_tcg_ticket], map: "fk_tcg_tag_tcg_ticketid") @@ -564,6 +586,7 @@ model tcg_teams { created_at DateTime @db.Timestamp(6) modified_at DateTime @db.Timestamp(6) id_linked_user String? @db.Uuid + id_connection String @db.Uuid } /// This model or at least one of its fields has comments in the database, and requires an additional setup for migrations: Read more: https://pris.ly/d/database-comments @@ -587,6 +610,7 @@ model tcg_tickets { creator_type String? id_tcg_user String? @db.Uuid id_linked_user String @db.Uuid + id_connection String @db.Uuid tcg_attachments tcg_attachments[] tcg_comments tcg_comments[] tcg_tags tcg_tags[] @@ -605,6 +629,7 @@ model tcg_users { created_at DateTime? @db.Timestamp(6) modified_at DateTime? @db.Timestamp(6) id_linked_user String? @db.Uuid + id_connection String @db.Uuid tcg_comments tcg_comments[] } @@ -614,6 +639,8 @@ model value { data String id_entity String @db.Uuid id_attribute String @db.Uuid + created_at DateTime @db.Timestamptz(6) + modified_at DateTime @db.Timestamptz(6) attribute attribute @relation(fields: [id_attribute], references: [id_attribute], onDelete: NoAction, onUpdate: NoAction, map: "fk_33") entity entity @relation(fields: [id_entity], references: [id_entity], onDelete: NoAction, onUpdate: NoAction, map: "fk_34") @@ -680,20 +707,21 @@ model fs_drives { remote_id String? created_at DateTime @db.Timestamp(6) modified_at DateTime @db.Timestamp(6) -} + id_connection String @db.Uuid +} model fs_files { id_fs_file String @id(map: "pk_fs_files") @db.Uuid name String? - type String? file_url String? mime_type String? size BigInt? remote_id String? + id_fs_permission String? @db.Uuid id_fs_folder String? @db.Uuid created_at DateTime @db.Timestamp(6) modified_at DateTime @db.Timestamp(6) - id_fs_permission String? @db.Uuid + id_connection String @db.Uuid @@index([id_fs_folder], map: "fk_fs_file_folderid") @@index([id_fs_permission], map: "fk_fs_file_permissionid") @@ -707,9 +735,10 @@ model fs_folders { description String? parent_folder String? @db.Uuid remote_id String? - created_at DateTime @db.Timestamp(6) + created_at DateTime @db.Timestamp(6) modified_at DateTime @db.Timestamp(6) id_fs_drive String? @db.Uuid + id_connection String @db.Uuid id_fs_permission String? @db.Uuid @@index([id_fs_drive], map: "fk_fs_folder_driveid") @@ -720,27 +749,30 @@ model fs_folders { model fs_permissions { id_fs_permission String @id(map: "pk_fs_permissions") @db.Uuid remote_id String? - user String? @db.Uuid + user String? @db.Uuid group String? @db.Uuid - type String[] + type String? roles String[] created_at DateTime @db.Timestamp(6) modified_at DateTime @db.Timestamp(6) + id_connection String @db.Uuid } model fs_shared_links { id_fs_shared_link String @id(map: "pk_fs_shared_links") @db.Uuid url String? download_url String? - id_fs_folder String? @db.Uuid - id_fs_file String? @db.Uuid scope String? password_protected Boolean password String? expires_at DateTime? @db.Timestamptz(6) created_at DateTime @db.Timestamptz(6) modified_at DateTime @db.Timestamptz(6) -} + id_connection String @db.Uuid + id_fs_folder String? @db.Uuid + id_fs_file String? @db.Uuid + remote_id String? +} /// This model or at least one of its fields has comments in the database, and requires an additional setup for migrations: Read more: https://pris.ly/d/database-comments model ats_activities { @@ -754,6 +786,7 @@ model ats_activities { remote_created_at DateTime? @db.Timestamp(6) created_at DateTime @db.Timestamp(6) modified_at DateTime @db.Timestamp(6) + id_connection String @db.Uuid @@index([id_ats_candidate], map: "fk_activity_candidate") } @@ -762,10 +795,6 @@ model ats_activities { model ats_applications { id_ats_application String @id(map: "pk_ats_applications") @db.Uuid remote_id String? - created_at DateTime @db.Timestamp(6) - modified_at DateTime @db.Timestamp(6) - id_ats_candidate String? @db.Uuid - id_ats_job String? @db.Uuid applied_at DateTime? @db.Timestamp(6) rejected_at DateTime? @db.Timestamp(6) offers String[] @@ -773,6 +802,11 @@ model ats_applications { credited_to String? @db.Uuid current_stage String? @db.Uuid reject_reason String? + id_ats_candidate String? @db.Uuid + id_ats_job String? @db.Uuid + created_at DateTime @db.Timestamp(6) + modified_at DateTime @db.Timestamp(6) + id_connection String @db.Uuid @@index([id_ats_job], map: "fk_ats_application_ats_job_id") @@index([id_ats_candidate], map: "fk_ats_application_atscandidateid") @@ -790,6 +824,7 @@ model ats_candidate_attachments { created_at DateTime @db.Timestamp(6) modified_at DateTime @db.Timestamp(6) id_ats_candidate String @db.Uuid + id_connection String @db.Uuid @@index([id_ats_candidate], map: "fk_ats_candidate_attachment_candidateid_index") } @@ -820,12 +855,9 @@ model ats_candidate_phone_numbers { model ats_candidate_tags { id_ats_candidate_tag String @id(map: "pk_ats_candidate_tags") @db.Uuid name String? - id_ats_candidate String? @db.Uuid remote_id String? created_at DateTime @db.Timestamp(6) modified_at DateTime @db.Timestamp(6) - - @@index([id_ats_candidate], map: "fk_candidates_candidatestags") } model ats_candidate_urls { @@ -855,6 +887,8 @@ model ats_candidates { is_private Boolean? email_reachable Boolean? locations String? + tags String[] + id_connection String @db.Uuid } model ats_departments { @@ -863,6 +897,7 @@ model ats_departments { remote_id String? created_at DateTime @db.Timestamp(6) modified_at DateTime @db.Timestamp(6) + id_connection String @db.Uuid } /// This model or at least one of its fields has comments in the database, and requires an additional setup for migrations: Read more: https://pris.ly/d/database-comments @@ -877,6 +912,7 @@ model ats_eeocs { remote_id String? created_at DateTime @db.Timestamp(6) modified_at DateTime @db.Timestamp(6) + id_connection String @db.Uuid @@index([id_ats_candidate], map: "fk_candidate_eeocsid") } @@ -885,8 +921,6 @@ model ats_eeocs { model ats_interviews { id_ats_interview String @id(map: "pk_ats_interviews") @db.Uuid status String? - id_ats_application String? @db.Uuid - id_ats_job_interview_stage String? @db.Uuid organized_by String? @db.Uuid interviewers String[] location String? @@ -895,8 +929,11 @@ model ats_interviews { remote_created_at DateTime? @db.Timestamp(6) remote_updated_at DateTime? @db.Timestamp(6) remote_id String? + id_ats_application String? @db.Uuid + id_ats_job_interview_stage String? @db.Uuid created_at DateTime @db.Timestamp(6) modified_at DateTime @db.Timestamp(6) + id_connection String @db.Uuid @@index([id_ats_application], map: "fk_applications_interviews") @@index([id_ats_job_interview_stage], map: "fk_id_ats_job_interview_stageid") @@ -911,6 +948,7 @@ model ats_job_interview_stages { created_at DateTime @db.Timestamp(6) modified_at DateTime @db.Timestamp(6) id_ats_job String? @db.Uuid + id_connection String @db.Uuid @@index([id_ats_job], map: "fk_ats_jobs_ats_jobinterview_id") } @@ -933,6 +971,7 @@ model ats_jobs { remote_updated_at DateTime? @db.Timestamp(6) created_at DateTime @db.Timestamp(6) modified_at DateTime @db.Timestamp(6) + id_connection String @db.Uuid } /// This model or at least one of its fields has comments in the database, and requires an additional setup for migrations: Read more: https://pris.ly/d/database-comments @@ -948,6 +987,7 @@ model ats_offers { created_at DateTime @db.Timestamp(6) modified_at DateTime @db.Timestamp(6) id_ats_application String @db.Uuid + id_connection String @db.Uuid @@index([id_ats_application], map: "fk_ats_offers_applicationid") } @@ -960,6 +1000,7 @@ model ats_offices { modified_at DateTime @db.Timestamp(6) name String? location String? + id_connection String @db.Uuid } model ats_reject_reasons { @@ -968,6 +1009,7 @@ model ats_reject_reasons { remote_id String? modified_at DateTime @db.Timestamp(6) created_at DateTime @db.Timestamp(6) + id_connection String @db.Uuid } /// This model or at least one of its fields has comments in the database, and requires an additional setup for migrations: Read more: https://pris.ly/d/database-comments @@ -981,6 +1023,7 @@ model ats_scorecards { submitted_at DateTime? @db.Timestamp(6) created_at DateTime @db.Timestamp(6) modified_at DateTime @db.Timestamp(6) + id_connection String @db.Uuid @@index([id_ats_application], map: "fk_applications_scorecard") @@index([id_ats_interview], map: "fk_interviews_scorecards") @@ -999,25 +1042,604 @@ model ats_users { remote_modified_at DateTime? @db.Timestamp(6) created_at DateTime @db.Timestamp(6) modified_at DateTime @db.Timestamp(6) + id_connection String @db.Uuid } /// This model or at least one of its fields has comments in the database, and requires an additional setup for migrations: Read more: https://pris.ly/d/database-comments model fs_groups { id_fs_group String @id(map: "pk_fs_groups") @db.Uuid name String? - users Json? + users String[] remote_id String? remote_was_deleted Boolean created_at DateTime @db.Timestamp(6) modified_at DateTime @db.Timestamp(6) + id_connection String @db.Uuid } model fs_users { - id_fs_user String @id(map: "pk_fs_users") @db.Uuid - name String? - email String? - is_me Boolean - remote_id String? - created_at DateTime @db.Timestamp(6) - modified_at DateTime @db.Timestamp(6) + id_fs_user String @id(map: "pk_fs_users") @db.Uuid + name String? + email String? + is_me Boolean + remote_id String? + created_at DateTime @db.Timestamp(6) + modified_at DateTime @db.Timestamp(6) + id_connection String @db.Uuid +} + +/// This model or at least one of its fields has comments in the database, and requires an additional setup for migrations: Read more: https://pris.ly/d/database-comments +model acc_accounting_periods { + id_acc_accounting_period String @id(map: "pk_acc_accounting_periods") @db.Uuid + remote_id String? + created_at DateTime @db.Timestamptz(6) + modified_at DateTime @db.Timestamptz(6) + name String? + status String? + start_date DateTime? @db.Timestamptz(6) + end_date DateTime? @db.Timestamptz(6) + id_connection String @db.Uuid +} + +/// This model or at least one of its fields has comments in the database, and requires an additional setup for migrations: Read more: https://pris.ly/d/database-comments +model acc_accounts { + id_acc_account String @id(map: "pk_acc_accounts") @db.Uuid + name String? + description String? + classification String? + type String? + status String? + current_balance BigInt? + currency String? + account_number String? + parent_account String? @db.Uuid + remote_id String? + id_acc_company_info String? @db.Uuid + created_at DateTime @db.Timestamptz(6) + modified_at DateTime @db.Timestamptz(6) + id_connection String @db.Uuid + + @@index([id_acc_company_info], map: "fk_accounts_companyinfo_id") +} + +/// This model or at least one of its fields has comments in the database, and requires an additional setup for migrations: Read more: https://pris.ly/d/database-comments +model acc_addresses { + id_acc_address String @id(map: "pk_acc_addresses") @db.Uuid + type String? + street_1 String? + street_2 String? + city String? + state String? + country_subdivision String? + country String? + zip String? + created_at DateTime @db.Timestamptz(6) + modified_at DateTime @db.Timestamptz(6) + id_acc_contact String? @db.Uuid + id_acc_company_info String? @db.Uuid + id_connection String @db.Uuid + + @@index([id_acc_company_info], map: "fk_acc_company_info_acc_adresses") + @@index([id_acc_contact], map: "fk_acc_contact_acc_addresses") +} + +model acc_attachments { + id_acc_attachment String @id(map: "pk_acc_attachments") @db.Uuid + file_name String? + file_url String? + remote_id String? + id_acc_account String? @db.Uuid + created_at DateTime @db.Timestamptz(6) + modified_at DateTime @db.Timestamptz(6) + id_connection String @db.Uuid + + @@index([id_acc_account], map: "fk_acc_attachments_accountid") +} + +/// This model or at least one of its fields has comments in the database, and requires an additional setup for migrations: Read more: https://pris.ly/d/database-comments +model acc_balance_sheets { + id_acc_balance_sheet String @id(map: "pk_acc_balance_sheets") @db.Uuid + name String? + currency String? + id_acc_company_info String? @db.Uuid + date DateTime? @db.Timestamptz(6) + net_assets BigInt? + assets String[] + liabilities String[] + equity String[] + remote_generated_at DateTime? @db.Timestamptz(6) + remote_id String? + created_at DateTime @db.Timestamptz(6) + modified_at DateTime @db.Timestamptz(6) + id_connection String @db.Uuid + + @@index([id_acc_company_info], map: "fk_balancesheetcompanyinfoid") +} + +/// This model or at least one of its fields has comments in the database, and requires an additional setup for migrations: Read more: https://pris.ly/d/database-comments +model acc_balance_sheets_report_items { + id_acc_balance_sheets_report_item String @id(map: "pk_acc_balance_sheets_report_items") @db.Uuid + remote_id String? + created_at DateTime @db.Timestamptz(6) + modified_at DateTime @db.Timestamptz(6) + name String? + value BigInt? + parent_item String? @db.Uuid + id_acc_company_info String? @db.Uuid +} + +/// This model or at least one of its fields has comments in the database, and requires an additional setup for migrations: Read more: https://pris.ly/d/database-comments +model acc_cash_flow_statement_report_items { + id_acc_cash_flow_statement_report_item String @id(map: "pk_acc_cash_flow_statement_report_items") @db.Uuid + name String? + value BigInt? + type String? + parent_item String? @db.Uuid + remote_generated_at DateTime? @db.Timestamptz(6) + remote_id String? + modified_at DateTime @db.Timestamptz(6) + created_at DateTime @db.Timestamptz(6) + id_acc_cash_flow_statement String? @db.Uuid + + @@index([id_acc_cash_flow_statement], map: "fk_cashflow_statement_acc_cash_flow_statement_report_item") +} + +model acc_cash_flow_statements { + id_acc_cash_flow_statement String @id(map: "pk_acc_cash_flow_statements") @db.Uuid + name String? + currency String? + company String? @db.Uuid + start_period DateTime? @db.Timestamptz(6) + end_period DateTime? @db.Timestamptz(6) + cash_at_beginning_of_period BigInt? + cash_at_end_of_period BigInt? + remote_generated_at DateTime? @db.Timestamptz(6) + remote_id String? + modified_at DateTime @db.Timestamptz(6) + created_at DateTime @db.Timestamptz(6) + id_connection String @db.Uuid +} + +model acc_company_infos { + id_acc_company_info String @id(map: "pk_acc_company_infos") @db.Uuid + name String? + legal_name String? + tax_number String? + fiscal_year_end_month Int? + fiscal_year_end_day Int? + currency String? + remote_created_at DateTime? @db.Timestamptz(6) + remote_id String? + urls String[] + created_at DateTime @db.Timestamptz(6) + modified_at DateTime @db.Timestamptz(6) + id_connection String @db.Uuid + tracking_categories String[] +} + +/// This model or at least one of its fields has comments in the database, and requires an additional setup for migrations: Read more: https://pris.ly/d/database-comments +model acc_contacts { + id_acc_contact String @id(map: "pk_acc_contacts") @db.Uuid + name String? + is_supplier Boolean? + is_customer Boolean? + email_address String? + tax_number String? + status String? + currency String? + remote_updated_at String? + id_acc_company_info String? @db.Uuid + id_connection String @db.Uuid + remote_id String? + created_at DateTime @db.Timestamptz(6) + modified_at DateTime @db.Timestamptz(6) + + @@index([id_acc_company_info], map: "fk_acc_contact_company") +} + +/// This model or at least one of its fields has comments in the database, and requires an additional setup for migrations: Read more: https://pris.ly/d/database-comments +model acc_credit_notes { + id_acc_credit_note String @id(map: "pk_acc_credit_notes") @db.Uuid + transaction_date DateTime? @db.Timestamptz(6) + status String? + number String? + id_acc_contact String? @db.Uuid + company String? @db.Uuid + exchange_rate String? + total_amount BigInt? + remaining_credit BigInt? + tracking_categories String[] + currency String? + remote_created_at DateTime? @db.Timestamptz(6) + remote_updated_at DateTime? @db.Timestamptz(6) + payments String[] + applied_payments String[] + id_acc_accounting_period String? @db.Uuid + remote_id String? + modified_at DateTime @db.Timetz(6) + created_at DateTime @db.Timetz(6) + id_connection String @db.Uuid +} + +model acc_expense_lines { + id_acc_expense_line String @id(map: "pk_acc_expense_lines") @db.Uuid + id_acc_expense String @db.Uuid + remote_id String? + net_amount BigInt? + currency String? + description String? + exchange_rate String? + created_at DateTime @db.Timestamptz(6) + modified_at DateTime @db.Timestamptz(6) + id_connection String @db.Uuid + + @@index([id_acc_expense], map: "fk_acc_expense_expense_lines_index") +} + +/// This model or at least one of its fields has comments in the database, and requires an additional setup for migrations: Read more: https://pris.ly/d/database-comments +model acc_expenses { + id_acc_expense String @id(map: "pk_acc_expenses") @db.Uuid + transaction_date DateTime? @db.Timestamptz(6) + total_amount BigInt? + sub_total BigInt? + total_tax_amount BigInt? + currency String? + exchange_rate String? + memo String? + id_acc_account String? @db.Uuid + id_acc_contact String? @db.Uuid + id_acc_company_info String? @db.Uuid + remote_id String? + remote_created_at DateTime? @db.Timestamptz(6) + created_at DateTime @db.Timestamptz(6) + modified_at DateTime @db.Timestamptz(6) + id_connection String @db.Uuid + tracking_categories String[] + + @@index([id_acc_account], map: "fk_acc_account_acc_expense_index") + @@index([id_acc_company_info], map: "fk_acc_expense_acc_company_index") + @@index([id_acc_contact], map: "fk_acc_expense_acc_contact_index") +} + +model acc_income_statements { + id_acc_income_statement String @id(map: "pk_acc_income_statements") @db.Uuid + name String? + currency String? + start_period DateTime? @db.Timestamptz(6) + end_period DateTime? @db.Timestamptz(6) + gross_profit BigInt? + net_operating_income BigInt? + net_income BigInt? + remote_id String? + created_at DateTime @db.Timestamptz(6) + modified_at DateTime @db.Timestamptz(6) + id_connection String @db.Uuid +} + +/// This model or at least one of its fields has comments in the database, and requires an additional setup for migrations: Read more: https://pris.ly/d/database-comments +model acc_invoices { + id_acc_invoice String @id(map: "pk_acc_invoices") @db.Uuid + type String? + number String? + issue_date DateTime? @db.Timestamptz(6) + due_date DateTime? @db.Timestamptz(6) + paid_on_date DateTime? @db.Timestamptz(6) + memo String? + currency String? + exchange_rate String? + total_discount BigInt? + sub_total BigInt? + status String? + total_tax_amount BigInt? + total_amount BigInt? + balance BigInt? + remote_updated_at DateTime? @db.Timestamptz(6) + remote_id String? + created_at DateTime @db.Timestamptz(6) + modified_at DateTime @db.Timestamptz(6) + id_connection String @db.Uuid + id_acc_contact String? @db.Uuid + id_acc_accounting_period String? @db.Uuid + tracking_categories String[] + + @@index([id_acc_accounting_period], map: "fk_acc_invoice_accounting_period_index") + @@index([id_acc_contact], map: "fk_invoice_contactid") +} + +model acc_invoices_line_items { + id_acc_invoices_line_item String @id(map: "pk_acc_invoices_line_items") @db.Uuid + remote_id String? + description String? + unit_price BigInt? + quantity BigInt? + total_amount BigInt? + currency String? + exchange_rate String? + id_acc_invoice String @db.Uuid + id_acc_item String @db.Uuid + created_at DateTime @db.Timestamptz(6) + modified_at DateTime @db.Timestamptz(6) + id_connection String @db.Uuid + acc_tracking_categories String[] + + @@index([id_acc_invoice], map: "fk_acc_invoice_line_items_index") + @@index([id_acc_item], map: "fk_acc_items_lines_invoice_index") +} + +/// This model or at least one of its fields has comments in the database, and requires an additional setup for migrations: Read more: https://pris.ly/d/database-comments +model acc_items { + id_acc_item String @id(map: "pk_acc_items") @db.Uuid + name String? + status String? + unit_price BigInt? + purchase_price BigInt? + remote_updated_at DateTime? @db.Timestamptz(6) + remote_id String? + sales_account String? @db.Uuid + purchase_account String? @db.Uuid + id_acc_company_info String? @db.Uuid + created_at DateTime @db.Timestamptz(6) + modified_at DateTime @db.Timestamptz(6) + id_connection String @db.Uuid + + @@index([purchase_account], map: "fk_acc_item_acc_account") + @@index([id_acc_company_info], map: "fk_acc_item_acc_company_infos") + @@index([sales_account], map: "fk_acc_items_sales_account") +} + +model acc_journal_entries { + id_acc_journal_entry String @id(map: "pk_acc_journal_entries") @db.Uuid + transaction_date DateTime? @db.Timestamptz(6) + payments String[] + applied_payments String[] + memo String? + currency String? + exchange_rate String? + id_acc_company_info String @db.Uuid + journal_number String? + tracking_categories String[] + id_acc_accounting_period String? @db.Uuid + posting_status String? + remote_created_at DateTime? @db.Timestamptz(6) + remote_modiified_at DateTime? @db.Timestamptz(6) + id_connection String @db.Uuid + remote_id String + created_at DateTime @db.Timestamptz(6) + modified_at DateTime @db.Timestamptz(6) + + @@index([id_acc_accounting_period], map: "fk_journal_entry_accounting_period") + @@index([id_acc_company_info], map: "fk_journal_entry_companyinfo") +} + +model acc_journal_entries_lines { + id_acc_journal_entries_line String @id(map: "pk_acc_journal_entries_lines") @db.Uuid + net_amount BigInt? + tracking_categories String[] + currency String? + description String? + company String? @db.Uuid + contact String? @db.Uuid + exchange_rate String? + remote_id String? + created_at DateTime @db.Timestamptz(6) + modified_at DateTime @db.Timestamptz(6) + id_acc_journal_entry String @db.Uuid + + @@index([id_acc_journal_entry], map: "fk_journal_entries_entries_lines") +} + +/// This model or at least one of its fields has comments in the database, and requires an additional setup for migrations: Read more: https://pris.ly/d/database-comments +model acc_payments { + id_acc_payment String @id(map: "pk_acc_payments") @db.Uuid + id_acc_invoice String? @db.Uuid + transaction_date DateTime? @db.Timestamptz(6) + id_acc_contact String? @db.Uuid + id_acc_account String? @db.Uuid + currency String? + exchange_rate String? + total_amount BigInt? + type String? + remote_updated_at DateTime? @db.Timestamptz(6) + id_acc_company_info String? @db.Uuid + id_acc_accounting_period String? @db.Uuid + created_at DateTime @db.Timestamptz(6) + modified_at DateTime @db.Timestamptz(6) + id_connection String @db.Uuid + tracking_categories String[] + + @@index([id_acc_account], map: "fk_acc_payment_acc_account_index") + @@index([id_acc_company_info], map: "fk_acc_payment_acc_company_index") + @@index([id_acc_contact], map: "fk_acc_payment_acc_contact") + @@index([id_acc_accounting_period], map: "fk_acc_payment_accounting_period_index") + @@index([id_acc_invoice], map: "fk_acc_payment_invoiceid") +} + +/// This model or at least one of its fields has comments in the database, and requires an additional setup for migrations: Read more: https://pris.ly/d/database-comments +model acc_payments_line_items { + acc_payments_line_item String @id(map: "pk_acc_payments_line_items") @db.Uuid + id_acc_payment String @db.Uuid + applied_amount BigInt? + applied_date DateTime? @db.Timestamptz(6) + related_object_id String? @db.Uuid + related_object_type String? + remote_id String? + created_at DateTime @db.Timestamptz(6) + modified_at DateTime @db.Timestamptz(6) + id_connection String @db.Uuid + + @@index([id_acc_payment], map: "fk_acc_payment_line_items_index") +} + +/// This model or at least one of its fields has comments in the database, and requires an additional setup for migrations: Read more: https://pris.ly/d/database-comments +model acc_phone_numbers { + id_acc_phone_number String @id(map: "pk_acc_phone_numbers") @db.Uuid + number String? + type String? + created_at DateTime @db.Timestamptz(6) + modified_at DateTime @db.Timestamptz(6) + id_acc_company_info String? @db.Uuid + id_acc_contact String @db.Uuid + id_connection String @db.Uuid + + @@index([id_acc_contact], map: "fk_acc_phone_number_contact") + @@index([id_acc_company_info], map: "fk_company_infos_phone_number") +} + +/// This model or at least one of its fields has comments in the database, and requires an additional setup for migrations: Read more: https://pris.ly/d/database-comments +model acc_purchase_orders { + id_acc_purchase_order String @id(map: "pk_acc_purchase_orders") @db.Uuid + remote_id String? + status String? + issue_date DateTime? @db.Timestamptz(6) + purchase_order_number String? + delivery_date DateTime? @db.Timestamptz(6) + delivery_address String? @db.Uuid + customer String? @db.Uuid + vendor String? @db.Uuid + memo String? + company String? @db.Uuid + total_amount BigInt? + currency String? + exchange_rate String? + tracking_categories String[] + remote_created_at DateTime? @db.Timestamptz(6) + remote_updated_at DateTime? @db.Timestamptz(6) + created_at DateTime @db.Timestamptz(6) + modified_at DateTime @db.Timestamptz(6) + id_connection String @db.Uuid + id_acc_accounting_period String? @db.Uuid + + @@index([id_acc_accounting_period], map: "fk_purchaseorder_accountingperiod") +} + +model acc_purchase_orders_line_items { + id_acc_purchase_orders_line_item String @id(map: "pk_acc_purchase_orders_line_items") @db.Uuid + id_acc_purchase_order String @db.Uuid + remote_id String? + modified_at DateTime @db.Timestamptz(6) + created_at DateTime @db.Timestamptz(6) + description String? + unit_price BigInt? + quantity BigInt? + tracking_categories String[] + tax_amount BigInt? + total_line_amount BigInt? + currency String? + exchange_rate String? + id_acc_account String? @db.Uuid + id_acc_company String? @db.Uuid + + @@index([id_acc_purchase_order], map: "fk_purchaseorder_purchaseorderlineitems") +} + +model acc_report_items { + id_acc_report_item String @id(map: "pk_acc_report_items") @db.Uuid + name String? + value BigInt? + company String? @db.Uuid + parent_item String? @db.Uuid + remote_id String? + created_at DateTime @db.Timestamptz(6) + modified_at DateTime @db.Timestamptz(6) +} + +/// This model or at least one of its fields has comments in the database, and requires an additional setup for migrations: Read more: https://pris.ly/d/database-comments +model acc_tax_rates { + id_acc_tax_rate String @id(map: "pk_acc_tax_rates") @db.Uuid + remote_id String? + description String? + total_tax_ratge BigInt? + effective_tax_rate BigInt? + company String? @db.Uuid + id_connection String @db.Uuid + created_at DateTime @db.Timestamptz(6) + modified_at DateTime @db.Timestamptz(6) +} + +/// This model or at least one of its fields has comments in the database, and requires an additional setup for migrations: Read more: https://pris.ly/d/database-comments +model acc_tracking_categories { + id_acc_tracking_category String @id(map: "pk_acc_tracking_categories") @db.Uuid + remote_id String? + name String? + status String? + category_type String? + parent_category String? @db.Uuid + created_at DateTime @db.Timestamptz(6) + modified_at DateTime @db.Timestamptz(6) + id_connection String @db.Uuid +} + +/// This model or at least one of its fields has comments in the database, and requires an additional setup for migrations: Read more: https://pris.ly/d/database-comments +model acc_transactions { + id_acc_transaction String @id(map: "pk_acc_transactions") @db.Uuid + transaction_type String? + number BigInt? + transaction_date DateTime? @db.Timestamptz(6) + total_amount String? + exchange_rate String? + currency String? + tracking_categories String[] + id_acc_account String? @db.Uuid + id_acc_contact String? @db.Uuid + id_acc_company_info String? @db.Uuid + id_acc_accounting_period String? @db.Uuid + remote_id String + created_at DateTime @db.Timestamptz(6) + modified_at DateTime @db.Timestamptz(6) + id_connection String @db.Uuid +} + +/// This model or at least one of its fields has comments in the database, and requires an additional setup for migrations: Read more: https://pris.ly/d/database-comments +model acc_transactions_lines_items { + id_acc_transactions_lines_item String @id(map: "pk_acc_transactions_lines_items") @db.Uuid + memo String? + unit_price String? + quantity String? + total_line_amount String? + id_acc_tax_rate String? @db.Uuid + currency String? + exchange_rate String? + tracking_categories String[] + id_acc_company_info String? @db.Uuid + id_acc_item String? @db.Uuid + id_acc_account String? @db.Uuid + remote_id String? + created_at DateTime @db.Timetz(6) + modified_at DateTime @db.Timetz(6) + id_acc_transaction String? @db.Uuid + + @@index([id_acc_transaction], map: "fk_acc_transactions_lineitems") +} + +model acc_vendor_credit_lines { + id_acc_vendor_credit_line String @id(map: "pk_acc_vendor_credit_lines") @db.Uuid + net_amount BigInt? + tracking_categories String[] + description String? + account String? @db.Uuid + id_acc_account String? @db.Uuid + exchange_rate String? + id_acc_company_info String? @db.Uuid + remote_id String? + created_at DateTime @db.Timestamptz(6) + modified_at DateTime @db.Timestamptz(6) + id_acc_vendor_credit String? @db.Uuid +} + +/// This model or at least one of its fields has comments in the database, and requires an additional setup for migrations: Read more: https://pris.ly/d/database-comments +model acc_vendor_credits { + id_acc_vendor_credit String @id(map: "pk_acc_vendor_credits") @db.Uuid + id_connection String @db.Uuid + remote_id String? + created_at DateTime @db.Timestamptz(6) + modified_at DateTime @db.Timestamptz(6) + number String? + transaction_date DateTime? @db.Timestamptz(6) + vendor String? @db.Uuid + total_amount BigInt? + currency String? + exchange_rate String? + company String? @db.Uuid + tracking_categories String[] + accounting_period String? @db.Uuid } diff --git a/packages/api/src/@core/utils/types/interface.ts b/packages/api/src/@core/utils/types/interface.ts index 763a15852..f860a03e5 100644 --- a/packages/api/src/@core/utils/types/interface.ts +++ b/packages/api/src/@core/utils/types/interface.ts @@ -41,6 +41,12 @@ export interface IUnification { }): Promise; } +export type SyncLinkedUserType = { + integrationId: string; + linkedUserId: string; + [key: string]: any; +}; + export interface IBaseSync { saveToDb( connection_id: string, @@ -51,6 +57,10 @@ export interface IBaseSync { ...rest: any ): Promise; + kickstartSync?(...params: any[]): Promise; + + syncForLinkedUser?(param: SyncLinkedUserType): Promise; + removeInDb?(connection_id: string, remote_id: string): Promise; } diff --git a/packages/api/src/accounting/address/sync/sync.service.ts b/packages/api/src/accounting/address/sync/sync.service.ts index a7e773a99..5e95c80eb 100644 --- a/packages/api/src/accounting/address/sync/sync.service.ts +++ b/packages/api/src/accounting/address/sync/sync.service.ts @@ -22,6 +22,19 @@ export class SyncService implements OnModuleInit, IBaseSync { ) { this.logger.setContext(SyncService.name); } + saveToDb( + connection_id: string, + linkedUserId: string, + data: any[], + originSource: string, + remote_data: Record[], + ...rest: any + ): Promise { + throw new Error('Method not implemented.'); + } + removeInDb?(connection_id: string, remote_id: string): Promise { + throw new Error('Method not implemented.'); + } async onModuleInit() { // Initialization logic diff --git a/packages/api/src/accounting/attachment/sync/sync.service.ts b/packages/api/src/accounting/attachment/sync/sync.service.ts index e696be422..eaf321036 100644 --- a/packages/api/src/accounting/attachment/sync/sync.service.ts +++ b/packages/api/src/accounting/attachment/sync/sync.service.ts @@ -22,6 +22,19 @@ export class SyncService implements OnModuleInit, IBaseSync { ) { this.logger.setContext(SyncService.name); } + saveToDb( + connection_id: string, + linkedUserId: string, + data: any[], + originSource: string, + remote_data: Record[], + ...rest: any + ): Promise { + throw new Error('Method not implemented.'); + } + removeInDb?(connection_id: string, remote_id: string): Promise { + throw new Error('Method not implemented.'); + } async onModuleInit() { // Initialization logic diff --git a/packages/api/src/accounting/balancesheet/sync/sync.service.ts b/packages/api/src/accounting/balancesheet/sync/sync.service.ts index 110234171..1cac5c34a 100644 --- a/packages/api/src/accounting/balancesheet/sync/sync.service.ts +++ b/packages/api/src/accounting/balancesheet/sync/sync.service.ts @@ -26,6 +26,15 @@ export class SyncService implements OnModuleInit, IBaseSync { async onModuleInit() { // Initialization logic } - + saveToDb( + connection_id: string, + linkedUserId: string, + data: any[], + originSource: string, + remote_data: Record[], + ...rest: any + ): Promise { + throw new Error('Method not implemented.'); + } // Additional methods and logic } diff --git a/packages/api/src/accounting/cashflowstatement/sync/sync.service.ts b/packages/api/src/accounting/cashflowstatement/sync/sync.service.ts index bf575e8dc..eef4b3adb 100644 --- a/packages/api/src/accounting/cashflowstatement/sync/sync.service.ts +++ b/packages/api/src/accounting/cashflowstatement/sync/sync.service.ts @@ -27,5 +27,16 @@ export class SyncService implements OnModuleInit, IBaseSync { // Initialization logic } + saveToDb( + connection_id: string, + linkedUserId: string, + data: any[], + originSource: string, + remote_data: Record[], + ...rest: any + ): Promise { + throw new Error('Method not implemented.'); + } + // Additional methods and logic } diff --git a/packages/api/src/accounting/companyinfo/sync/sync.service.ts b/packages/api/src/accounting/companyinfo/sync/sync.service.ts index 716bb1fe8..f54b691fc 100644 --- a/packages/api/src/accounting/companyinfo/sync/sync.service.ts +++ b/packages/api/src/accounting/companyinfo/sync/sync.service.ts @@ -28,5 +28,16 @@ export class SyncService implements OnModuleInit, IBaseSync { // Initialization logic } + saveToDb( + connection_id: string, + linkedUserId: string, + data: any[], + originSource: string, + remote_data: Record[], + ...rest: any + ): Promise { + throw new Error('Method not implemented.'); + } + // Additional methods and logic } diff --git a/packages/api/src/accounting/contact/sync/sync.service.ts b/packages/api/src/accounting/contact/sync/sync.service.ts index 2b807f3f5..cb3f3c005 100644 --- a/packages/api/src/accounting/contact/sync/sync.service.ts +++ b/packages/api/src/accounting/contact/sync/sync.service.ts @@ -28,5 +28,16 @@ export class SyncService implements OnModuleInit, IBaseSync { // Initialization logic } + saveToDb( + connection_id: string, + linkedUserId: string, + data: any[], + originSource: string, + remote_data: Record[], + ...rest: any + ): Promise { + throw new Error('Method not implemented.'); + } + // Additional methods and logic } diff --git a/packages/api/src/accounting/creditnote/sync/sync.service.ts b/packages/api/src/accounting/creditnote/sync/sync.service.ts index d97909161..fc82a4335 100644 --- a/packages/api/src/accounting/creditnote/sync/sync.service.ts +++ b/packages/api/src/accounting/creditnote/sync/sync.service.ts @@ -28,5 +28,16 @@ export class SyncService implements OnModuleInit, IBaseSync { // Initialization logic } + saveToDb( + connection_id: string, + linkedUserId: string, + data: any[], + originSource: string, + remote_data: Record[], + ...rest: any + ): Promise { + throw new Error('Method not implemented.'); + } + // Additional methods and logic } diff --git a/packages/api/src/accounting/expense/sync/sync.service.ts b/packages/api/src/accounting/expense/sync/sync.service.ts index dc2e9db6e..f63aa3962 100644 --- a/packages/api/src/accounting/expense/sync/sync.service.ts +++ b/packages/api/src/accounting/expense/sync/sync.service.ts @@ -28,5 +28,16 @@ export class SyncService implements OnModuleInit, IBaseSync { // Initialization logic } + saveToDb( + connection_id: string, + linkedUserId: string, + data: any[], + originSource: string, + remote_data: Record[], + ...rest: any + ): Promise { + throw new Error('Method not implemented.'); + } + // Additional methods and logic } diff --git a/packages/api/src/accounting/incomestatement/sync/sync.service.ts b/packages/api/src/accounting/incomestatement/sync/sync.service.ts index 4cc73d990..74582659c 100644 --- a/packages/api/src/accounting/incomestatement/sync/sync.service.ts +++ b/packages/api/src/accounting/incomestatement/sync/sync.service.ts @@ -27,6 +27,16 @@ export class SyncService implements OnModuleInit, IBaseSync { async onModuleInit() { // Initialization logic } + saveToDb( + connection_id: string, + linkedUserId: string, + data: any[], + originSource: string, + remote_data: Record[], + ...rest: any + ): Promise { + throw new Error('Method not implemented.'); + } // Additional methods and logic } diff --git a/packages/api/src/accounting/invoice/sync/sync.service.ts b/packages/api/src/accounting/invoice/sync/sync.service.ts index 62ff66bbc..152ac01eb 100644 --- a/packages/api/src/accounting/invoice/sync/sync.service.ts +++ b/packages/api/src/accounting/invoice/sync/sync.service.ts @@ -27,6 +27,15 @@ export class SyncService implements OnModuleInit, IBaseSync { async onModuleInit() { // Initialization logic } - + saveToDb( + connection_id: string, + linkedUserId: string, + data: any[], + originSource: string, + remote_data: Record[], + ...rest: any + ): Promise { + throw new Error('Method not implemented.'); + } // Additional methods and logic } diff --git a/packages/api/src/accounting/item/sync/sync.service.ts b/packages/api/src/accounting/item/sync/sync.service.ts index 2c6b71ede..49232d2a3 100644 --- a/packages/api/src/accounting/item/sync/sync.service.ts +++ b/packages/api/src/accounting/item/sync/sync.service.ts @@ -27,6 +27,16 @@ export class SyncService implements OnModuleInit, IBaseSync { async onModuleInit() { // Initialization logic } + saveToDb( + connection_id: string, + linkedUserId: string, + data: any[], + originSource: string, + remote_data: Record[], + ...rest: any + ): Promise { + throw new Error('Method not implemented.'); + } // Additional methods and logic } diff --git a/packages/api/src/accounting/journalentry/sync/sync.service.ts b/packages/api/src/accounting/journalentry/sync/sync.service.ts index b61557bb5..ce5805f70 100644 --- a/packages/api/src/accounting/journalentry/sync/sync.service.ts +++ b/packages/api/src/accounting/journalentry/sync/sync.service.ts @@ -27,6 +27,16 @@ export class SyncService implements OnModuleInit, IBaseSync { async onModuleInit() { // Initialization logic } + saveToDb( + connection_id: string, + linkedUserId: string, + data: any[], + originSource: string, + remote_data: Record[], + ...rest: any + ): Promise { + throw new Error('Method not implemented.'); + } // Additional methods and logic } diff --git a/packages/api/src/accounting/payment/sync/sync.service.ts b/packages/api/src/accounting/payment/sync/sync.service.ts index bf1f79f47..38b9d0a13 100644 --- a/packages/api/src/accounting/payment/sync/sync.service.ts +++ b/packages/api/src/accounting/payment/sync/sync.service.ts @@ -27,6 +27,16 @@ export class SyncService implements OnModuleInit, IBaseSync { async onModuleInit() { // Initialization logic } + saveToDb( + connection_id: string, + linkedUserId: string, + data: any[], + originSource: string, + remote_data: Record[], + ...rest: any + ): Promise { + throw new Error('Method not implemented.'); + } // Additional methods and logic } diff --git a/packages/api/src/accounting/phonenumber/sync/sync.service.ts b/packages/api/src/accounting/phonenumber/sync/sync.service.ts index e3c0cdb6a..ad1c35661 100644 --- a/packages/api/src/accounting/phonenumber/sync/sync.service.ts +++ b/packages/api/src/accounting/phonenumber/sync/sync.service.ts @@ -28,5 +28,15 @@ export class SyncService implements OnModuleInit, IBaseSync { // Initialization logic } + saveToDb( + connection_id: string, + linkedUserId: string, + data: any[], + originSource: string, + remote_data: Record[], + ...rest: any + ): Promise { + throw new Error('Method not implemented.'); + } // Additional methods and logic } diff --git a/packages/api/src/accounting/purchaseorder/sync/sync.service.ts b/packages/api/src/accounting/purchaseorder/sync/sync.service.ts index 95bf9306d..ba55df1db 100644 --- a/packages/api/src/accounting/purchaseorder/sync/sync.service.ts +++ b/packages/api/src/accounting/purchaseorder/sync/sync.service.ts @@ -27,6 +27,15 @@ export class SyncService implements OnModuleInit, IBaseSync { async onModuleInit() { // Initialization logic } - + saveToDb( + connection_id: string, + linkedUserId: string, + data: any[], + originSource: string, + remote_data: Record[], + ...rest: any + ): Promise { + throw new Error('Method not implemented.'); + } // Additional methods and logic } diff --git a/packages/api/src/accounting/taxrate/sync/sync.service.ts b/packages/api/src/accounting/taxrate/sync/sync.service.ts index 7d466981b..91c41e4af 100644 --- a/packages/api/src/accounting/taxrate/sync/sync.service.ts +++ b/packages/api/src/accounting/taxrate/sync/sync.service.ts @@ -27,6 +27,15 @@ export class SyncService implements OnModuleInit, IBaseSync { async onModuleInit() { // Initialization logic } - + saveToDb( + connection_id: string, + linkedUserId: string, + data: any[], + originSource: string, + remote_data: Record[], + ...rest: any + ): Promise { + throw new Error('Method not implemented.'); + } // Additional methods and logic } diff --git a/packages/api/src/accounting/trackingcategory/sync/sync.service.ts b/packages/api/src/accounting/trackingcategory/sync/sync.service.ts index 720604803..48b92e00f 100644 --- a/packages/api/src/accounting/trackingcategory/sync/sync.service.ts +++ b/packages/api/src/accounting/trackingcategory/sync/sync.service.ts @@ -27,6 +27,15 @@ export class SyncService implements OnModuleInit, IBaseSync { async onModuleInit() { // Initialization logic } - + saveToDb( + connection_id: string, + linkedUserId: string, + data: any[], + originSource: string, + remote_data: Record[], + ...rest: any + ): Promise { + throw new Error('Method not implemented.'); + } // Additional methods and logic } diff --git a/packages/api/src/accounting/transaction/sync/sync.service.ts b/packages/api/src/accounting/transaction/sync/sync.service.ts index b6d61d1c1..aafc1405c 100644 --- a/packages/api/src/accounting/transaction/sync/sync.service.ts +++ b/packages/api/src/accounting/transaction/sync/sync.service.ts @@ -27,6 +27,16 @@ export class SyncService implements OnModuleInit, IBaseSync { async onModuleInit() { // Initialization logic } + saveToDb( + connection_id: string, + linkedUserId: string, + data: any[], + originSource: string, + remote_data: Record[], + ...rest: any + ): Promise { + throw new Error('Method not implemented.'); + } // Additional methods and logic } diff --git a/packages/api/src/accounting/vendorcredit/sync/sync.service.ts b/packages/api/src/accounting/vendorcredit/sync/sync.service.ts index 83bdf325f..dc25c7ea1 100644 --- a/packages/api/src/accounting/vendorcredit/sync/sync.service.ts +++ b/packages/api/src/accounting/vendorcredit/sync/sync.service.ts @@ -27,6 +27,15 @@ export class SyncService implements OnModuleInit, IBaseSync { async onModuleInit() { // Initialization logic } - + saveToDb( + connection_id: string, + linkedUserId: string, + data: any[], + originSource: string, + remote_data: Record[], + ...rest: any + ): Promise { + throw new Error('Method not implemented.'); + } // Additional methods and logic } diff --git a/packages/api/src/ats/activity/services/activity.service.ts b/packages/api/src/ats/activity/services/activity.service.ts index 9e0527d3e..831d30180 100644 --- a/packages/api/src/ats/activity/services/activity.service.ts +++ b/packages/api/src/ats/activity/services/activity.service.ts @@ -10,6 +10,8 @@ import { Injectable } from '@nestjs/common'; import { v4 as uuidv4 } from 'uuid'; import { IActivityService } from '../types'; import { + ActivityType, + ActivityVisibility, UnifiedActivityInput, UnifiedActivityOutput, } from '../types/model.unified'; @@ -246,10 +248,10 @@ export class ActivityService { const unifiedActivity: UnifiedActivityOutput = { id: activity.id_ats_activity, - activity_type: activity.activity_type, + activity_type: activity.activity_type as ActivityType, subject: activity.subject, body: activity.body, - visibility: activity.visibility, + visibility: activity.visibility as ActivityVisibility, candidate_id: activity.id_ats_candidate, remote_created_at: String(activity.remote_created_at), field_mappings: field_mappings, @@ -359,10 +361,10 @@ export class ActivityService { return { id: activity.id_ats_activity, - activity_type: activity.activity_type, + activity_type: activity.activity_type as ActivityType, subject: activity.subject, body: activity.body, - visibility: activity.visibility, + visibility: activity.visibility as ActivityVisibility, candidate_id: activity.id_ats_candidate, remote_created_at: String(activity.remote_created_at), field_mappings: field_mappings, diff --git a/packages/api/src/ats/activity/sync/sync.service.ts b/packages/api/src/ats/activity/sync/sync.service.ts index df2ae0e0a..598c97896 100644 --- a/packages/api/src/ats/activity/sync/sync.service.ts +++ b/packages/api/src/ats/activity/sync/sync.service.ts @@ -51,7 +51,7 @@ export class SyncService implements OnModuleInit, IBaseSync { //its role is to fetch all activities from providers 3rd parties and save the info inside our db // @Cron('*/2 * * * *') // every 2 minutes (for testing) @Cron('0 */8 * * *') // every 8 hours - async syncActivities(user_id?: string) { + async kickstartSync(user_id?: string) { try { this.logger.log(`Syncing activities....`); const users = user_id diff --git a/packages/api/src/ats/activity/types/model.unified.ts b/packages/api/src/ats/activity/types/model.unified.ts index 883cfd44b..7699fe1ea 100644 --- a/packages/api/src/ats/activity/types/model.unified.ts +++ b/packages/api/src/ats/activity/types/model.unified.ts @@ -1,11 +1,14 @@ import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger'; import { IsUUID, IsOptional, IsString, IsDateString } from 'class-validator'; +export type ActivityType = 'NOTE' | 'EMAIL' | 'OTHER'; +export type ActivityVisibility = 'ADMIN_ONLY' | 'PUBLIC' | 'PRIVATE'; + export class UnifiedActivityInput { @ApiPropertyOptional({ type: String, description: 'The type of activity' }) @IsString() @IsOptional() - activity_type?: string; + activity_type?: ActivityType; @ApiPropertyOptional({ type: String, @@ -29,7 +32,7 @@ export class UnifiedActivityInput { }) @IsString() @IsOptional() - visibility?: string; + visibility?: ActivityVisibility; @ApiPropertyOptional({ type: String, diff --git a/packages/api/src/ats/ats.module.ts b/packages/api/src/ats/ats.module.ts index b685f5baf..c6abbf6e5 100644 --- a/packages/api/src/ats/ats.module.ts +++ b/packages/api/src/ats/ats.module.ts @@ -11,7 +11,6 @@ import { OfferModule } from './offer/offer.module'; import { OfficeModule } from './office/office.module'; import { RejectReasonModule } from './rejectreason/rejectreason.module'; import { ScoreCardModule } from './scorecard/scorecard.module'; -import { ScreeningQuestionModule } from './screeningquestion/screeningquestion.module'; import { TagModule } from './tag/tag.module'; import { UserModule } from './user/user.module'; import { EeocsModule } from './eeocs/eeocs.module'; @@ -30,7 +29,6 @@ import { EeocsModule } from './eeocs/eeocs.module'; OfficeModule, RejectReasonModule, ScoreCardModule, - ScreeningQuestionModule, TagModule, UserModule, EeocsModule, @@ -48,7 +46,6 @@ import { EeocsModule } from './eeocs/eeocs.module'; OfficeModule, RejectReasonModule, ScoreCardModule, - ScreeningQuestionModule, TagModule, UserModule, EeocsModule, diff --git a/packages/api/src/ats/attachment/services/ashby/mappers.ts b/packages/api/src/ats/attachment/services/ashby/mappers.ts index afc8aa979..6a91a1af1 100644 --- a/packages/api/src/ats/attachment/services/ashby/mappers.ts +++ b/packages/api/src/ats/attachment/services/ashby/mappers.ts @@ -104,7 +104,6 @@ export class AshbyAttachmentMapper implements IAttachmentMapper { remote_data: attachment, file_url: url || null, file_name: attachment.name || null, - file_type: null, // todo }; } } diff --git a/packages/api/src/ats/attachment/services/attachment.service.ts b/packages/api/src/ats/attachment/services/attachment.service.ts index 2b0426e51..e180883fd 100644 --- a/packages/api/src/ats/attachment/services/attachment.service.ts +++ b/packages/api/src/ats/attachment/services/attachment.service.ts @@ -3,6 +3,7 @@ import { PrismaService } from '@@core/@core-services/prisma/prisma.service'; import { LoggerService } from '@@core/@core-services/logger/logger.service'; import { v4 as uuidv4 } from 'uuid'; import { + AttachmentType, UnifiedAttachmentInput, UnifiedAttachmentOutput, } from '../types/model.unified'; @@ -96,7 +97,7 @@ export class AttachmentService { const data: any = { file_url: target_attachment.file_url, file_name: target_attachment.file_name, - file_type: target_attachment.file_type, + file_type: target_attachment.attachment_type, remote_created_at: target_attachment.remote_created_at, remote_modified_at: target_attachment.remote_modified_at, modified_at: new Date(), @@ -116,7 +117,7 @@ export class AttachmentService { id_ats_candidate_attachment: uuidv4(), file_url: target_attachment.file_url, file_name: target_attachment.file_name, - file_type: target_attachment.file_type, + file_type: target_attachment.attachment_type, remote_created_at: target_attachment.remote_created_at, remote_modified_at: target_attachment.remote_modified_at, created_at: new Date(), @@ -264,7 +265,7 @@ export class AttachmentService { id: attachment.id_ats_candidate_attachment, file_url: attachment.file_url, file_name: attachment.file_name, - file_type: attachment.file_type, + attachment_type: attachment.file_type as AttachmentType, remote_created_at: String(attachment.remote_created_at), remote_modified_at: String(attachment.remote_modified_at), candidate_id: attachment.id_ats_candidate, @@ -382,7 +383,7 @@ export class AttachmentService { id: attachment.id_ats_candidate_attachment, file_url: attachment.file_url, file_name: attachment.file_name, - file_type: attachment.file_type, + attachment_type: attachment.file_type as AttachmentType, remote_created_at: String(attachment.remote_created_at), remote_modified_at: String(attachment.remote_modified_at), candidate_id: attachment.id_ats_candidate, diff --git a/packages/api/src/ats/attachment/sync/sync.service.ts b/packages/api/src/ats/attachment/sync/sync.service.ts index 567734834..ccffbd437 100644 --- a/packages/api/src/ats/attachment/sync/sync.service.ts +++ b/packages/api/src/ats/attachment/sync/sync.service.ts @@ -11,7 +11,7 @@ import { ApiResponse } from '@@core/utils/types'; import { IAttachmentService } from '../types'; import { OriginalAttachmentOutput } from '@@core/utils/types/original/original.ats'; import { UnifiedAttachmentOutput } from '../types/model.unified'; -import { ats_attachments as AtsAttachment } from '@prisma/client'; +import { ats_candidate_attachments as AtsAttachment } from '@prisma/client'; import { ATS_PROVIDERS } from '@panora/shared'; import { AtsObject } from '@ats/@lib/@types'; import { BullQueueService } from '@@core/@core-services/queues/shared.service'; diff --git a/packages/api/src/ats/attachment/types/model.unified.ts b/packages/api/src/ats/attachment/types/model.unified.ts index 22da8a01a..6b2489112 100644 --- a/packages/api/src/ats/attachment/types/model.unified.ts +++ b/packages/api/src/ats/attachment/types/model.unified.ts @@ -1,6 +1,11 @@ import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger'; import { IsUUID, IsOptional, IsString, IsDateString } from 'class-validator'; +export type AttachmentType = + | 'RESUME' + | 'COVER_LETTER' + | 'OFFER_LETTER' + | 'OTHER'; export class UnifiedAttachmentInput { @ApiPropertyOptional({ type: String, description: 'The URL of the file' }) @IsString() @@ -15,7 +20,7 @@ export class UnifiedAttachmentInput { @ApiPropertyOptional({ type: String, description: 'The type of the file' }) @IsString() @IsOptional() - file_type?: string; + attachment_type?: AttachmentType; @ApiPropertyOptional({ type: String, diff --git a/packages/api/src/ats/eeocs/services/eeocs.service.ts b/packages/api/src/ats/eeocs/services/eeocs.service.ts index ad604b74b..8703f2bd4 100644 --- a/packages/api/src/ats/eeocs/services/eeocs.service.ts +++ b/packages/api/src/ats/eeocs/services/eeocs.service.ts @@ -2,7 +2,13 @@ import { Injectable } from '@nestjs/common'; import { PrismaService } from '@@core/@core-services/prisma/prisma.service'; import { LoggerService } from '@@core/@core-services/logger/logger.service'; import { v4 as uuidv4 } from 'uuid'; -import { UnifiedEeocsOutput } from '../types/model.unified'; +import { + EeocsDisabilityStatus, + EeocsGender, + EeocsRace, + EeocsVeteranStatus, + UnifiedEeocsOutput, +} from '../types/model.unified'; @Injectable() export class EeocsService { @@ -56,10 +62,10 @@ export class EeocsService { id: eeocs.id_ats_eeoc, candidate_id: eeocs.id_ats_candidate, submitted_at: String(eeocs.submitted_at), - race: eeocs.race, - gender: eeocs.gender, - veteran_status: eeocs.veteran_status, - disability_status: eeocs.disability_status, + race: eeocs.race as EeocsRace, + gender: eeocs.gender as EeocsGender, + veteran_status: eeocs.veteran_status as EeocsVeteranStatus, + disability_status: eeocs.disability_status as EeocsDisabilityStatus, field_mappings: field_mappings, remote_id: eeocs.remote_id, created_at: eeocs.created_at, @@ -188,10 +194,10 @@ export class EeocsService { id: eeocs.id_ats_eeoc, candidate_id: eeocs.id_ats_candidate, submitted_at: String(eeocs.submitted_at), - race: eeocs.race, - gender: eeocs.gender, - veteran_status: eeocs.veteran_status, - disability_status: eeocs.disability_status, + race: eeocs.race as EeocsRace, + gender: eeocs.gender as EeocsGender, + veteran_status: eeocs.veteran_status as EeocsVeteranStatus, + disability_status: eeocs.disability_status as EeocsDisabilityStatus, field_mappings: field_mappings, remote_id: eeocs.remote_id, created_at: eeocs.created_at, diff --git a/packages/api/src/ats/eeocs/types/model.unified.ts b/packages/api/src/ats/eeocs/types/model.unified.ts index 482f7fe88..62d57f751 100644 --- a/packages/api/src/ats/eeocs/types/model.unified.ts +++ b/packages/api/src/ats/eeocs/types/model.unified.ts @@ -1,6 +1,33 @@ import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger'; import { IsUUID, IsOptional, IsString, IsDateString } from 'class-validator'; +export type EeocsRace = + | 'AMERICAN_INDIAN_OR_ALASKAN_NATIVE' + | 'ASIAN' + | 'BLACK_OR_AFRICAN_AMERICAN' + | 'HISPANIC_OR_LATINO' + | 'WHITE' + | 'NATIVE_HAWAIIAN_OR_OTHER_PACIFIC_ISLANDER' + | 'TWO_OR_MORE_RACES' + | 'DECLINE_TO_SELF_IDENTIFY'; + +export type EeocsDisabilityStatus = + | 'YES_I_HAVE_A_DISABILITY_OR_PREVIOUSLY_HAD_A_DISABILITY' + | 'NO_I_DONT_HAVE_A_DISABILITY' + | 'I_DONT_WISH_TO_ANSWER'; + +export type EeocsGender = + | 'MALE' + | 'FEMALE' + | 'NON_BINARY' + | 'OTHER' + | 'DECLINE_TO_SELF_IDENTIFY'; + +export type EeocsVeteranStatus = + | 'I_AM_NOT_A_PROTECTED_VETERAN' + | 'I_IDENTIFY_AS_ONE_OR_MORE_OF_THE_CLASSIFICATIONS_OF_A_PROTECTED_VETERAN' + | 'I_DONT_WISH_TO_ANSWER'; + export class UnifiedEeocsInput { @ApiPropertyOptional({ type: String, @@ -25,7 +52,7 @@ export class UnifiedEeocsInput { }) @IsString() @IsOptional() - race?: string; + race?: EeocsRace; @ApiPropertyOptional({ type: String, @@ -33,7 +60,7 @@ export class UnifiedEeocsInput { }) @IsString() @IsOptional() - gender?: string; + gender?: EeocsGender; @ApiPropertyOptional({ type: String, @@ -41,7 +68,7 @@ export class UnifiedEeocsInput { }) @IsString() @IsOptional() - veteran_status?: string; + veteran_status?: EeocsVeteranStatus; @ApiPropertyOptional({ type: String, @@ -49,7 +76,7 @@ export class UnifiedEeocsInput { }) @IsString() @IsOptional() - disability_status?: string; + disability_status?: EeocsDisabilityStatus; @ApiPropertyOptional({ type: {}, diff --git a/packages/api/src/ats/interview/services/ashby/mappers.ts b/packages/api/src/ats/interview/services/ashby/mappers.ts index cc9b4e36b..fc3fff585 100644 --- a/packages/api/src/ats/interview/services/ashby/mappers.ts +++ b/packages/api/src/ats/interview/services/ashby/mappers.ts @@ -1,5 +1,6 @@ import { AshbyInterviewInput, AshbyInterviewOutput } from './types'; import { + InterviewStatus, UnifiedInterviewInput, UnifiedInterviewOutput, } from '@ats/interview/types/model.unified'; @@ -78,7 +79,7 @@ export class AshbyInterviewMapper implements IInterviewMapper { return { remote_id: interview.id, remote_data: interview, - status: interview.status || null, //todo + status: (interview.status as InterviewStatus) || null, //todo application_id: (await this.utils.getApplicationUuidFromRemoteId( interview.applicationId, diff --git a/packages/api/src/ats/interview/services/interview.service.ts b/packages/api/src/ats/interview/services/interview.service.ts index 85c1e97ca..f21fe2ccc 100644 --- a/packages/api/src/ats/interview/services/interview.service.ts +++ b/packages/api/src/ats/interview/services/interview.service.ts @@ -3,6 +3,7 @@ import { PrismaService } from '@@core/@core-services/prisma/prisma.service'; import { LoggerService } from '@@core/@core-services/logger/logger.service'; import { v4 as uuidv4 } from 'uuid'; import { + InterviewStatus, UnifiedInterviewInput, UnifiedInterviewOutput, } from '../types/model.unified'; @@ -274,7 +275,7 @@ export class InterviewService { // Transform to UnifiedInterviewOutput format const unifiedInterview: UnifiedInterviewOutput = { id: interview.id_ats_interview, - status: interview.status, + status: interview.status as InterviewStatus, application_id: interview.id_ats_application, job_interview_stage_id: interview.id_ats_job_interview_stage, organized_by: interview.organized_by, @@ -410,7 +411,7 @@ export class InterviewService { // Transform to UnifiedInterviewOutput format return { id: interview.id_ats_interview, - status: interview.status, + status: interview.status as InterviewStatus, application_id: interview.id_ats_application, job_interview_stage_id: interview.id_ats_job_interview_stage, organized_by: interview.organized_by, diff --git a/packages/api/src/ats/interview/types/model.unified.ts b/packages/api/src/ats/interview/types/model.unified.ts index 3d23b7b36..f9bad2f72 100644 --- a/packages/api/src/ats/interview/types/model.unified.ts +++ b/packages/api/src/ats/interview/types/model.unified.ts @@ -7,6 +7,8 @@ import { IsArray, } from 'class-validator'; +export type InterviewStatus = 'SCHEDULED' | 'AWAITING_FEEDBACK' | 'COMPLETED'; + export class UnifiedInterviewInput { @ApiPropertyOptional({ type: String, @@ -14,7 +16,7 @@ export class UnifiedInterviewInput { }) @IsString() @IsOptional() - status?: string; + status?: InterviewStatus; @ApiPropertyOptional({ type: String, diff --git a/packages/api/src/ats/job/services/ashby/mappers.ts b/packages/api/src/ats/job/services/ashby/mappers.ts index 53632a00a..35731582e 100644 --- a/packages/api/src/ats/job/services/ashby/mappers.ts +++ b/packages/api/src/ats/job/services/ashby/mappers.ts @@ -1,5 +1,6 @@ import { AshbyJobInput, AshbyJobOutput } from './types'; import { + JobStatus, UnifiedJobInput, UnifiedJobOutput, } from '@ats/job/types/model.unified'; @@ -91,7 +92,7 @@ export class AshbyJobMapper implements IJobMapper { name: job.title || null, description: null, code: null, - status: job.status || null, //todo + status: (job.status as JobStatus) || null, //todo type: null, confidential: job.confidential || null, departments: department ? [department] : null, diff --git a/packages/api/src/ats/job/services/job.service.ts b/packages/api/src/ats/job/services/job.service.ts index e3d7b2a56..22461c254 100644 --- a/packages/api/src/ats/job/services/job.service.ts +++ b/packages/api/src/ats/job/services/job.service.ts @@ -2,7 +2,7 @@ import { Injectable } from '@nestjs/common'; import { PrismaService } from '@@core/@core-services/prisma/prisma.service'; import { LoggerService } from '@@core/@core-services/logger/logger.service'; import { v4 as uuidv4 } from 'uuid'; -import { UnifiedJobOutput } from '../types/model.unified'; +import { JobStatus, JobType, UnifiedJobOutput } from '../types/model.unified'; @Injectable() export class JobService { @@ -57,8 +57,8 @@ export class JobService { name: job.name, description: job.description, code: job.code, - status: job.status, - type: job.type, + status: job.status as JobStatus, + type: job.type as JobType, confidential: job.confidential, departments: job.ats_departments, offices: job.ats_offices, @@ -195,8 +195,8 @@ export class JobService { name: job.name, description: job.description, code: job.code, - status: job.status, - type: job.type, + status: job.status as JobStatus, + type: job.type as JobType, confidential: job.confidential, departments: job.ats_departments, offices: job.ats_offices, diff --git a/packages/api/src/ats/job/types/model.unified.ts b/packages/api/src/ats/job/types/model.unified.ts index cdf603925..133044110 100644 --- a/packages/api/src/ats/job/types/model.unified.ts +++ b/packages/api/src/ats/job/types/model.unified.ts @@ -8,6 +8,8 @@ import { IsArray, } from 'class-validator'; +export type JobStatus = 'OPEN' | 'CLOSED' | 'DRAFT' | 'ARCHIVED' | 'PENDING'; +export type JobType = 'POSTING' | 'REQUISITION' | 'PROFILE'; export class UnifiedJobInput { @ApiPropertyOptional({ type: String, description: 'The name of the job' }) @IsString() @@ -30,12 +32,12 @@ export class UnifiedJobInput { @ApiPropertyOptional({ type: String, description: 'The status of the job' }) @IsString() @IsOptional() - status?: string; + status?: JobStatus; @ApiPropertyOptional({ type: String, description: 'The type of the job' }) @IsString() @IsOptional() - type?: string; + type?: JobType; @ApiPropertyOptional({ type: Boolean, diff --git a/packages/api/src/ats/offer/services/ashby/mappers.ts b/packages/api/src/ats/offer/services/ashby/mappers.ts index cc7e51d1a..e7c5ceec3 100644 --- a/packages/api/src/ats/offer/services/ashby/mappers.ts +++ b/packages/api/src/ats/offer/services/ashby/mappers.ts @@ -1,5 +1,6 @@ import { AshbyOfferInput, AshbyOfferOutput } from './types'; import { + OfferStatus, UnifiedOfferInput, UnifiedOfferOutput, } from '@ats/offer/types/model.unified'; @@ -65,7 +66,7 @@ export class AshbyOfferMapper implements IOfferMapper { remote_data: offer, closed_at: offer.decidedAt, start_date: offer.latestVersion.startDate, - status: offer.offerStatus || null, + status: (offer.offerStatus as OfferStatus) || null, application_id: (await this.utils.getApplicationUuidFromRemoteId( offer.applicationId, diff --git a/packages/api/src/ats/offer/services/offer.service.ts b/packages/api/src/ats/offer/services/offer.service.ts index f4e62eb94..1ed2013e8 100644 --- a/packages/api/src/ats/offer/services/offer.service.ts +++ b/packages/api/src/ats/offer/services/offer.service.ts @@ -2,7 +2,7 @@ import { Injectable } from '@nestjs/common'; import { PrismaService } from '@@core/@core-services/prisma/prisma.service'; import { LoggerService } from '@@core/@core-services/logger/logger.service'; import { v4 as uuidv4 } from 'uuid'; -import { UnifiedOfferOutput } from '../types/model.unified'; +import { OfferStatus, UnifiedOfferOutput } from '../types/model.unified'; @Injectable() export class OfferService { @@ -59,7 +59,7 @@ export class OfferService { closed_at: String(offer.closed_at), sent_at: String(offer.sent_at), start_date: String(offer.start_date), - status: offer.status, + status: offer.status as OfferStatus, application_id: offer.id_ats_application, field_mappings: field_mappings, remote_id: offer.remote_id, @@ -191,7 +191,7 @@ export class OfferService { closed_at: String(offer.closed_at), sent_at: String(offer.sent_at), start_date: String(offer.start_date), - status: offer.status, + status: offer.status as OfferStatus, application_id: offer.id_ats_application, field_mappings: field_mappings, remote_id: offer.remote_id, diff --git a/packages/api/src/ats/offer/types/model.unified.ts b/packages/api/src/ats/offer/types/model.unified.ts index 6547ff9e9..1e4b0584a 100644 --- a/packages/api/src/ats/offer/types/model.unified.ts +++ b/packages/api/src/ats/offer/types/model.unified.ts @@ -1,6 +1,16 @@ import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger'; import { IsUUID, IsOptional, IsString, IsDateString } from 'class-validator'; +export type OfferStatus = + | 'DRAFT' + | 'APPROVAL_SENT' + | 'APPROVED' + | 'SENT' + | 'SENT_MANUALLY' + | 'OPENED' + | 'DENIED' + | 'SIGNED' + | 'DEPRECATED'; export class UnifiedOfferInput { @ApiPropertyOptional({ type: String, description: 'The UUID of the creator' }) @IsUUID() @@ -46,7 +56,7 @@ export class UnifiedOfferInput { @ApiPropertyOptional({ type: String, description: 'The status of the offer' }) @IsString() @IsOptional() - status?: string; + status?: OfferStatus; @ApiPropertyOptional({ type: String, diff --git a/packages/api/src/ats/scorecard/services/scorecard.service.ts b/packages/api/src/ats/scorecard/services/scorecard.service.ts index 962d303b6..3b41970b0 100644 --- a/packages/api/src/ats/scorecard/services/scorecard.service.ts +++ b/packages/api/src/ats/scorecard/services/scorecard.service.ts @@ -2,7 +2,10 @@ import { Injectable } from '@nestjs/common'; import { PrismaService } from '@@core/@core-services/prisma/prisma.service'; import { LoggerService } from '@@core/@core-services/logger/logger.service'; import { v4 as uuidv4 } from 'uuid'; -import { UnifiedScoreCardOutput } from '../types/model.unified'; +import { + ScoreCardRecommendation, + UnifiedScoreCardOutput, +} from '../types/model.unified'; @Injectable() export class ScoreCardService { @@ -54,7 +57,8 @@ export class ScoreCardService { // Transform to UnifiedScoreCardOutput format const unifiedScoreCard: UnifiedScoreCardOutput = { id: scorecard.id_ats_scorecard, - overall_recommendation: scorecard.overall_recommendation, + overall_recommendation: + scorecard.overall_recommendation as ScoreCardRecommendation, application_id: scorecard.id_ats_application, interview_id: scorecard.id_ats_interview, remote_created_at: String(scorecard.remote_created_at), @@ -185,7 +189,8 @@ export class ScoreCardService { // Transform to UnifiedScoreCardOutput format return { id: scorecard.id_ats_scorecard, - overall_recommendation: scorecard.overall_recommendation, + overall_recommendation: + scorecard.overall_recommendation as ScoreCardRecommendation, application_id: scorecard.id_ats_application, interview_id: scorecard.id_ats_interview, remote_created_at: String(scorecard.remote_created_at), diff --git a/packages/api/src/ats/scorecard/types/model.unified.ts b/packages/api/src/ats/scorecard/types/model.unified.ts index c2a818514..4d771956f 100644 --- a/packages/api/src/ats/scorecard/types/model.unified.ts +++ b/packages/api/src/ats/scorecard/types/model.unified.ts @@ -1,5 +1,11 @@ import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger'; import { IsUUID, IsOptional, IsString, IsDateString } from 'class-validator'; +export type ScoreCardRecommendation = + | 'DEFINITELY_NO' + | 'NO' + | 'YES' + | 'STRONG_YES' + | 'NO_DECISION'; export class UnifiedScoreCardInput { @ApiPropertyOptional({ @@ -8,7 +14,7 @@ export class UnifiedScoreCardInput { }) @IsString() @IsOptional() - overall_recommendation?: string; + overall_recommendation?: ScoreCardRecommendation; @ApiPropertyOptional({ type: String, diff --git a/packages/api/src/ats/tag/services/tag.service.ts b/packages/api/src/ats/tag/services/tag.service.ts index e9034c96e..2314c0e1f 100644 --- a/packages/api/src/ats/tag/services/tag.service.ts +++ b/packages/api/src/ats/tag/services/tag.service.ts @@ -10,27 +10,27 @@ export class TagService { } async getTag( - id_ats_tag: string, + id_ats_candidate_tag: string, linkedUserId: string, integrationId: string, remote_data?: boolean, ): Promise { try { - const tag = await this.prisma.ats_tags.findUnique({ + const tag = await this.prisma.ats_candidate_tags.findUnique({ where: { - id_ats_tag: id_ats_tag, + id_ats_candidate_tag: id_ats_candidate_tag, }, }); if (!tag) { - throw new Error(`Tag with ID ${id_ats_tag} not found.`); + throw new Error(`Tag with ID ${id_ats_candidate_tag} not found.`); } // Fetch field mappings for the tag const values = await this.prisma.value.findMany({ where: { entity: { - ressource_owner_id: tag.id_ats_tag, + ressource_owner_id: tag.id_ats_candidate_tag, }, }, include: { @@ -64,7 +64,7 @@ export class TagService { if (remote_data) { const resp = await this.prisma.remote_data.findFirst({ where: { - ressource_owner_id: tag.id_ats_tag, + ressource_owner_id: tag.id_ats_candidate_tag, }, }); const remote_data = JSON.parse(resp.data); @@ -111,10 +111,10 @@ export class TagService { let next_cursor = null; if (cursor) { - const isCursorPresent = await this.prisma.ats_tag.findFirst({ + const isCursorPresent = await this.prisma.ats_candidate_tags.findFirst({ where: { id_connection: connection_id, - id_ats_tag: cursor, + id_ats_candidate_tag: cursor, }, }); if (!isCursorPresent) { @@ -122,11 +122,11 @@ export class TagService { } } - const tags = await this.prisma.ats_tags.findMany({ + const tags = await this.prisma.ats_candidate_tags.findMany({ take: limit + 1, cursor: cursor ? { - id_ats_tag: cursor, + id_ats_candidate_tag: cursor, } : undefined, orderBy: { @@ -138,9 +138,9 @@ export class TagService { }); if (tags.length === limit + 1) { - next_cursor = Buffer.from(tags[tags.length - 1].id_ats_tag).toString( - 'base64', - ); + next_cursor = Buffer.from( + tags[tags.length - 1].id_ats_candidate_tag, + ).toString('base64'); tags.pop(); } @@ -154,7 +154,7 @@ export class TagService { const values = await this.prisma.value.findMany({ where: { entity: { - ressource_owner_id: tag.id_ats_tag, + ressource_owner_id: tag.id_ats_candidate_tag, }, }, include: { diff --git a/packages/api/src/ats/user/services/ashby/mappers.ts b/packages/api/src/ats/user/services/ashby/mappers.ts index 528a361e3..f871aaf98 100644 --- a/packages/api/src/ats/user/services/ashby/mappers.ts +++ b/packages/api/src/ats/user/services/ashby/mappers.ts @@ -2,6 +2,7 @@ import { AshbyUserInput, AshbyUserOutput } from './types'; import { UnifiedUserInput, UnifiedUserOutput, + UserAccessRole, } from '@ats/user/types/model.unified'; import { IUserMapper } from '@ats/user/types'; import { MappersRegistry } from '@@core/@core-services/registries/mappers.registry'; @@ -67,7 +68,7 @@ export class AshbyUserMapper implements IUserMapper { last_name: user.lastName || null, email: user.email || null, disabled: user.isEnabled || null, - access_role: user.globalRole || null, // todo + access_role: (user.globalRole as UserAccessRole) || null, // todo remote_modified_at: user.updatedAt || null, }; } diff --git a/packages/api/src/ats/user/services/user.service.ts b/packages/api/src/ats/user/services/user.service.ts index 443cdbadd..db13995a2 100644 --- a/packages/api/src/ats/user/services/user.service.ts +++ b/packages/api/src/ats/user/services/user.service.ts @@ -2,7 +2,7 @@ import { Injectable } from '@nestjs/common'; import { PrismaService } from '@@core/@core-services/prisma/prisma.service'; import { LoggerService } from '@@core/@core-services/logger/logger.service'; import { v4 as uuidv4 } from 'uuid'; -import { UnifiedUserOutput } from '../types/model.unified'; +import { UnifiedUserOutput, UserAccessRole } from '../types/model.unified'; @Injectable() export class UserService { @@ -58,7 +58,7 @@ export class UserService { last_name: user.last_name, email: user.email, disabled: user.disabled, - access_role: user.access_role, + access_role: user.access_role as UserAccessRole, remote_created_at: String(user.remote_created_at), remote_modified_at: String(user.remote_modified_at), field_mappings: field_mappings, @@ -190,7 +190,7 @@ export class UserService { last_name: user.last_name, email: user.email, disabled: user.disabled, - access_role: user.access_role, + access_role: user.access_role as UserAccessRole, remote_created_at: String(user.remote_created_at), remote_modified_at: String(user.remote_modified_at), field_mappings: field_mappings, diff --git a/packages/api/src/ats/user/types/model.unified.ts b/packages/api/src/ats/user/types/model.unified.ts index 29f906b03..73dc1a222 100644 --- a/packages/api/src/ats/user/types/model.unified.ts +++ b/packages/api/src/ats/user/types/model.unified.ts @@ -7,6 +7,13 @@ import { IsDateString, } from 'class-validator'; +export type UserAccessRole = + | 'SUPER_ADMIN' + | 'ADMIN' + | 'TEAM_MEMBER' + | 'LIMITED_TEAM_MEMBER' + | 'INTERVIEWER'; + export class UnifiedUserInput { @ApiPropertyOptional({ type: String, @@ -43,7 +50,7 @@ export class UnifiedUserInput { }) @IsString() @IsOptional() - access_role?: string; + access_role?: UserAccessRole; @ApiPropertyOptional({ type: String, diff --git a/packages/api/src/crm/@webhook/handler.module.ts b/packages/api/src/crm/@webhook/handler.module.ts index edbb5fd31..8bb6a0f53 100644 --- a/packages/api/src/crm/@webhook/handler.module.ts +++ b/packages/api/src/crm/@webhook/handler.module.ts @@ -3,6 +3,7 @@ import { EnvironmentService } from '@@core/@core-services/environment/environmen import { LoggerService } from '@@core/@core-services/logger/logger.service'; import { Module } from '@nestjs/common'; import { CrmWebhookHandlerService } from './handler.service'; +import { IngestDataService } from '@@core/@core-services/unification/ingest-data.service'; @Module({ imports: [], diff --git a/packages/api/src/crm/company/services/company.service.ts b/packages/api/src/crm/company/services/company.service.ts index c1bcf27a0..b99963a17 100644 --- a/packages/api/src/crm/company/services/company.service.ts +++ b/packages/api/src/crm/company/services/company.service.ts @@ -4,7 +4,7 @@ import { WebhookService } from '@@core/@core-services/webhooks/panora-webhooks/w import { FieldMappingService } from '@@core/field-mapping/field-mapping.service'; import { ApiResponse } from '@@core/utils/types'; import { OriginalCompanyOutput } from '@@core/utils/types/original/original.crm'; -import { CrmObject } from '@crm/@lib/@types'; +import { CrmObject, Industry } from '@crm/@lib/@types'; import { Utils } from '@crm/@lib/@utils'; import { Injectable } from '@nestjs/common'; import { v4 as uuidv4 } from 'uuid'; @@ -393,7 +393,7 @@ export class CompanyService { const unifiedCompany: UnifiedCompanyOutput = { id: company.id_crm_company, name: company.name, - industry: company.industry, + industry: company.industry as Industry, number_of_employees: Number(company.number_of_employees), user_id: company.id_crm_user, // uuid of User object field_mappings: field_mappings, @@ -539,7 +539,7 @@ export class CompanyService { return { id: company.id_crm_company, name: company.name, - industry: company.industry, + industry: company.industry as Industry, number_of_employees: Number(company.number_of_employees), user_id: company.id_crm_user, // uuid of User object field_mappings: field_mappings, diff --git a/packages/api/src/crm/company/services/pipedrive/mappers.ts b/packages/api/src/crm/company/services/pipedrive/mappers.ts index 1be61d62c..acf8b2cd1 100644 --- a/packages/api/src/crm/company/services/pipedrive/mappers.ts +++ b/packages/api/src/crm/company/services/pipedrive/mappers.ts @@ -115,7 +115,7 @@ export class PipedriveCompanyMapper implements ICompanyMapper { } } if (company.address) { - res.addresses[0] = { + opts.addresses[0] = { street_1: company.address, city: company.address_locality, country: company.address_country, diff --git a/packages/api/src/crm/company/services/zoho/mappers.ts b/packages/api/src/crm/company/services/zoho/mappers.ts index 97513539c..243dee9cd 100644 --- a/packages/api/src/crm/company/services/zoho/mappers.ts +++ b/packages/api/src/crm/company/services/zoho/mappers.ts @@ -7,6 +7,7 @@ import { Utils } from '@crm/@lib/@utils'; import { MappersRegistry } from '@@core/@core-services/registries/mappers.registry'; import { Injectable } from '@nestjs/common'; import { ICompanyMapper } from '@crm/company/types'; +import { Industry } from '@crm/@lib/@types'; @Injectable() export class ZohoCompanyMapper implements ICompanyMapper { @@ -123,7 +124,7 @@ export class ZohoCompanyMapper implements ICompanyMapper { owner_type: 'company', }, ], - industry: company.Industry, //TODO: map to correct industry + industry: company.Industry as Industry, //TODO: map to correct industry user_id: await this.utils.getUserUuidFromRemoteId( company.Owner.id, connectionId, diff --git a/packages/api/src/crm/company/types/model.unified.ts b/packages/api/src/crm/company/types/model.unified.ts index e61bc341b..5ae25286a 100644 --- a/packages/api/src/crm/company/types/model.unified.ts +++ b/packages/api/src/crm/company/types/model.unified.ts @@ -20,7 +20,7 @@ export class UnifiedCompanyInput { }) @IsEnum(Industry) @IsOptional() - industry?: string; + industry?: Industry; @ApiPropertyOptional({ type: Number, diff --git a/packages/api/src/crm/contact/contact.controller.ts b/packages/api/src/crm/contact/contact.controller.ts index d6b8ebd46..8e965a897 100644 --- a/packages/api/src/crm/contact/contact.controller.ts +++ b/packages/api/src/crm/contact/contact.controller.ts @@ -166,17 +166,4 @@ export class ContactController { throw new Error(error); } } - - @ApiOperation({ - operationId: 'update', - summary: 'Update a CRM Contact', - }) - @UseGuards(ApiKeyAuthGuard) - @Patch() - update( - @Query('id') id: string, - @Body() updateContactData: Partial, - ) { - return this.contactService.updateContact(id, updateContactData); - } } diff --git a/packages/api/src/crm/engagement/services/engagement.service.ts b/packages/api/src/crm/engagement/services/engagement.service.ts index af4688baa..6c92554cc 100644 --- a/packages/api/src/crm/engagement/services/engagement.service.ts +++ b/packages/api/src/crm/engagement/services/engagement.service.ts @@ -9,6 +9,8 @@ import { Injectable } from '@nestjs/common'; import { v4 as uuidv4 } from 'uuid'; import { IEngagementService } from '../types'; import { + EngagementDirection, + EngagementType, UnifiedEngagementInput, UnifiedEngagementOutput, } from '../types/model.unified'; @@ -312,11 +314,11 @@ export class EngagementService { const unifiedEngagement: UnifiedEngagementOutput = { id: engagement.id_crm_engagement, content: engagement.content, - direction: engagement.direction, + direction: engagement.direction as EngagementDirection, subject: engagement.subject, start_at: engagement.start_at, end_time: engagement.end_time, - type: engagement.type, + type: engagement.type as EngagementType, company_id: engagement.id_crm_company, field_mappings: field_mappings, remote_id: engagement.remote_id, @@ -447,11 +449,11 @@ export class EngagementService { return { id: engagement.id_crm_engagement, content: engagement.content, - direction: engagement.direction, + direction: engagement.direction as EngagementDirection, subject: engagement.subject, start_at: engagement.start_at, end_time: engagement.end_time, - type: engagement.type, + type: engagement.type as EngagementType, company_id: engagement.id_crm_company, field_mappings: field_mappings, remote_id: engagement.remote_id, diff --git a/packages/api/src/crm/engagement/services/zendesk/mappers.ts b/packages/api/src/crm/engagement/services/zendesk/mappers.ts index 20979feea..e0479c156 100644 --- a/packages/api/src/crm/engagement/services/zendesk/mappers.ts +++ b/packages/api/src/crm/engagement/services/zendesk/mappers.ts @@ -45,7 +45,7 @@ export class ZendeskEngagementMapper implements IEngagementMapper { ): Promise { const result: ZendeskEngagementInput = { summary: source.content || null, - incoming: source.direction === 'incoming', // Example mapping + incoming: source.direction === 'INBOUND', }; if (source.start_at && source.end_time) { diff --git a/packages/api/src/crm/engagement/types/model.unified.ts b/packages/api/src/crm/engagement/types/model.unified.ts index 1437685b5..53884074c 100644 --- a/packages/api/src/crm/engagement/types/model.unified.ts +++ b/packages/api/src/crm/engagement/types/model.unified.ts @@ -1,6 +1,9 @@ import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger'; import { IsIn, IsOptional, IsString, IsUUID } from 'class-validator'; +export type EngagementDirection = 'INBOUND' | 'OUTBOUND'; +export type EngagementType = 'EMAIL' | 'CALL' | 'MEETING'; + export class UnifiedEngagementInput { @ApiPropertyOptional({ type: String, @@ -19,7 +22,7 @@ export class UnifiedEngagementInput { message: 'Direction must be either INBOUND or OUTBOUND', }) @IsOptional() - direction?: string; + direction?: EngagementDirection; @ApiPropertyOptional({ type: String, @@ -45,7 +48,7 @@ export class UnifiedEngagementInput { @IsIn(['EMAIL', 'CALL', 'MEETING'], { message: 'Type must be either EMAIL, CALL or MEETING', }) - type: string; + type?: EngagementType; @ApiPropertyOptional({ type: String, diff --git a/packages/api/src/crm/task/services/task.service.ts b/packages/api/src/crm/task/services/task.service.ts index 86c943784..100b9079e 100644 --- a/packages/api/src/crm/task/services/task.service.ts +++ b/packages/api/src/crm/task/services/task.service.ts @@ -8,7 +8,11 @@ import { CrmObject } from '@crm/@lib/@types'; import { Injectable } from '@nestjs/common'; import { v4 as uuidv4 } from 'uuid'; import { ITaskService } from '../types'; -import { UnifiedTaskInput, UnifiedTaskOutput } from '../types/model.unified'; +import { + TaskStatus, + UnifiedTaskInput, + UnifiedTaskOutput, +} from '../types/model.unified'; import { ServiceRegistry } from './registry.service'; import { CoreUnification } from '@@core/@core-services/unification/core-unification.service'; @@ -297,7 +301,7 @@ export class TaskService { id: task.id_crm_task, subject: task.subject, content: task.content, - status: task.status, + status: task.status as TaskStatus, due_date: task.due_date, finished_date: task.finished_date, company_id: task.id_crm_company, @@ -432,7 +436,7 @@ export class TaskService { id: task.id_crm_task, subject: task.subject, content: task.content, - status: task.status, + status: task.status as TaskStatus, due_date: task.due_date, finished_date: task.finished_date, company_id: task.id_crm_company, diff --git a/packages/api/src/crm/task/services/zoho/mappers.ts b/packages/api/src/crm/task/services/zoho/mappers.ts index 0e57b9c43..24f547839 100644 --- a/packages/api/src/crm/task/services/zoho/mappers.ts +++ b/packages/api/src/crm/task/services/zoho/mappers.ts @@ -1,6 +1,7 @@ import { ITaskMapper } from '@crm/task/types'; import { ZohoTaskInput, ZohoTaskOutput } from './types'; import { + TaskStatus, UnifiedTaskInput, UnifiedTaskOutput, } from '@crm/task/types/model.unified'; @@ -105,7 +106,10 @@ export class ZohoTaskMapper implements ITaskMapper { remote_id: task.id, content: task.Description, subject: task.Subject, - status: task.Status === 'Completed' ? 'COMPLETED' : 'IN PROGRESS', + status: + task.Status === 'Completed' + ? 'COMPLETED' + : ('IN PROGRESS' as TaskStatus), finished_date: new Date(task.Closed_Time), due_date: new Date(task.Due_Date), field_mappings, diff --git a/packages/api/src/crm/task/types/model.unified.ts b/packages/api/src/crm/task/types/model.unified.ts index c3ad5d83a..6c8eab1d4 100644 --- a/packages/api/src/crm/task/types/model.unified.ts +++ b/packages/api/src/crm/task/types/model.unified.ts @@ -1,6 +1,7 @@ import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger'; import { IsIn, IsOptional, IsString, IsUUID } from 'class-validator'; +export type TaskStatus = 'PENDING' | 'COMPLETED'; export class UnifiedTaskInput { @ApiProperty({ type: String, description: 'The subject of the task' }) @IsString() @@ -18,7 +19,7 @@ export class UnifiedTaskInput { @IsIn(['PENDING', 'COMPLETED'], { message: 'Type must be either PENDING or COMPLETED', }) - status: string; + status: TaskStatus; @ApiPropertyOptional({ description: 'The due date of the task' }) @IsOptional() diff --git a/packages/api/src/filestorage/file/services/file.service.ts b/packages/api/src/filestorage/file/services/file.service.ts index eac88e2e4..84d18d44c 100644 --- a/packages/api/src/filestorage/file/services/file.service.ts +++ b/packages/api/src/filestorage/file/services/file.service.ts @@ -98,7 +98,7 @@ export class FileService { mime_type: target_file.mime_type, size: target_file.size, folder_id: target_file.folder_id, - permission_id: target_file.permission_id, + permission_id: target_file.permission as string, modified_at: new Date(), }; @@ -119,7 +119,7 @@ export class FileService { mime_type: target_file.mime_type, size: target_file.size, folder_id: target_file.folder_id, - permission_id: target_file.permission_id, + permission_id: target_file.permission as string, created_at: new Date(), modified_at: new Date(), remote_id: target_file.remote_id, @@ -271,10 +271,10 @@ export class FileService { } let sharedLink; - if (file.id_shared_link) { + if (file.id_fs_shared_link) { const sl = await this.prisma.fs_shared_links.findUnique({ where: { - id_fs_shared_link: file.id_shared_link, + id_fs_shared_link: file.id_fs_shared_link, }, }); sharedLink = sl; @@ -284,7 +284,6 @@ export class FileService { const unifiedFile: UnifiedFileOutput = { id: file.id_fs_file, name: file.name, - type: file.type, file_url: file.file_url, mime_type: file.mime_type, size: String(file.size), @@ -424,10 +423,10 @@ export class FileService { } let sharedLink; - if (file.id_shared_link) { + if (file.id_fs_shared_link) { const sl = await this.prisma.fs_shared_links.findUnique({ where: { - id_fs_shared_link: file.id_shared_link, + id_fs_shared_link: file.id_fs_shared_link, }, }); sharedLink = sl; @@ -437,7 +436,6 @@ export class FileService { return { id: file.id_fs_file, name: file.name, - type: file.type, file_url: file.file_url, mime_type: file.mime_type, size: String(file.size), diff --git a/packages/api/src/filestorage/folder/services/folder.service.ts b/packages/api/src/filestorage/folder/services/folder.service.ts index 1ee59d919..54a2f3560 100644 --- a/packages/api/src/filestorage/folder/services/folder.service.ts +++ b/packages/api/src/filestorage/folder/services/folder.service.ts @@ -100,7 +100,7 @@ export class FolderService { description: target_folder.description, parent_folder: target_folder.parent_folder_id, id_fs_drive: target_folder.drive_id, - id_fs_permission: target_folder.permission_id, + id_fs_permission: target_folder.permission as string, modified_at: new Date(), }; @@ -121,7 +121,7 @@ export class FolderService { description: target_folder.description, parent_folder: target_folder.parent_folder_id, id_fs_drive: target_folder.drive_id, - id_fs_permission: target_folder.permission_id, + id_fs_permission: target_folder.permission as string, created_at: new Date(), modified_at: new Date(), remote_id: target_folder.remote_id, @@ -275,10 +275,10 @@ export class FolderService { } let sharedLink; - if (folder.id_shared_link) { + if (folder.id_fs_shared_link) { const sl = await this.prisma.fs_shared_links.findUnique({ where: { - id_fs_shared_link: folder.id_shared_link, + id_fs_shared_link: folder.id_fs_shared_link, }, }); sharedLink = sl; @@ -423,10 +423,10 @@ export class FolderService { } let sharedLink; - if (folder.id_shared_link) { + if (folder.id_fs_shared_link) { const sl = await this.prisma.fs_shared_links.findUnique({ where: { - id_fs_shared_link: folder.id_shared_link, + id_fs_shared_link: folder.id_fs_shared_link, }, }); sharedLink = sl; diff --git a/packages/api/src/filestorage/permission/services/permission.service.ts b/packages/api/src/filestorage/permission/services/permission.service.ts index 21cd64aaa..49447bf3b 100644 --- a/packages/api/src/filestorage/permission/services/permission.service.ts +++ b/packages/api/src/filestorage/permission/services/permission.service.ts @@ -6,6 +6,8 @@ import { FieldMappingService } from '@@core/field-mapping/field-mapping.service' import { Injectable } from '@nestjs/common'; import { v4 as uuidv4 } from 'uuid'; import { + PermissionRole, + PermissionType, UnifiedPermissionInput, UnifiedPermissionOutput, } from '../types/model.unified'; @@ -66,8 +68,8 @@ export class PermissionService { id: permission.id_fs_permission, user_id: permission.user, group_id: permission.group, - type: permission.type, - roles: permission.roles, + type: permission.type as PermissionType, + roles: permission.roles as PermissionRole[], field_mappings: field_mappings, remote_id: permission.remote_id, created_at: permission.created_at, @@ -195,8 +197,8 @@ export class PermissionService { id: permission.id_fs_permission, user_id: permission.user, group_id: permission.group, - type: permission.type, - roles: permission.roles, + type: permission.type as PermissionType, + roles: permission.roles as PermissionRole[], field_mappings: field_mappings, remote_id: permission.remote_id, created_at: permission.created_at, diff --git a/packages/api/src/filestorage/permission/types/model.unified.ts b/packages/api/src/filestorage/permission/types/model.unified.ts index b25f41d7b..0cb654b16 100644 --- a/packages/api/src/filestorage/permission/types/model.unified.ts +++ b/packages/api/src/filestorage/permission/types/model.unified.ts @@ -1,14 +1,17 @@ import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger'; import { IsUUID, IsOptional, IsString } from 'class-validator'; +export type PermissionType = 'USER' | 'GROUP' | 'COMPANY' | 'ANYONE'; +export type PermissionRole = 'READ' | 'WRITE' | 'OWNER'; + export class UnifiedPermissionInput { @ApiProperty({ type: [String], description: 'The roles of the permission' }) @IsString() - roles: string[]; + roles: PermissionRole[]; @ApiProperty({ type: String, description: 'The type of the permission' }) @IsString() - type: string; + type: PermissionType; @ApiProperty({ type: String, diff --git a/packages/api/src/ticketing/@lib/@utils/index.ts b/packages/api/src/ticketing/@lib/@utils/index.ts index 60e4ab47d..d0806cf8b 100644 --- a/packages/api/src/ticketing/@lib/@utils/index.ts +++ b/packages/api/src/ticketing/@lib/@utils/index.ts @@ -149,6 +149,21 @@ export class Utils { } } + async getCollectionNameFromUuid(uuid: string) { + try { + const res = await this.prisma.tcg_collections.findFirst({ + where: { + id_tcg_collection: uuid, + }, + }); + if (!res) return undefined; + + return res.name; + } catch (error) { + throw error; + } + } + async getTicketUuidFromRemoteId(remote_id: string, connection_id: string) { try { const res = await this.prisma.tcg_tickets.findFirst({ diff --git a/packages/api/src/ticketing/attachment/attachment.controller.ts b/packages/api/src/ticketing/attachment/attachment.controller.ts index 5b7305920..a2aa48e56 100644 --- a/packages/api/src/ticketing/attachment/attachment.controller.ts +++ b/packages/api/src/ticketing/attachment/attachment.controller.ts @@ -160,8 +160,8 @@ export class AttachmentController { @ApiOperation({ operationId: 'create', - summary: 'Create a Attachment', - description: 'Create a attachment in any supported Ticketing software', + summary: 'Create an Attachment', + description: 'Create an attachment in any supported Ticketing software', }) @ApiHeader({ name: 'x-connection-token', diff --git a/packages/api/src/ticketing/collection/services/collection.service.ts b/packages/api/src/ticketing/collection/services/collection.service.ts index dbf96471e..27f665b9f 100644 --- a/packages/api/src/ticketing/collection/services/collection.service.ts +++ b/packages/api/src/ticketing/collection/services/collection.service.ts @@ -4,7 +4,10 @@ import { LoggerService } from '@@core/@core-services/logger/logger.service'; import { v4 as uuidv4 } from 'uuid'; import { throwTypedError, UnifiedTicketingError } from '@@core/utils/errors'; import { WebhookService } from '@@core/@core-services/webhooks/panora-webhooks/webhook.service'; -import { UnifiedCollectionOutput } from '../types/model.unified'; +import { + CollectionType, + UnifiedCollectionOutput, +} from '../types/model.unified'; import { FieldMappingService } from '@@core/field-mapping/field-mapping.service'; import { ServiceRegistry } from './registry.service'; @@ -37,7 +40,7 @@ export class CollectionService { id: collection.id_tcg_collection, name: collection.name, description: collection.description, - collection_type: collection.collection_type, + collection_type: collection.collection_type as CollectionType, remote_id: collection.remote_id, created_at: collection.created_at, modified_at: collection.modified_at, @@ -133,7 +136,7 @@ export class CollectionService { id: collection.id_tcg_collection, name: collection.name, description: collection.description, - collection_type: collection.collection_type, + collection_type: collection.collection_type as CollectionType, remote_id: collection.remote_id, created_at: collection.created_at, modified_at: collection.modified_at, diff --git a/packages/api/src/ticketing/collection/services/jira/mappers.ts b/packages/api/src/ticketing/collection/services/jira/mappers.ts index e58afe0ed..a74133723 100644 --- a/packages/api/src/ticketing/collection/services/jira/mappers.ts +++ b/packages/api/src/ticketing/collection/services/jira/mappers.ts @@ -59,7 +59,7 @@ export class JiraCollectionMapper implements ICollectionMapper { const unifiedCollection: UnifiedCollectionOutput = { remote_id: collection.id, remote_data: collection, - name: collection.name, + name: collection.key, description: collection.name, collection_type: 'PROJECT', }; diff --git a/packages/api/src/ticketing/collection/services/jira/types.ts b/packages/api/src/ticketing/collection/services/jira/types.ts index 9d1d7181a..af97b7a69 100644 --- a/packages/api/src/ticketing/collection/services/jira/types.ts +++ b/packages/api/src/ticketing/collection/services/jira/types.ts @@ -1,5 +1,5 @@ -export type JiraCollectionOutput = { - avatarUrls: AvatarUrls; +export type JiraCollectionInput = { + avatarUrls?: Partial; id: string; insight?: Insight; key: string; @@ -29,4 +29,4 @@ type ProjectCategory = { self: string; }; -export type JiraCollectionInput = null; +export type JiraCollectionOutput = Partial; diff --git a/packages/api/src/ticketing/collection/types/model.unified.ts b/packages/api/src/ticketing/collection/types/model.unified.ts index 8f7b7930d..fcda144f7 100644 --- a/packages/api/src/ticketing/collection/types/model.unified.ts +++ b/packages/api/src/ticketing/collection/types/model.unified.ts @@ -1,6 +1,8 @@ import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger'; import { IsIn, IsOptional, IsString, IsUUID } from 'class-validator'; +export type CollectionType = 'PROJECT' | 'LIST'; + export class UnifiedCollectionInput { @ApiProperty({ type: String, @@ -26,7 +28,7 @@ export class UnifiedCollectionInput { message: 'Type must be either PROJECT or LIST', }) @IsOptional() - collection_type?: string; + collection_type?: CollectionType; } export class UnifiedCollectionOutput extends UnifiedCollectionInput { diff --git a/packages/api/src/ticketing/comment/services/comment.service.ts b/packages/api/src/ticketing/comment/services/comment.service.ts index f63d738bf..41eb7fdd5 100644 --- a/packages/api/src/ticketing/comment/services/comment.service.ts +++ b/packages/api/src/ticketing/comment/services/comment.service.ts @@ -9,10 +9,12 @@ import { TicketingObject } from '@ticketing/@lib/@types'; import { v4 as uuidv4 } from 'uuid'; import { ICommentService } from '../types'; import { + CommentCreatorType, UnifiedCommentInput, UnifiedCommentOutput, } from '../types/model.unified'; import { ServiceRegistry } from './registry.service'; +import { CoreSyncRegistry } from '@@core/@core-services/registries/core-sync.registry'; @Injectable() export class CommentService { @@ -21,6 +23,7 @@ export class CommentService { private logger: LoggerService, private webhook: WebhookService, private serviceRegistry: ServiceRegistry, + private registry: CoreSyncRegistry, private coreUnification: CoreUnification, ) { this.logger.setContext(CommentService.name); @@ -40,7 +43,6 @@ export class CommentService { }, }); - //CHECKS if (!linkedUser) throw new ReferenceError('Linked User Not Found'); const tick = unifiedCommentData.ticket_id; //check if contact_id and account_id refer to real uuids @@ -88,19 +90,36 @@ export class CommentService { } const attachmts = unifiedCommentData.attachments; - //CHEK IF attachments contains valid Attachment uuids if (attachmts && attachmts.length > 0) { - attachmts.map(async (attachmt) => { - const search = await this.prisma.tcg_attachments.findUnique({ - where: { - id_tcg_attachment: attachmt, - }, + if (typeof attachmts[0] === 'string') { + // we have string array + // check if attachments contains valid Attachment uuids + attachmts.map(async (uuid: string) => { + const search = await this.prisma.tcg_attachments.findUnique({ + where: { + id_tcg_attachment: uuid, + }, + }); + if (!search) + throw new ReferenceError( + 'You inserted an attachment_id which does not exist', + ); }); - if (!search) - throw new ReferenceError( - 'You inserted an attachment_id which does not exist', + } else { + // we have a nested attachment object to process + const attchms_res = await this.registry + .getService('ticketing', 'attachment') + .saveToDb( + connection_id, + linkedUserId, + attachmts, + integrationId, + [], ); - }); + unifiedCommentData.attachments = attchms_res.map( + (att) => att.id_tcg_attachment, + ); + } } //desunify the data according to the target obj wanted @@ -155,11 +174,11 @@ export class CommentService { let unique_ticketing_comment_id: string; const opts = - target_comment.creator_type === 'contact' + target_comment.creator_type === 'CONTACT' ? { id_tcg_contact: unifiedCommentData.contact_id, } - : target_comment.creator_type === 'user' + : target_comment.creator_type === 'USER' ? { id_tcg_user: unifiedCommentData.user_id, } @@ -224,6 +243,22 @@ export class CommentService { unique_ticketing_comment_id = res.id_tcg_comment; } + // update parent comment id on attachment objects + + const uuids = unifiedCommentData.attachments as string[]; + + await Promise.all( + uuids.map(async (uuid) => { + const res = await this.prisma.tcg_attachments.update({ + where: { + id_tcg_attachment: uuid, + }, + data: { + id_tcg_comment: unique_ticketing_comment_id, + }, + }); + }), + ); //insert remote_data in db await this.prisma.remote_data.upsert({ where: { @@ -328,7 +363,7 @@ export class CommentService { body: comment.body, html_body: comment.html_body, is_private: comment.is_private, - creator_type: comment.creator_type as 'user' | 'contact', + creator_type: comment.creator_type as CommentCreatorType, ticket_id: comment.id_tcg_ticket, contact_id: comment.id_tcg_contact, // uuid of Contact object user_id: comment.id_tcg_user, // uuid of User object @@ -459,7 +494,7 @@ export class CommentService { body: comment.body, html_body: comment.html_body, is_private: comment.is_private, - creator_type: comment.creator_type as 'user' | 'contact', + creator_type: comment.creator_type as CommentCreatorType, ticket_id: comment.id_tcg_ticket, contact_id: comment.id_tcg_contact, // uuid of Contact object user_id: comment.id_tcg_user, // uuid of User object diff --git a/packages/api/src/ticketing/comment/services/front/mappers.ts b/packages/api/src/ticketing/comment/services/front/mappers.ts index 406d9a5d8..1b6f49e46 100644 --- a/packages/api/src/ticketing/comment/services/front/mappers.ts +++ b/packages/api/src/ticketing/comment/services/front/mappers.ts @@ -31,7 +31,7 @@ export class FrontCommentMapper implements ICommentMapper { const result: FrontCommentInput = { body: source.body, author_id: await this.utils.getUserRemoteIdFromUuid(source.user_id), // for Front it must be a User - attachments: source.attachments, + attachments: source.attachments as string[], }; return result; } diff --git a/packages/api/src/ticketing/comment/services/gorgias/index.ts b/packages/api/src/ticketing/comment/services/gorgias/index.ts index 4120c59bf..844a2aa94 100644 --- a/packages/api/src/ticketing/comment/services/gorgias/index.ts +++ b/packages/api/src/ticketing/comment/services/gorgias/index.ts @@ -42,43 +42,9 @@ export class GorgiasService implements ICommentService { }, }); - let uploads = []; - const uuids = commentData.attachments as any[]; - if (uuids && uuids.length > 0) { - const attachmentPromises = uuids.map(async (uuid) => { - const res = await this.prisma.tcg_attachments.findUnique({ - where: { - id_tcg_attachment: uuid.extra, - }, - }); - if (!res) { - throw new ReferenceError( - `tcg_attachment not found for uuid ${uuid}`, - ); - } - // Assuming you want to construct the right binary attachment here - // For now, we'll just return the URL - const stats = fs.statSync(res.file_url); - return { - url: res.file_url, - name: res.file_name, - size: stats.size, - content_type: 'application/pdf', //todo - }; - }); - uploads = await Promise.all(attachmentPromises); - } - - // Assuming you want to modify the comment object here - // For now, we'll just add the uploads to the comment - const data = { - ...commentData, - attachments: uploads, - }; - const resp = await axios.post( `${connection.account_url}/tickets/${remoteIdTicket}/messages`, - JSON.stringify(data), + JSON.stringify(commentData), { headers: { 'Content-Type': 'application/json', diff --git a/packages/api/src/ticketing/comment/services/gorgias/mappers.ts b/packages/api/src/ticketing/comment/services/gorgias/mappers.ts index 814b3e3e1..2fd7f3070 100644 --- a/packages/api/src/ticketing/comment/services/gorgias/mappers.ts +++ b/packages/api/src/ticketing/comment/services/gorgias/mappers.ts @@ -11,6 +11,8 @@ import { UnifiedCommentOutput, } from '@ticketing/comment/types/model.unified'; import { GorgiasCommentInput, GorgiasCommentOutput } from './types'; +import { PrismaService } from '@@core/@core-services/prisma/prisma.service'; +import * as fs from 'fs'; @Injectable() export class GorgiasCommentMapper implements ICommentMapper { @@ -18,6 +20,7 @@ export class GorgiasCommentMapper implements ICommentMapper { private mappersRegistry: MappersRegistry, private utils: Utils, private coreUnificationService: CoreUnification, + private prisma: PrismaService, ) { this.mappersRegistry.registerService( 'ticketing', @@ -34,6 +37,34 @@ export class GorgiasCommentMapper implements ICommentMapper { remote_id: string; }[], ): Promise { + let uploads = []; + if (source.attachments) { + const uuids = source.attachments as string[]; + if (uuids && uuids.length > 0) { + const attachmentPromises = uuids.map(async (uuid) => { + const res = await this.prisma.tcg_attachments.findUnique({ + where: { + id_tcg_attachment: uuid, + }, + }); + if (!res) { + throw new ReferenceError( + `tcg_attachment not found for uuid ${uuid}`, + ); + } + // Assuming you want to construct the right binary attachment here + // For now, we'll just return the URL + const stats = fs.statSync(res.file_url); + return { + url: res.file_url, + name: res.file_name, + size: stats.size, + content_type: 'application/pdf', //todo + }; + }); + uploads = await Promise.all(attachmentPromises); + } + } const result: GorgiasCommentInput = { sender: { id: @@ -49,8 +80,10 @@ export class GorgiasCommentMapper implements ICommentMapper { channel: 'chat', body_html: source.html_body, body_text: source.body, - attachments: source.attachments, }; + if (uploads && uploads.length > 0) { + result.attachments = uploads; + } return result; } diff --git a/packages/api/src/ticketing/comment/services/jira/mappers.ts b/packages/api/src/ticketing/comment/services/jira/mappers.ts index d08c103ee..08bfef15f 100644 --- a/packages/api/src/ticketing/comment/services/jira/mappers.ts +++ b/packages/api/src/ticketing/comment/services/jira/mappers.ts @@ -24,7 +24,7 @@ export class JiraCommentMapper implements ICommentMapper { body: source.body, }; if (source.attachments) { - result.attachments = source.attachments; + result.attachments = source.attachments as string[]; } return result; } diff --git a/packages/api/src/ticketing/comment/services/zendesk/mappers.ts b/packages/api/src/ticketing/comment/services/zendesk/mappers.ts index f15cdd91c..893775f39 100644 --- a/packages/api/src/ticketing/comment/services/zendesk/mappers.ts +++ b/packages/api/src/ticketing/comment/services/zendesk/mappers.ts @@ -54,7 +54,8 @@ export class ZendeskCommentMapper implements ICommentMapper { } if (source.attachments) { - result.uploads = source.attachments; //we let the array of uuids on purpose (it will be modified in the given service on the fly!) + // it is a string array of uuids of attachmts objects + result.uploads = source.attachments as string[]; } if (source.html_body) { diff --git a/packages/api/src/ticketing/comment/types/model.unified.ts b/packages/api/src/ticketing/comment/types/model.unified.ts index 73ab458ab..cffb2d0c7 100644 --- a/packages/api/src/ticketing/comment/types/model.unified.ts +++ b/packages/api/src/ticketing/comment/types/model.unified.ts @@ -5,6 +5,8 @@ import { } from '@ticketing/attachment/types/model.unified'; import { IsBoolean, IsIn, IsOptional, IsString, IsUUID } from 'class-validator'; +export type CommentCreatorType = 'USER' | 'CONTACT'; + export class UnifiedCommentInput { @ApiProperty({ type: String, description: 'The body of the comment' }) @IsString() @@ -35,7 +37,7 @@ export class UnifiedCommentInput { message: 'Type must be either USER or CONTACT', }) @IsOptional() - creator_type?: string; + creator_type?: CommentCreatorType; @ApiPropertyOptional({ type: String, diff --git a/packages/api/src/ticketing/tag/services/jira/index.ts b/packages/api/src/ticketing/tag/services/jira/index.ts index 15c667be2..897e382ee 100644 --- a/packages/api/src/ticketing/tag/services/jira/index.ts +++ b/packages/api/src/ticketing/tag/services/jira/index.ts @@ -46,23 +46,21 @@ export class JiraService implements ITagService { }, }); - //todo: TAGS - const resp = await axios.get(`${connection.account_url}/conversations`, { - headers: { - 'Content-Type': 'application/json', - Authorization: `Bearer ${this.cryptoService.decrypt( - connection.access_token, - )}`, + const resp = await axios.get( + `${connection.account_url}/issue/${ticket.remote_id}?fields=labels`, + { + headers: { + 'Content-Type': 'application/json', + Authorization: `Bearer ${this.cryptoService.decrypt( + connection.access_token, + )}`, + }, }, - }); - this.logger.log(`Synced jira tags !`); - - const conversation = resp.data._results.find( - (c) => c.id === ticket.remote_id, ); + this.logger.log(`Synced jira tags !`); return { - data: conversation.tags, + data: resp.data.fields.labels, message: 'Jira tags retrieved', statusCode: 200, }; diff --git a/packages/api/src/ticketing/tag/services/jira/mappers.ts b/packages/api/src/ticketing/tag/services/jira/mappers.ts index 6641a6969..5049047f4 100644 --- a/packages/api/src/ticketing/tag/services/jira/mappers.ts +++ b/packages/api/src/ticketing/tag/services/jira/mappers.ts @@ -48,7 +48,7 @@ export class JiraTagMapper implements ITagMapper { }[], ): UnifiedTagOutput { const unifiedTag: UnifiedTagOutput = { - remote_id: tag.id, + remote_id: tag.id ?? null, remote_data: tag, name: tag.name, }; diff --git a/packages/api/src/ticketing/ticket/services/front/mappers.ts b/packages/api/src/ticketing/ticket/services/front/mappers.ts index 56e203f42..35d24040a 100644 --- a/packages/api/src/ticketing/ticket/services/front/mappers.ts +++ b/packages/api/src/ticketing/ticket/services/front/mappers.ts @@ -7,6 +7,7 @@ import { TicketingObject } from '@ticketing/@lib/@types'; import { Utils } from '@ticketing/@lib/@utils'; import { ITicketMapper } from '@ticketing/ticket/types'; import { + TicketStatus, UnifiedTicketInput, UnifiedTicketOutput, } from '@ticketing/ticket/types/model.unified'; @@ -30,13 +31,13 @@ export class FrontTicketMapper implements ITicketMapper { ): Promise { const body_: any = {}; - if (source.comment.creator_type === 'user') { + if (source.comment.creator_type === 'USER') { body_.author_id = await this.utils.getAsigneeRemoteIdFromUserUuid( source.comment.user_id, ); } - if (source.comment.attachments) { - body_.attachments = source.comment.attachments; + if (source.attachments) { + body_.attachments = source.attachments as string[]; } const result: FrontTicketInput = { type: 'discussion', @@ -144,7 +145,7 @@ export class FrontTicketMapper implements ITicketMapper { remote_id: ticket.id, remote_data: ticket, name: ticket.subject, - status: ticket.status, + status: ticket.status as TicketStatus, description: ticket.subject, due_date: null, field_mappings: field_mappings, diff --git a/packages/api/src/ticketing/ticket/services/gitlab/mappers.ts b/packages/api/src/ticketing/ticket/services/gitlab/mappers.ts index 159c3cc26..8d0227f45 100644 --- a/packages/api/src/ticketing/ticket/services/gitlab/mappers.ts +++ b/packages/api/src/ticketing/ticket/services/gitlab/mappers.ts @@ -30,7 +30,7 @@ export class GitlabTicketMapper implements ITicketMapper { }[], ): Promise { const remote_project_id = await this.utils.getCollectionRemoteIdFromUuid( - source.collections[0], + source.collections[0] as string, ); const result: GitlabTicketInput = { diff --git a/packages/api/src/ticketing/ticket/services/gorgias/index.ts b/packages/api/src/ticketing/ticket/services/gorgias/index.ts index b0e3e36e1..f4a7baa31 100644 --- a/packages/api/src/ticketing/ticket/services/gorgias/index.ts +++ b/packages/api/src/ticketing/ticket/services/gorgias/index.ts @@ -43,12 +43,12 @@ export class GorgiasService implements ITicketService { const modifiedComments = await Promise.all( comments.map(async (comment) => { let uploads = []; - const uuids = comment.attachments as any[]; + const uuids = comment.attachments as string[]; if (uuids && uuids.length > 0) { const attachmentPromises = uuids.map(async (uuid) => { const res = await this.prisma.tcg_attachments.findUnique({ where: { - id_tcg_attachment: uuid.extra, + id_tcg_attachment: uuid, }, }); if (!res) { diff --git a/packages/api/src/ticketing/ticket/services/gorgias/mappers.ts b/packages/api/src/ticketing/ticket/services/gorgias/mappers.ts index 8a539b95b..2cd91c52c 100644 --- a/packages/api/src/ticketing/ticket/services/gorgias/mappers.ts +++ b/packages/api/src/ticketing/ticket/services/gorgias/mappers.ts @@ -46,13 +46,9 @@ export class GorgiasTicketMapper implements ITicketMapper { channel: source.type ?? 'email', body_html: source.comment.html_body || null, body_text: source.comment.body || null, - attachments: source.comment.attachments - ? source.comment.attachments.map((att) => ({ - extra: att, - })) - : [], + attachments: (source.attachments as string[]) ?? [], sender: - source.comment.creator_type === 'user' + source.comment.creator_type === 'USER' ? { id: Number( await this.utils.getAsigneeRemoteIdFromUserUuid( diff --git a/packages/api/src/ticketing/ticket/services/hubspot/mappers.ts b/packages/api/src/ticketing/ticket/services/hubspot/mappers.ts index 2187a779b..ccfa6fed3 100644 --- a/packages/api/src/ticketing/ticket/services/hubspot/mappers.ts +++ b/packages/api/src/ticketing/ticket/services/hubspot/mappers.ts @@ -1,6 +1,7 @@ import { ITicketMapper } from '@ticketing/ticket/types'; import { HubspotTicketInput, HubspotTicketOutput } from './types'; import { + TicketPriority, UnifiedTicketInput, UnifiedTicketOutput, } from '@ticketing/ticket/types/model.unified'; @@ -102,7 +103,7 @@ export class HubspotTicketMapper implements ITicketMapper { type: null, parent_ticket: null, completed_at: new Date(ticket.properties.hs_lastmodifieddate), - priority: ticket.properties.hs_ticket_priority, + priority: ticket.properties.hs_ticket_priority as TicketPriority, ...opts, field_mappings: field_mappings, }; diff --git a/packages/api/src/ticketing/ticket/services/jira/index.ts b/packages/api/src/ticketing/ticket/services/jira/index.ts index b2f4a1544..5af97c2d7 100644 --- a/packages/api/src/ticketing/ticket/services/jira/index.ts +++ b/packages/api/src/ticketing/ticket/services/jira/index.ts @@ -38,8 +38,6 @@ export class JiraService implements ITicketService { }, }); - //Add comment by calling the unified comment function but first insert the ticket base data - const resp = await axios.post( `${connection.account_url}/issue`, JSON.stringify(ticketData), @@ -53,7 +51,56 @@ export class JiraService implements ITicketService { }, ); - // Add comment if someone wants to add one when creation of the ticket + // todo: Add comment if someone wants to add one when creation of the ticket + + // Process attachments + let uploads = []; + const uuids = ticketData.attachments; + if (uuids && uuids.length > 0) { + uploads = await Promise.all( + uuids.map(async (uuid) => { + const attachment = await this.prisma.tcg_attachments.findUnique({ + where: { + id_tcg_attachment: uuid, + }, + }); + if (!attachment) { + throw new ReferenceError( + `tcg_attachment not found for uuid ${uuid}`, + ); + } + // TODO: Construct the right binary attachment + // Get the AWS S3 right file + // TODO: Check how to send a stream of a URL + return attachment.file_url; //await this.utils.fetchFileStreamFromURL(attachment.file_url); + }), + ); + } + + if (uploads.length > 0) { + const formData = new FormData(); + + uploads.forEach((fileStream, index) => { + //const stats = fs.statSync(fileStream); + //const fileSizeInBytes = stats.size; + formData.append('file', fileStream); //, { knownLength: fileSizeInBytes }); + }); + + // Send request with attachments + const resp_ = await axios.post( + `${connection.account_url}/issue/${resp.data.id}/attachments`, + formData, + { + headers: { + 'Content-Type': 'application/json', + 'X-Atlassian-Token': 'no-check', + Authorization: `Bearer ${this.cryptoService.decrypt( + connection.access_token, + )}`, + }, + }, + ); + } return { data: resp.data, diff --git a/packages/api/src/ticketing/ticket/services/jira/mappers.ts b/packages/api/src/ticketing/ticket/services/jira/mappers.ts index d689ae2e4..1336ea01b 100644 --- a/packages/api/src/ticketing/ticket/services/jira/mappers.ts +++ b/packages/api/src/ticketing/ticket/services/jira/mappers.ts @@ -1,6 +1,7 @@ import { ITicketMapper } from '@ticketing/ticket/types'; import { JiraTicketInput, JiraTicketOutput } from './types'; import { + TicketType, UnifiedTicketInput, UnifiedTicketOutput, } from '@ticketing/ticket/types/model.unified'; @@ -30,6 +31,19 @@ export class JiraTicketMapper implements ITicketMapper { this.mappersRegistry.registerService('ticketing', 'ticket', 'jira', this); } + mapToIssueTypeName(data: TicketType) { + switch (data) { + case 'BUG': + return 'Bug'; + case 'SUBTASK': + return 'Sub-task'; + case 'TASK': + return 'Task'; + case 'TO-DO': + return 'Story'; + } + } + async desunify( source: UnifiedTicketInput, customFieldMappings?: { @@ -37,19 +51,22 @@ export class JiraTicketMapper implements ITicketMapper { remote_id: string; }[], ): Promise { - if (!source.project_id) { + if (!source.collections[0]) { throw new ReferenceError( 'a project key/id is mandatory for Jira ticket creation', ); } + const project_name = await this.utils.getCollectionNameFromUuid( + source.collections[0] as string, + ); const result: JiraTicketInput = { fields: { project: { - key: source.project_id || null, + key: project_name || undefined, }, description: source.description, issuetype: { - name: source.type || null, + name: this.mapToIssueTypeName(source.type) || null, }, }, }; @@ -67,6 +84,10 @@ export class JiraTicketMapper implements ITicketMapper { result.fields.labels = source.tags as string[]; } + if (source.attachments) { + result.attachments = source.attachments as string[]; // dummy assigning we'll insert them in the service func + } + // Map custom fields if applicable /*TODO if (customFieldMappings && source.field_mappings) { result.meta = {}; // Ensure meta exists diff --git a/packages/api/src/ticketing/ticket/services/jira/types.ts b/packages/api/src/ticketing/ticket/services/jira/types.ts index e331135c4..d0d8c70ab 100644 --- a/packages/api/src/ticketing/ticket/services/jira/types.ts +++ b/packages/api/src/ticketing/ticket/services/jira/types.ts @@ -110,7 +110,7 @@ interface Issue { attachment: Attachment[]; 'sub-tasks': Partial[]; description: any; - project: Project; + project: Partial; comment: Partial[]; issuelinks: Partial[]; worklog: Partial[]; @@ -127,6 +127,7 @@ interface Issue { id: string; key: string; self: string; + [key: string]: any; } interface Watcher { diff --git a/packages/api/src/ticketing/ticket/services/ticket.service.ts b/packages/api/src/ticketing/ticket/services/ticket.service.ts index 9255dda67..6cbba4c18 100644 --- a/packages/api/src/ticketing/ticket/services/ticket.service.ts +++ b/packages/api/src/ticketing/ticket/services/ticket.service.ts @@ -10,10 +10,14 @@ import { TicketingObject } from '@ticketing/@lib/@types'; import { v4 as uuidv4 } from 'uuid'; import { ITicketService } from '../types'; import { + TicketPriority, + TicketStatus, + TicketType, UnifiedTicketInput, UnifiedTicketOutput, } from '../types/model.unified'; import { ServiceRegistry } from './registry.service'; +import { CoreSyncRegistry } from '@@core/@core-services/registries/core-sync.registry'; @Injectable() export class TicketService { @@ -23,6 +27,7 @@ export class TicketService { private webhook: WebhookService, private fieldMappingService: FieldMappingService, private serviceRegistry: ServiceRegistry, + private registry: CoreSyncRegistry, private coreUnification: CoreUnification, ) { this.logger.setContext(TicketService.name); @@ -85,6 +90,38 @@ export class TicketService { ); }); } + const attachmts = unifiedTicketData.attachments; + if (attachmts && attachmts.length > 0) { + if (typeof attachmts[0] === 'string') { + // we have string array + // check if attachments contains valid Attachment uuids + attachmts.map(async (uuid: string) => { + const search = await this.prisma.tcg_attachments.findUnique({ + where: { + id_tcg_attachment: uuid, + }, + }); + if (!search) + throw new ReferenceError( + 'You inserted an attachment_id which does not exist', + ); + }); + } else { + // we have a nested attachment object to process + const attchms_res = await this.registry + .getService('ticketing', 'attachment') + .saveToDb( + connection_id, + linkedUserId, + attachmts, + integrationId, + [], + ); + unifiedTicketData.attachments = attchms_res.map( + (att) => att.id_tcg_attachment, + ); + } + } // Retrieve custom field mappings // get potential fieldMappings and extract the original properties name const customFieldMappings = @@ -398,13 +435,13 @@ export class TicketService { const unifiedTicket: UnifiedTicketOutput = { id: ticket.id_tcg_ticket, name: ticket.name || null, - status: ticket.status || null, + status: (ticket.status as TicketStatus) || null, description: ticket.description || null, due_date: ticket.due_date || null, - type: ticket.ticket_type || null, + type: (ticket.ticket_type as TicketType) || null, parent_ticket: ticket.parent_ticket || null, completed_at: ticket.completed_at || null, - priority: ticket.priority || null, + priority: (ticket.priority as TicketPriority) || null, assigned_to: ticket.assigned_to || null, field_mappings: field_mappings, tags: tagsArray || null, @@ -570,13 +607,13 @@ export class TicketService { const unifiedTicket: UnifiedTicketOutput = { id: ticket.id_tcg_ticket, name: ticket.name || null, - status: ticket.status || null, + status: (ticket.status as TicketStatus) || null, description: ticket.description || null, due_date: ticket.due_date || null, - type: ticket.ticket_type || null, + type: (ticket.ticket_type as TicketType) || null, parent_ticket: ticket.parent_ticket || null, completed_at: ticket.completed_at || null, - priority: ticket.priority || null, + priority: (ticket.priority as TicketPriority) || null, assigned_to: ticket.assigned_to || [], tags: tagsArray || null, collections: collectionsArray || null, diff --git a/packages/api/src/ticketing/ticket/services/zendesk/mappers.ts b/packages/api/src/ticketing/ticket/services/zendesk/mappers.ts index d15ca171e..96f98b115 100644 --- a/packages/api/src/ticketing/ticket/services/zendesk/mappers.ts +++ b/packages/api/src/ticketing/ticket/services/zendesk/mappers.ts @@ -42,7 +42,7 @@ export class ZendeskTicketMapper implements ITicketMapper { comment: { body: source.comment.body || null, public: !source.comment.is_private || true, - uploads: source.comment.attachments || [], //fetch token attachments for this uuid, would be done on the fly in dest service + uploads: (source.attachments as string[]) ?? [], //fetch token attachments for this uuid, would be done on the fly in dest service }, }; if (source.comment.html_body) { diff --git a/packages/api/src/ticketing/ticket/types/model.unified.ts b/packages/api/src/ticketing/ticket/types/model.unified.ts index d0242d952..f4bbafec7 100644 --- a/packages/api/src/ticketing/ticket/types/model.unified.ts +++ b/packages/api/src/ticketing/ticket/types/model.unified.ts @@ -5,6 +5,10 @@ import { UnifiedCommentInput } from '@ticketing/comment/types/model.unified'; import { UnifiedTagOutput } from '@ticketing/tag/types/model.unified'; import { IsIn, IsOptional, IsString, IsUUID } from 'class-validator'; +export type TicketType = 'BUG' | 'SUBTASK' | 'TASK' | 'TO-DO'; +export type TicketStatus = 'OPEN' | 'CLOSED'; +export type TicketPriority = 'HIGH' | 'MEDIUM' | 'LOW'; + export class UnifiedTicketInput { @ApiProperty({ type: String, @@ -22,7 +26,7 @@ export class UnifiedTicketInput { message: 'Type must be either OPEN or CLOSED', }) @IsOptional() - status?: string; + status?: TicketStatus; @ApiProperty({ type: String, @@ -43,11 +47,11 @@ export class UnifiedTicketInput { description: 'The type of the ticket. Authorized values are PROBLEM, QUESTION, or TASK', }) - @IsIn(['PROBLEM', 'QUESTION', 'TASK'], { - message: 'Type must be either PROBLEM, QUESTION or TASK', + @IsIn(['BUG', 'SUBTASK', 'TASK', 'TO-DO'], { + message: 'Type must be either BUG, SUBTASK, TASK or TO-DO', }) @IsOptional() - type?: string; + type?: TicketType; @ApiPropertyOptional({ type: String, @@ -88,7 +92,7 @@ export class UnifiedTicketInput { message: 'Type must be either HIGH, MEDIUM or LOW', }) @IsOptional() - priority?: string; + priority?: TicketPriority; @ApiPropertyOptional({ type: [String],