From 8a2d3935630b329613feb287fa146b421a191d9e Mon Sep 17 00:00:00 2001
From: Guilherme Sborz
Date: Wed, 14 Aug 2024 18:29:26 -0300
Subject: [PATCH 01/49] fix: add missing columns to connector_sets migration
scripts
---
packages/api/scripts/init.sql | 2 ++
packages/api/scripts/seed.sql | 6 +++---
2 files changed, 5 insertions(+), 3 deletions(-)
diff --git a/packages/api/scripts/init.sql b/packages/api/scripts/init.sql
index ead5ee43c..534ed146f 100644
--- a/packages/api/scripts/init.sql
+++ b/packages/api/scripts/init.sql
@@ -545,6 +545,8 @@ CREATE TABLE connector_sets
ecom_shopify boolean NULL,
ecom_amazon boolean NULL,
ecom_squarespace boolean NULL,
+ hris_gusto boolean NULL,
+ ats_bamboohr boolean NULL,
CONSTRAINT PK_project_connector PRIMARY KEY ( id_connector_set )
);
diff --git a/packages/api/scripts/seed.sql b/packages/api/scripts/seed.sql
index 0bee28a94..dd3e6c570 100644
--- a/packages/api/scripts/seed.sql
+++ b/packages/api/scripts/seed.sql
@@ -2,9 +2,9 @@ INSERT INTO users (id_user, identification_strategy, email, password_hash, first
('0ce39030-2901-4c56-8db0-5e326182ec6b', 'b2c','local@panora.dev', '$2b$10$Y7Q8TWGyGuc5ecdIASbBsuXMo3q/Rs3/cnY.mLZP4tUgfGUOCUBlG', 'local', 'Panora');
INSERT INTO connector_sets (id_connector_set, crm_hubspot, crm_zoho, crm_pipedrive, crm_attio, crm_zendesk, crm_close, tcg_zendesk, tcg_gorgias, tcg_front, tcg_jira, tcg_gitlab, fs_box, tcg_github) VALUES
- ('1709da40-17f7-4d3a-93a0-96dc5da6ddd7', TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE),
- ('852dfff8-ab63-4530-ae49-e4b2924407f8', TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE),
- ('aed0f856-f802-4a79-8640-66d441581a99', TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE);
+ ('1709da40-17f7-4d3a-93a0-96dc5da6ddd7', TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE),
+ ('852dfff8-ab63-4530-ae49-e4b2924407f8', TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE),
+ ('aed0f856-f802-4a79-8640-66d441581a99', TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE);
INSERT INTO projects (id_project, name, sync_mode, id_user, id_connector_set) VALUES
('1e468c15-aa57-4448-aa2b-7fed640d1e3d', 'Project 1', 'pull', '0ce39030-2901-4c56-8db0-5e326182ec6b', '1709da40-17f7-4d3a-93a0-96dc5da6ddd7'),
From e02fb493f78fef7aa8ceb0f9de56b0806a2760f0 Mon Sep 17 00:00:00 2001
From: speakeasybot
Date: Fri, 16 Aug 2024 00:05:19 +0000
Subject: [PATCH 02/49] ci: regenerated with Speakeasy CLI v1.372.0
---
.speakeasy/workflow.lock | 6 +-
.../swagger/openapi-with-code-samples.yaml | 9867 ++++++++++++++---
2 files changed, 8463 insertions(+), 1410 deletions(-)
diff --git a/.speakeasy/workflow.lock b/.speakeasy/workflow.lock
index 0ab14de46..c8370252e 100644
--- a/.speakeasy/workflow.lock
+++ b/.speakeasy/workflow.lock
@@ -1,9 +1,9 @@
-speakeasyVersion: 1.366.0
+speakeasyVersion: 1.372.0
sources:
merge-code-samples-into-spec:
sourceNamespace: merge-code-samples-into-spec
- sourceRevisionDigest: sha256:61d763ced26b2104e5f13eb6e4b32bd0f598073da2505d842baaa9efd4c78ff1
- sourceBlobDigest: sha256:d53140203694ab341c7f9b60bcfce1995e2c287358ec29504fcb45b677d38918
+ sourceRevisionDigest: sha256:62bd8d64f8278dcb7b23d28bffcffbb549e57b5b9dc09bae93ac4c1112dbd09a
+ sourceBlobDigest: sha256:ebdf0ba69a79a32d558c774cfe0f0c32d742319ed3c3d3d887bf14ac67f417d8
tags:
- latest
- main
diff --git a/packages/api/swagger/openapi-with-code-samples.yaml b/packages/api/swagger/openapi-with-code-samples.yaml
index 63f5d5778..eac26bebd 100644
--- a/packages/api/swagger/openapi-with-code-samples.yaml
+++ b/packages/api/swagger/openapi-with-code-samples.yaml
@@ -483,8 +483,6 @@ paths:
schema:
type: string
responses:
- '200':
- description: ''
'201':
description: ''
content:
@@ -568,8 +566,6 @@ paths:
schema:
type: string
responses:
- '200':
- description: ''
'201':
description: ''
content:
@@ -663,8 +659,6 @@ paths:
type: object
additionalProperties: true
description: Dynamic event payload
- '201':
- description: ''
tags: *ref_0
x-speakeasy-group: webhooks
x-codeSamples:
@@ -6782,12 +6776,6 @@ paths:
application/json:
schema:
type: object
- '201':
- description: ''
- content:
- application/json:
- schema:
- type: object
tags: &ref_21
- passthrough
x-speakeasy-group: passthrough
@@ -8125,6 +8113,12 @@ paths:
label: createHrisEmployee
source: |-
import { Panora } from "@panora/sdk";
+ import {
+ UnifiedHrisEmployeeInputEmploymentStatus,
+ UnifiedHrisEmployeeInputEthnicity,
+ UnifiedHrisEmployeeInputGender,
+ UnifiedHrisEmployeeInputMaritalStatus,
+ } from "@panora/sdk/models/components";
const panora = new Panora({
apiKey: "",
@@ -8133,7 +8127,40 @@ paths:
async function run() {
const result = await panora.hris.employees.create({
xConnectionToken: "",
- unifiedHrisEmployeeInput: {},
+ unifiedHrisEmployeeInput: {
+ groups: [
+ "Group1",
+ "Group2",
+ ],
+ locations: [
+ "801f9ede-c698-4e66-a7fc-48d19eebaa4f",
+ ],
+ employeeNumber: "EMP001",
+ companyId: "801f9ede-c698-4e66-a7fc-48d19eebaa4f",
+ firstName: "John",
+ lastName: "Doe",
+ preferredName: "Johnny",
+ displayFullName: "John Doe",
+ username: "johndoe",
+ workEmail: "john.doe@company.com",
+ personalEmail: "john.doe@personal.com",
+ mobilePhoneNumber: "+1234567890",
+ employments: [
+ "801f9ede-c698-4e66-a7fc-48d19eebaa4f",
+ "801f9ede-c698-4e66-a7fc-48d19eebaa4f",
+ ],
+ ssn: "123-45-6789",
+ gender: UnifiedHrisEmployeeInputGender.Male,
+ ethnicity: UnifiedHrisEmployeeInputEthnicity.AmericanIndianOrAlaskaNative,
+ maritalStatus: UnifiedHrisEmployeeInputMaritalStatus.MarriedFilingSeparately,
+ dateOfBirth: new Date("1990-01-01"),
+ startDate: new Date("2020-01-01"),
+ employmentStatus: UnifiedHrisEmployeeInputEmploymentStatus.Active,
+ terminationDate: new Date("2025-01-01"),
+ avatarUrl: "https://example.com/avatar.jpg",
+ managerId: "801f9ede-c698-4e66-a7fc-48d19eebaa4f",
+ fieldMappings: {},
+ },
});
// Handle the result
@@ -9695,6 +9722,11 @@ paths:
label: createHrisTimeoff
source: |-
import { Panora } from "@panora/sdk";
+ import {
+ UnifiedHrisTimeoffInputRequestType,
+ UnifiedHrisTimeoffInputStatus,
+ UnifiedHrisTimeoffInputUnits,
+ } from "@panora/sdk/models/components";
const panora = new Panora({
apiKey: "",
@@ -9703,7 +9735,18 @@ paths:
async function run() {
const result = await panora.hris.timeoffs.create({
xConnectionToken: "",
- unifiedHrisTimeoffInput: {},
+ unifiedHrisTimeoffInput: {
+ employee: "801f9ede-c698-4e66-a7fc-48d19eebaa4f",
+ approver: "801f9ede-c698-4e66-a7fc-48d19eebaa4f",
+ status: UnifiedHrisTimeoffInputStatus.Requested,
+ employeeNote: "Annual vacation",
+ units: UnifiedHrisTimeoffInputUnits.Days,
+ amount: 5,
+ requestType: UnifiedHrisTimeoffInputRequestType.Vacation,
+ startTime: new Date("2024-07-01T09:00:00Z"),
+ endTime: new Date("2024-07-05T17:00:00Z"),
+ fieldMappings: {},
+ },
});
// Handle the result
@@ -10071,6 +10114,204 @@ paths:
- lang: ruby
label: retrieveHrisTimeoffbalance
source: "require 'panora'\n\n\ns = ::OpenApiSDK::Panora.new\ns.config_security(\n ::OpenApiSDK::Shared::Security.new(\n api_key: \"\",\n )\n)\n\n \nres = s.hris_timeoffbalances.retrieve(x_connection_token=\"\", id=\"801f9ede-c698-4e66-a7fc-48d19eebaa4f\", remote_data=false)\n\nif ! res.unified_hris_timeoffbalance_output.nil?\n # handle response\nend"
+ /hris/timesheetentries:
+ get:
+ operationId: listHrisTimesheetentries
+ summary: List Timesheetentries
+ parameters:
+ - name: x-connection-token
+ required: true
+ in: header
+ description: The connection token
+ schema:
+ type: string
+ - name: remote_data
+ required: false
+ in: query
+ example: true
+ description: Set to true to include data from the original software.
+ schema:
+ type: boolean
+ - name: limit
+ required: false
+ in: query
+ example: 10
+ description: Set to get the number of records.
+ schema:
+ default: 50
+ type: number
+ - name: cursor
+ required: false
+ in: query
+ example: 1b8b05bb-5273-4012-b520-8657b0b90874
+ description: Set to get the number of records after this cursor.
+ schema:
+ type: string
+ responses:
+ '200':
+ description: ''
+ content:
+ application/json:
+ schema:
+ allOf:
+ - $ref: '#/components/schemas/PaginatedDto'
+ - properties:
+ data:
+ type: array
+ items:
+ $ref: '#/components/schemas/UnifiedHrisTimesheetEntryOutput'
+ tags: &ref_36
+ - hris/timesheetentries
+ x-speakeasy-group: hris.timesheetentries
+ x-speakeasy-pagination:
+ type: cursor
+ inputs:
+ - name: cursor
+ in: parameters
+ type: cursor
+ outputs:
+ nextCursor: $.next_cursor
+ x-codeSamples:
+ - lang: typescript
+ label: listHrisTimesheetentries
+ source: |-
+ import { Panora } from "@panora/sdk";
+
+ const panora = new Panora({
+ apiKey: "",
+ });
+
+ async function run() {
+ const result = await panora.hris.timesheetentries.list({
+ xConnectionToken: "",
+ remoteData: true,
+ limit: 10,
+ cursor: "1b8b05bb-5273-4012-b520-8657b0b90874",
+ });
+
+ for await (const page of result) {
+ // handle page
+ }
+ }
+
+ run();
+ post:
+ operationId: createHrisTimesheetentry
+ summary: Create Timesheetentrys
+ description: Create Timesheetentrys in any supported Hris software
+ parameters:
+ - name: x-connection-token
+ required: true
+ in: header
+ description: The connection token
+ schema:
+ type: string
+ - name: remote_data
+ required: false
+ in: query
+ description: Set to true to include data from the original Hris software.
+ schema:
+ type: boolean
+ requestBody:
+ required: true
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/UnifiedHrisTimesheetEntryInput'
+ responses:
+ '201':
+ description: ''
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/UnifiedHrisTimesheetEntryOutput'
+ tags: *ref_36
+ x-speakeasy-group: hris.timesheetentries
+ x-codeSamples:
+ - lang: typescript
+ label: createHrisTimesheetentry
+ source: |-
+ import { Panora } from "@panora/sdk";
+
+ const panora = new Panora({
+ apiKey: "",
+ });
+
+ async function run() {
+ const result = await panora.hris.timesheetentries.create({
+ xConnectionToken: "",
+ unifiedHrisTimesheetEntryInput: {
+ hoursWorked: 40,
+ startTime: new Date("2024-10-01T08:00:00Z"),
+ endTime: new Date("2024-10-01T16:00:00Z"),
+ employeeId: "801f9ede-c698-4e66-a7fc-48d19eebaa4f",
+ remoteWasDeleted: false,
+ fieldMappings: {},
+ },
+ });
+
+ // Handle the result
+ console.log(result)
+ }
+
+ run();
+ /hris/timesheetentries/{id}:
+ get:
+ operationId: retrieveHrisTimesheetentry
+ summary: Retrieve Timesheetentry
+ description: Retrieve an Timesheetentry from any connected Hris software
+ parameters:
+ - name: x-connection-token
+ required: true
+ in: header
+ description: The connection token
+ schema:
+ type: string
+ - name: id
+ required: true
+ in: path
+ description: id of the timesheetentry you want to retrieve.
+ example: 801f9ede-c698-4e66-a7fc-48d19eebaa4f
+ schema:
+ type: string
+ - name: remote_data
+ required: false
+ in: query
+ description: Set to true to include data from the original Hris software.
+ example: false
+ schema:
+ type: boolean
+ responses:
+ '200':
+ description: ''
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/UnifiedHrisTimesheetEntryOutput'
+ tags: *ref_36
+ x-speakeasy-group: hris.timesheetentries
+ x-codeSamples:
+ - lang: typescript
+ label: retrieveHrisTimesheetentry
+ source: |-
+ import { Panora } from "@panora/sdk";
+
+ const panora = new Panora({
+ apiKey: "",
+ });
+
+ async function run() {
+ const result = await panora.hris.timesheetentries.retrieve({
+ xConnectionToken: "",
+ id: "801f9ede-c698-4e66-a7fc-48d19eebaa4f",
+ remoteData: false,
+ });
+
+ // Handle the result
+ console.log(result)
+ }
+
+ run();
/marketingautomation/actions:
get:
operationId: listMarketingautomationAction
@@ -10118,7 +10359,7 @@ paths:
items:
$ref: >-
#/components/schemas/UnifiedMarketingautomationActionOutput
- tags: &ref_36
+ tags: &ref_37
- marketingautomation/actions
x-speakeasy-group: marketingautomation.actions
x-speakeasy-pagination:
@@ -10210,7 +10451,7 @@ paths:
application/json:
schema:
$ref: '#/components/schemas/UnifiedMarketingautomationActionOutput'
- tags: *ref_36
+ tags: *ref_37
x-speakeasy-group: marketingautomation.actions
x-codeSamples:
- lang: typescript
@@ -10316,7 +10557,7 @@ paths:
application/json:
schema:
$ref: '#/components/schemas/UnifiedMarketingautomationActionOutput'
- tags: *ref_36
+ tags: *ref_37
x-speakeasy-group: marketingautomation.actions
x-codeSamples:
- lang: typescript
@@ -10434,7 +10675,7 @@ paths:
items:
$ref: >-
#/components/schemas/UnifiedMarketingautomationAutomationOutput
- tags: &ref_37
+ tags: &ref_38
- marketingautomation/automations
x-speakeasy-group: marketingautomation.automations
x-speakeasy-pagination:
@@ -10527,7 +10768,7 @@ paths:
schema:
$ref: >-
#/components/schemas/UnifiedMarketingautomationAutomationOutput
- tags: *ref_37
+ tags: *ref_38
x-speakeasy-group: marketingautomation.automations
x-codeSamples:
- lang: typescript
@@ -10634,7 +10875,7 @@ paths:
schema:
$ref: >-
#/components/schemas/UnifiedMarketingautomationAutomationOutput
- tags: *ref_37
+ tags: *ref_38
x-speakeasy-group: marketingautomation.automations
x-codeSamples:
- lang: typescript
@@ -10752,7 +10993,7 @@ paths:
items:
$ref: >-
#/components/schemas/UnifiedMarketingautomationCampaignOutput
- tags: &ref_38
+ tags: &ref_39
- marketingautomation/campaigns
x-speakeasy-group: marketingautomation.campaigns
x-speakeasy-pagination:
@@ -10844,7 +11085,7 @@ paths:
application/json:
schema:
$ref: '#/components/schemas/UnifiedMarketingautomationCampaignOutput'
- tags: *ref_38
+ tags: *ref_39
x-speakeasy-group: marketingautomation.campaigns
x-codeSamples:
- lang: typescript
@@ -10950,7 +11191,7 @@ paths:
application/json:
schema:
$ref: '#/components/schemas/UnifiedMarketingautomationCampaignOutput'
- tags: *ref_38
+ tags: *ref_39
x-speakeasy-group: marketingautomation.campaigns
x-codeSamples:
- lang: typescript
@@ -11068,7 +11309,7 @@ paths:
items:
$ref: >-
#/components/schemas/UnifiedMarketingautomationContactOutput
- tags: &ref_39
+ tags: &ref_40
- marketingautomation/contacts
x-speakeasy-group: marketingautomation.contacts
x-speakeasy-pagination:
@@ -11160,7 +11401,7 @@ paths:
application/json:
schema:
$ref: '#/components/schemas/UnifiedMarketingautomationContactOutput'
- tags: *ref_39
+ tags: *ref_40
x-speakeasy-group: marketingautomation.contacts
x-codeSamples:
- lang: typescript
@@ -11266,7 +11507,7 @@ paths:
application/json:
schema:
$ref: '#/components/schemas/UnifiedMarketingautomationContactOutput'
- tags: *ref_39
+ tags: *ref_40
x-speakeasy-group: marketingautomation.contacts
x-codeSamples:
- lang: typescript
@@ -11384,7 +11625,7 @@ paths:
items:
$ref: >-
#/components/schemas/UnifiedMarketingautomationEmailOutput
- tags: &ref_40
+ tags: &ref_41
- marketingautomation/emails
x-speakeasy-group: marketingautomation.emails
x-speakeasy-pagination:
@@ -11478,7 +11719,7 @@ paths:
application/json:
schema:
$ref: '#/components/schemas/UnifiedMarketingautomationEmailOutput'
- tags: *ref_40
+ tags: *ref_41
x-speakeasy-group: marketingautomation.emails
x-codeSamples:
- lang: typescript
@@ -11596,7 +11837,7 @@ paths:
items:
$ref: >-
#/components/schemas/UnifiedMarketingautomationEventOutput
- tags: &ref_41
+ tags: &ref_42
- marketingautomation/events
x-speakeasy-group: marketingautomation.events
x-speakeasy-pagination:
@@ -11690,7 +11931,7 @@ paths:
application/json:
schema:
$ref: '#/components/schemas/UnifiedMarketingautomationEventOutput'
- tags: *ref_41
+ tags: *ref_42
x-speakeasy-group: marketingautomation.events
x-codeSamples:
- lang: typescript
@@ -11808,7 +12049,7 @@ paths:
items:
$ref: >-
#/components/schemas/UnifiedMarketingautomationListOutput
- tags: &ref_42
+ tags: &ref_43
- marketingautomation/lists
x-speakeasy-group: marketingautomation.lists
x-speakeasy-pagination:
@@ -11899,7 +12140,7 @@ paths:
application/json:
schema:
$ref: '#/components/schemas/UnifiedMarketingautomationListOutput'
- tags: *ref_42
+ tags: *ref_43
x-speakeasy-group: marketingautomation.lists
x-codeSamples:
- lang: typescript
@@ -12002,7 +12243,7 @@ paths:
application/json:
schema:
$ref: '#/components/schemas/UnifiedMarketingautomationListOutput'
- tags: *ref_42
+ tags: *ref_43
x-speakeasy-group: marketingautomation.lists
x-codeSamples:
- lang: typescript
@@ -12120,7 +12361,7 @@ paths:
items:
$ref: >-
#/components/schemas/UnifiedMarketingautomationMessageOutput
- tags: &ref_43
+ tags: &ref_44
- marketingautomation/messages
x-speakeasy-group: marketingautomation.messages
x-speakeasy-pagination:
@@ -12214,7 +12455,7 @@ paths:
application/json:
schema:
$ref: '#/components/schemas/UnifiedMarketingautomationMessageOutput'
- tags: *ref_43
+ tags: *ref_44
x-speakeasy-group: marketingautomation.messages
x-codeSamples:
- lang: typescript
@@ -12332,7 +12573,7 @@ paths:
items:
$ref: >-
#/components/schemas/UnifiedMarketingautomationTemplateOutput
- tags: &ref_44
+ tags: &ref_45
- marketingautomation/templates
x-speakeasy-group: marketingautomation.templates
x-speakeasy-pagination:
@@ -12423,7 +12664,7 @@ paths:
application/json:
schema:
$ref: '#/components/schemas/UnifiedMarketingautomationTemplateOutput'
- tags: *ref_44
+ tags: *ref_45
x-speakeasy-group: marketingautomation.templates
x-codeSamples:
- lang: typescript
@@ -12526,7 +12767,7 @@ paths:
application/json:
schema:
$ref: '#/components/schemas/UnifiedMarketingautomationTemplateOutput'
- tags: *ref_44
+ tags: *ref_45
x-speakeasy-group: marketingautomation.templates
x-codeSamples:
- lang: typescript
@@ -12644,7 +12885,7 @@ paths:
items:
$ref: >-
#/components/schemas/UnifiedMarketingautomationUserOutput
- tags: &ref_45
+ tags: &ref_46
- marketingautomation/users
x-speakeasy-group: marketingautomation.users
x-speakeasy-pagination:
@@ -12738,7 +12979,7 @@ paths:
application/json:
schema:
$ref: '#/components/schemas/UnifiedMarketingautomationUserOutput'
- tags: *ref_45
+ tags: *ref_46
x-speakeasy-group: marketingautomation.users
x-codeSamples:
- lang: typescript
@@ -12855,7 +13096,7 @@ paths:
type: array
items:
$ref: '#/components/schemas/UnifiedAtsActivityOutput'
- tags: &ref_46
+ tags: &ref_47
- ats/activities
x-speakeasy-group: ats.activities
x-speakeasy-pagination:
@@ -12946,7 +13187,7 @@ paths:
application/json:
schema:
$ref: '#/components/schemas/UnifiedAtsActivityOutput'
- tags: *ref_46
+ tags: *ref_47
x-speakeasy-group: ats.activities
x-codeSamples:
- lang: typescript
@@ -13088,7 +13329,7 @@ paths:
application/json:
schema:
$ref: '#/components/schemas/UnifiedAtsActivityOutput'
- tags: *ref_46
+ tags: *ref_47
x-speakeasy-group: ats.activities
x-codeSamples:
- lang: typescript
@@ -13205,7 +13446,7 @@ paths:
type: array
items:
$ref: '#/components/schemas/UnifiedAtsApplicationOutput'
- tags: &ref_47
+ tags: &ref_48
- ats/applications
x-speakeasy-group: ats.applications
x-speakeasy-pagination:
@@ -13296,7 +13537,7 @@ paths:
application/json:
schema:
$ref: '#/components/schemas/UnifiedAtsApplicationOutput'
- tags: *ref_47
+ tags: *ref_48
x-speakeasy-group: ats.applications
x-codeSamples:
- lang: typescript
@@ -13454,7 +13695,7 @@ paths:
application/json:
schema:
$ref: '#/components/schemas/UnifiedAtsApplicationOutput'
- tags: *ref_47
+ tags: *ref_48
x-speakeasy-group: ats.applications
x-codeSamples:
- lang: typescript
@@ -13571,7 +13812,7 @@ paths:
type: array
items:
$ref: '#/components/schemas/UnifiedAtsAttachmentOutput'
- tags: &ref_48
+ tags: &ref_49
- ats/attachments
x-speakeasy-group: ats.attachments
x-speakeasy-pagination:
@@ -13662,7 +13903,7 @@ paths:
application/json:
schema:
$ref: '#/components/schemas/UnifiedAtsAttachmentOutput'
- tags: *ref_48
+ tags: *ref_49
x-speakeasy-group: ats.attachments
x-codeSamples:
- lang: typescript
@@ -13804,7 +14045,7 @@ paths:
application/json:
schema:
$ref: '#/components/schemas/UnifiedAtsAttachmentOutput'
- tags: *ref_48
+ tags: *ref_49
x-speakeasy-group: ats.attachments
x-codeSamples:
- lang: typescript
@@ -13921,7 +14162,7 @@ paths:
type: array
items:
$ref: '#/components/schemas/UnifiedAtsCandidateOutput'
- tags: &ref_49
+ tags: &ref_50
- ats/candidates
x-speakeasy-group: ats.candidates
x-speakeasy-pagination:
@@ -14012,7 +14253,7 @@ paths:
application/json:
schema:
$ref: '#/components/schemas/UnifiedAtsCandidateOutput'
- tags: *ref_49
+ tags: *ref_50
x-speakeasy-group: ats.candidates
x-codeSamples:
- lang: typescript
@@ -14258,7 +14499,7 @@ paths:
application/json:
schema:
$ref: '#/components/schemas/UnifiedAtsCandidateOutput'
- tags: *ref_49
+ tags: *ref_50
x-speakeasy-group: ats.candidates
x-codeSamples:
- lang: typescript
@@ -14375,7 +14616,7 @@ paths:
type: array
items:
$ref: '#/components/schemas/UnifiedAtsDepartmentOutput'
- tags: &ref_50
+ tags: &ref_51
- ats/departments
x-speakeasy-group: ats.departments
x-speakeasy-pagination:
@@ -14468,7 +14709,7 @@ paths:
application/json:
schema:
$ref: '#/components/schemas/UnifiedAtsDepartmentOutput'
- tags: *ref_50
+ tags: *ref_51
x-speakeasy-group: ats.departments
x-codeSamples:
- lang: typescript
@@ -14585,7 +14826,7 @@ paths:
type: array
items:
$ref: '#/components/schemas/UnifiedAtsInterviewOutput'
- tags: &ref_51
+ tags: &ref_52
- ats/interviews
x-speakeasy-group: ats.interviews
x-speakeasy-pagination:
@@ -14676,7 +14917,7 @@ paths:
application/json:
schema:
$ref: '#/components/schemas/UnifiedAtsInterviewOutput'
- tags: *ref_51
+ tags: *ref_52
x-speakeasy-group: ats.interviews
x-codeSamples:
- lang: typescript
@@ -14836,7 +15077,7 @@ paths:
application/json:
schema:
$ref: '#/components/schemas/UnifiedAtsInterviewOutput'
- tags: *ref_51
+ tags: *ref_52
x-speakeasy-group: ats.interviews
x-codeSamples:
- lang: typescript
@@ -14954,7 +15195,7 @@ paths:
items:
$ref: >-
#/components/schemas/UnifiedAtsJobinterviewstageOutput
- tags: &ref_52
+ tags: &ref_53
- ats/jobinterviewstages
x-speakeasy-group: ats.jobinterviewstages
x-speakeasy-pagination:
@@ -15047,7 +15288,7 @@ paths:
application/json:
schema:
$ref: '#/components/schemas/UnifiedAtsJobinterviewstageOutput'
- tags: *ref_52
+ tags: *ref_53
x-speakeasy-group: ats.jobinterviewstages
x-codeSamples:
- lang: typescript
@@ -15164,7 +15405,7 @@ paths:
type: array
items:
$ref: '#/components/schemas/UnifiedAtsJobOutput'
- tags: &ref_53
+ tags: &ref_54
- ats/jobs
x-speakeasy-group: ats.jobs
x-speakeasy-pagination:
@@ -15257,7 +15498,7 @@ paths:
application/json:
schema:
$ref: '#/components/schemas/UnifiedAtsJobOutput'
- tags: *ref_53
+ tags: *ref_54
x-speakeasy-group: ats.jobs
x-codeSamples:
- lang: typescript
@@ -15374,7 +15615,7 @@ paths:
type: array
items:
$ref: '#/components/schemas/UnifiedAtsOfferOutput'
- tags: &ref_54
+ tags: &ref_55
- ats/offers
x-speakeasy-group: ats.offers
x-speakeasy-pagination:
@@ -15467,7 +15708,7 @@ paths:
application/json:
schema:
$ref: '#/components/schemas/UnifiedAtsOfferOutput'
- tags: *ref_54
+ tags: *ref_55
x-speakeasy-group: ats.offers
x-codeSamples:
- lang: typescript
@@ -15584,7 +15825,7 @@ paths:
type: array
items:
$ref: '#/components/schemas/UnifiedAtsOfficeOutput'
- tags: &ref_55
+ tags: &ref_56
- ats/offices
x-speakeasy-group: ats.offices
x-speakeasy-pagination:
@@ -15677,7 +15918,7 @@ paths:
application/json:
schema:
$ref: '#/components/schemas/UnifiedAtsOfficeOutput'
- tags: *ref_55
+ tags: *ref_56
x-speakeasy-group: ats.offices
x-codeSamples:
- lang: typescript
@@ -15794,7 +16035,7 @@ paths:
type: array
items:
$ref: '#/components/schemas/UnifiedAtsRejectreasonOutput'
- tags: &ref_56
+ tags: &ref_57
- ats/rejectreasons
x-speakeasy-group: ats.rejectreasons
x-speakeasy-pagination:
@@ -15887,7 +16128,7 @@ paths:
application/json:
schema:
$ref: '#/components/schemas/UnifiedAtsRejectreasonOutput'
- tags: *ref_56
+ tags: *ref_57
x-speakeasy-group: ats.rejectreasons
x-codeSamples:
- lang: typescript
@@ -16004,7 +16245,7 @@ paths:
type: array
items:
$ref: '#/components/schemas/UnifiedAtsScorecardOutput'
- tags: &ref_57
+ tags: &ref_58
- ats/scorecards
x-speakeasy-group: ats.scorecards
x-speakeasy-pagination:
@@ -16097,7 +16338,7 @@ paths:
application/json:
schema:
$ref: '#/components/schemas/UnifiedAtsScorecardOutput'
- tags: *ref_57
+ tags: *ref_58
x-speakeasy-group: ats.scorecards
x-codeSamples:
- lang: typescript
@@ -16214,7 +16455,7 @@ paths:
type: array
items:
$ref: '#/components/schemas/UnifiedAtsTagOutput'
- tags: &ref_58
+ tags: &ref_59
- ats/tags
x-speakeasy-group: ats.tags
x-speakeasy-pagination:
@@ -16307,7 +16548,7 @@ paths:
application/json:
schema:
$ref: '#/components/schemas/UnifiedAtsTagOutput'
- tags: *ref_58
+ tags: *ref_59
x-speakeasy-group: ats.tags
x-codeSamples:
- lang: typescript
@@ -16424,7 +16665,7 @@ paths:
type: array
items:
$ref: '#/components/schemas/UnifiedAtsUserOutput'
- tags: &ref_59
+ tags: &ref_60
- ats/users
x-speakeasy-group: ats.users
x-speakeasy-pagination:
@@ -16517,7 +16758,7 @@ paths:
application/json:
schema:
$ref: '#/components/schemas/UnifiedAtsUserOutput'
- tags: *ref_59
+ tags: *ref_60
x-speakeasy-group: ats.users
x-codeSamples:
- lang: typescript
@@ -16634,7 +16875,7 @@ paths:
type: array
items:
$ref: '#/components/schemas/UnifiedAtsEeocsOutput'
- tags: &ref_60
+ tags: &ref_61
- ats/eeocs
x-speakeasy-group: ats.eeocs
x-speakeasy-pagination:
@@ -16725,7 +16966,7 @@ paths:
application/json:
schema:
$ref: '#/components/schemas/UnifiedAtsEeocsOutput'
- tags: *ref_60
+ tags: *ref_61
x-speakeasy-group: ats.eeocs
x-codeSamples:
- lang: typescript
@@ -16839,7 +17080,7 @@ paths:
type: array
items:
$ref: '#/components/schemas/UnifiedAccountingAccountOutput'
- tags: &ref_61
+ tags: &ref_62
- accounting/accounts
x-speakeasy-group: accounting.accounts
x-speakeasy-pagination:
@@ -16930,13 +17171,14 @@ paths:
application/json:
schema:
$ref: '#/components/schemas/UnifiedAccountingAccountOutput'
- tags: *ref_61
+ tags: *ref_62
x-speakeasy-group: accounting.accounts
x-codeSamples:
- lang: typescript
label: createAccountingAccount
source: |-
import { Panora } from "@panora/sdk";
+ import { UnifiedAccountingAccountInputCurrency } from "@panora/sdk/models/components";
const panora = new Panora({
apiKey: "",
@@ -16946,7 +17188,19 @@ paths:
const result = await panora.accounting.accounts.create({
xConnectionToken: "",
remoteData: false,
- unifiedAccountingAccountInput: {},
+ unifiedAccountingAccountInput: {
+ name: "Cash",
+ description: "Main cash account for daily operations",
+ classification: "Asset",
+ type: "Current Asset",
+ status: "Active",
+ currentBalance: 10000,
+ currency: UnifiedAccountingAccountInputCurrency.Usd,
+ accountNumber: "1000",
+ parentAccount: "801f9ede-c698-4e66-a7fc-48d19eebaa4f",
+ companyInfoId: "801f9ede-c698-4e66-a7fc-48d19eebaa4f",
+ fieldMappings: {},
+ },
});
// Handle the result
@@ -17035,7 +17289,7 @@ paths:
application/json:
schema:
$ref: '#/components/schemas/UnifiedAccountingAccountOutput'
- tags: *ref_61
+ tags: *ref_62
x-speakeasy-group: accounting.accounts
x-codeSamples:
- lang: typescript
@@ -17152,7 +17406,7 @@ paths:
type: array
items:
$ref: '#/components/schemas/UnifiedAccountingAddressOutput'
- tags: &ref_62
+ tags: &ref_63
- accounting/addresses
x-speakeasy-group: accounting.addresses
x-speakeasy-pagination:
@@ -17245,7 +17499,7 @@ paths:
application/json:
schema:
$ref: '#/components/schemas/UnifiedAccountingAddressOutput'
- tags: *ref_62
+ tags: *ref_63
x-speakeasy-group: accounting.addresses
x-codeSamples:
- lang: typescript
@@ -17363,7 +17617,7 @@ paths:
items:
$ref: >-
#/components/schemas/UnifiedAccountingAttachmentOutput
- tags: &ref_63
+ tags: &ref_64
- accounting/attachments
x-speakeasy-group: accounting.attachments
x-speakeasy-pagination:
@@ -17454,7 +17708,7 @@ paths:
application/json:
schema:
$ref: '#/components/schemas/UnifiedAccountingAttachmentOutput'
- tags: *ref_63
+ tags: *ref_64
x-speakeasy-group: accounting.attachments
x-codeSamples:
- lang: typescript
@@ -17470,7 +17724,12 @@ paths:
const result = await panora.accounting.attachments.create({
xConnectionToken: "",
remoteData: false,
- unifiedAccountingAttachmentInput: {},
+ unifiedAccountingAttachmentInput: {
+ fileName: "invoice.pdf",
+ fileUrl: "https://example.com/files/invoice.pdf",
+ accountId: "801f9ede-c698-4e66-a7fc-48d19eebaa4f",
+ fieldMappings: {},
+ },
});
// Handle the result
@@ -17559,7 +17818,7 @@ paths:
application/json:
schema:
$ref: '#/components/schemas/UnifiedAccountingAttachmentOutput'
- tags: *ref_63
+ tags: *ref_64
x-speakeasy-group: accounting.attachments
x-codeSamples:
- lang: typescript
@@ -17677,7 +17936,7 @@ paths:
items:
$ref: >-
#/components/schemas/UnifiedAccountingBalancesheetOutput
- tags: &ref_64
+ tags: &ref_65
- accounting/balancesheets
x-speakeasy-group: accounting.balancesheets
x-speakeasy-pagination:
@@ -17770,7 +18029,7 @@ paths:
application/json:
schema:
$ref: '#/components/schemas/UnifiedAccountingBalancesheetOutput'
- tags: *ref_64
+ tags: *ref_65
x-speakeasy-group: accounting.balancesheets
x-codeSamples:
- lang: typescript
@@ -17888,7 +18147,7 @@ paths:
items:
$ref: >-
#/components/schemas/UnifiedAccountingCashflowstatementOutput
- tags: &ref_65
+ tags: &ref_66
- accounting/cashflowstatements
x-speakeasy-group: accounting.cashflowstatements
x-speakeasy-pagination:
@@ -17981,7 +18240,7 @@ paths:
application/json:
schema:
$ref: '#/components/schemas/UnifiedAccountingCashflowstatementOutput'
- tags: *ref_65
+ tags: *ref_66
x-speakeasy-group: accounting.cashflowstatements
x-codeSamples:
- lang: typescript
@@ -18099,7 +18358,7 @@ paths:
items:
$ref: >-
#/components/schemas/UnifiedAccountingCompanyinfoOutput
- tags: &ref_66
+ tags: &ref_67
- accounting/companyinfos
x-speakeasy-group: accounting.companyinfos
x-speakeasy-pagination:
@@ -18192,7 +18451,7 @@ paths:
application/json:
schema:
$ref: '#/components/schemas/UnifiedAccountingCompanyinfoOutput'
- tags: *ref_66
+ tags: *ref_67
x-speakeasy-group: accounting.companyinfos
x-codeSamples:
- lang: typescript
@@ -18309,7 +18568,7 @@ paths:
type: array
items:
$ref: '#/components/schemas/UnifiedAccountingContactOutput'
- tags: &ref_67
+ tags: &ref_68
- accounting/contacts
x-speakeasy-group: accounting.contacts
x-speakeasy-pagination:
@@ -18400,13 +18659,14 @@ paths:
application/json:
schema:
$ref: '#/components/schemas/UnifiedAccountingContactOutput'
- tags: *ref_67
+ tags: *ref_68
x-speakeasy-group: accounting.contacts
x-codeSamples:
- lang: typescript
label: createAccountingContact
source: |-
import { Panora } from "@panora/sdk";
+ import { UnifiedAccountingContactInputCurrency } from "@panora/sdk/models/components";
const panora = new Panora({
apiKey: "",
@@ -18416,7 +18676,18 @@ paths:
const result = await panora.accounting.contacts.create({
xConnectionToken: "",
remoteData: false,
- unifiedAccountingContactInput: {},
+ unifiedAccountingContactInput: {
+ name: "John Doe",
+ isSupplier: true,
+ isCustomer: false,
+ emailAddress: "john.doe@example.com",
+ taxNumber: "123456789",
+ status: "Active",
+ currency: UnifiedAccountingContactInputCurrency.Usd,
+ remoteUpdatedAt: "2024-06-15T12:00:00Z",
+ companyInfoId: "801f9ede-c698-4e66-a7fc-48d19eebaa4f",
+ fieldMappings: {},
+ },
});
// Handle the result
@@ -18505,7 +18776,7 @@ paths:
application/json:
schema:
$ref: '#/components/schemas/UnifiedAccountingContactOutput'
- tags: *ref_67
+ tags: *ref_68
x-speakeasy-group: accounting.contacts
x-codeSamples:
- lang: typescript
@@ -18623,7 +18894,7 @@ paths:
items:
$ref: >-
#/components/schemas/UnifiedAccountingCreditnoteOutput
- tags: &ref_68
+ tags: &ref_69
- accounting/creditnotes
x-speakeasy-group: accounting.creditnotes
x-speakeasy-pagination:
@@ -18716,7 +18987,7 @@ paths:
application/json:
schema:
$ref: '#/components/schemas/UnifiedAccountingCreditnoteOutput'
- tags: *ref_68
+ tags: *ref_69
x-speakeasy-group: accounting.creditnotes
x-codeSamples:
- lang: typescript
@@ -18833,7 +19104,7 @@ paths:
type: array
items:
$ref: '#/components/schemas/UnifiedAccountingExpenseOutput'
- tags: &ref_69
+ tags: &ref_70
- accounting/expenses
x-speakeasy-group: accounting.expenses
x-speakeasy-pagination:
@@ -18924,13 +19195,14 @@ paths:
application/json:
schema:
$ref: '#/components/schemas/UnifiedAccountingExpenseOutput'
- tags: *ref_69
+ tags: *ref_70
x-speakeasy-group: accounting.expenses
x-codeSamples:
- lang: typescript
label: createAccountingExpense
source: |-
import { Panora } from "@panora/sdk";
+ import { UnifiedAccountingExpenseInputCurrency } from "@panora/sdk/models/components";
const panora = new Panora({
apiKey: "",
@@ -18940,7 +19212,35 @@ paths:
const result = await panora.accounting.expenses.create({
xConnectionToken: "",
remoteData: false,
- unifiedAccountingExpenseInput: {},
+ unifiedAccountingExpenseInput: {
+ transactionDate: new Date("2024-06-15T12:00:00Z"),
+ totalAmount: 10000,
+ subTotal: 9000,
+ totalTaxAmount: 1000,
+ currency: UnifiedAccountingExpenseInputCurrency.Usd,
+ exchangeRate: "1.2",
+ memo: "Business lunch with client",
+ accountId: "801f9ede-c698-4e66-a7fc-48d19eebaa4f",
+ contactId: "801f9ede-c698-4e66-a7fc-48d19eebaa4f",
+ companyInfoId: "801f9ede-c698-4e66-a7fc-48d19eebaa4f",
+ trackingCategories: [
+ "801f9ede-c698-4e66-a7fc-48d19eebaa4f",
+ ],
+ lineItems: [
+ {
+ name: "Net Income",
+ value: 100000,
+ type: "Operating Activities",
+ parentItem: "801f9ede-c698-4e66-a7fc-48d19eebaa4f",
+ remoteId: "report_item_1234",
+ remoteGeneratedAt: new Date("2024-07-01T12:00:00Z"),
+ companyInfoId: "801f9ede-c698-4e66-a7fc-48d19eebaa4f",
+ createdAt: new Date("2024-06-15T12:00:00Z"),
+ modifiedAt: new Date("2024-06-15T12:00:00Z"),
+ },
+ ],
+ fieldMappings: {},
+ },
});
// Handle the result
@@ -19029,7 +19329,7 @@ paths:
application/json:
schema:
$ref: '#/components/schemas/UnifiedAccountingExpenseOutput'
- tags: *ref_69
+ tags: *ref_70
x-speakeasy-group: accounting.expenses
x-codeSamples:
- lang: typescript
@@ -19147,7 +19447,7 @@ paths:
items:
$ref: >-
#/components/schemas/UnifiedAccountingIncomestatementOutput
- tags: &ref_70
+ tags: &ref_71
- accounting/incomestatements
x-speakeasy-group: accounting.incomestatements
x-speakeasy-pagination:
@@ -19240,7 +19540,7 @@ paths:
application/json:
schema:
$ref: '#/components/schemas/UnifiedAccountingIncomestatementOutput'
- tags: *ref_70
+ tags: *ref_71
x-speakeasy-group: accounting.incomestatements
x-codeSamples:
- lang: typescript
@@ -19357,7 +19657,7 @@ paths:
type: array
items:
$ref: '#/components/schemas/UnifiedAccountingInvoiceOutput'
- tags: &ref_71
+ tags: &ref_72
- accounting/invoices
x-speakeasy-group: accounting.invoices
x-speakeasy-pagination:
@@ -19448,13 +19748,14 @@ paths:
application/json:
schema:
$ref: '#/components/schemas/UnifiedAccountingInvoiceOutput'
- tags: *ref_71
+ tags: *ref_72
x-speakeasy-group: accounting.invoices
x-codeSamples:
- lang: typescript
label: createAccountingInvoice
source: |-
import { Panora } from "@panora/sdk";
+ import { UnifiedAccountingInvoiceInputCurrency } from "@panora/sdk/models/components";
const panora = new Panora({
apiKey: "",
@@ -19464,7 +19765,42 @@ paths:
const result = await panora.accounting.invoices.create({
xConnectionToken: "",
remoteData: false,
- unifiedAccountingInvoiceInput: {},
+ unifiedAccountingInvoiceInput: {
+ type: "Sales",
+ number: "INV-001",
+ issueDate: new Date("2024-06-15T12:00:00Z"),
+ dueDate: new Date("2024-07-15T12:00:00Z"),
+ paidOnDate: new Date("2024-07-10T12:00:00Z"),
+ memo: "Payment for services rendered",
+ currency: UnifiedAccountingInvoiceInputCurrency.Usd,
+ exchangeRate: "1.2",
+ totalDiscount: 1000,
+ subTotal: 10000,
+ status: "Paid",
+ totalTaxAmount: 1000,
+ totalAmount: 11000,
+ balance: 0,
+ contactId: "801f9ede-c698-4e66-a7fc-48d19eebaa4f",
+ accountingPeriodId: "801f9ede-c698-4e66-a7fc-48d19eebaa4f",
+ trackingCategories: [
+ "801f9ede-c698-4e66-a7fc-48d19eebaa4f",
+ "801f9ede-c698-4e66-a7fc-48d19eebaa4f",
+ ],
+ lineItems: [
+ {
+ name: "Net Income",
+ value: 100000,
+ type: "Operating Activities",
+ parentItem: "801f9ede-c698-4e66-a7fc-48d19eebaa4f",
+ remoteId: "report_item_1234",
+ remoteGeneratedAt: new Date("2024-07-01T12:00:00Z"),
+ companyInfoId: "801f9ede-c698-4e66-a7fc-48d19eebaa4f",
+ createdAt: new Date("2024-06-15T12:00:00Z"),
+ modifiedAt: new Date("2024-06-15T12:00:00Z"),
+ },
+ ],
+ fieldMappings: {},
+ },
});
// Handle the result
@@ -19553,7 +19889,7 @@ paths:
application/json:
schema:
$ref: '#/components/schemas/UnifiedAccountingInvoiceOutput'
- tags: *ref_71
+ tags: *ref_72
x-speakeasy-group: accounting.invoices
x-codeSamples:
- lang: typescript
@@ -19670,7 +20006,7 @@ paths:
type: array
items:
$ref: '#/components/schemas/UnifiedAccountingItemOutput'
- tags: &ref_72
+ tags: &ref_73
- accounting/items
x-speakeasy-group: accounting.items
x-speakeasy-pagination:
@@ -19763,7 +20099,7 @@ paths:
application/json:
schema:
$ref: '#/components/schemas/UnifiedAccountingItemOutput'
- tags: *ref_72
+ tags: *ref_73
x-speakeasy-group: accounting.items
x-codeSamples:
- lang: typescript
@@ -19881,7 +20217,7 @@ paths:
items:
$ref: >-
#/components/schemas/UnifiedAccountingJournalentryOutput
- tags: &ref_73
+ tags: &ref_74
- accounting/journalentries
x-speakeasy-group: accounting.journalentries
x-speakeasy-pagination:
@@ -19972,13 +20308,14 @@ paths:
application/json:
schema:
$ref: '#/components/schemas/UnifiedAccountingJournalentryOutput'
- tags: *ref_73
+ tags: *ref_74
x-speakeasy-group: accounting.journalentries
x-codeSamples:
- lang: typescript
label: createAccountingJournalEntry
source: |-
import { Panora } from "@panora/sdk";
+ import { UnifiedAccountingJournalentryInputCurrency } from "@panora/sdk/models/components";
const panora = new Panora({
apiKey: "",
@@ -19988,7 +20325,41 @@ paths:
const result = await panora.accounting.journalentries.create({
xConnectionToken: "",
remoteData: false,
- unifiedAccountingJournalentryInput: {},
+ unifiedAccountingJournalentryInput: {
+ transactionDate: new Date("2024-06-15T12:00:00Z"),
+ payments: [
+ "payment1",
+ "payment2",
+ ],
+ appliedPayments: [
+ "appliedPayment1",
+ "appliedPayment2",
+ ],
+ memo: "Monthly expense journal entry",
+ currency: UnifiedAccountingJournalentryInputCurrency.Usd,
+ exchangeRate: "1.2",
+ idAccCompanyInfo: "801f9ede-c698-4e66-a7fc-48d19eebaa4f",
+ journalNumber: "JE-001",
+ trackingCategories: [
+ "801f9ede-c698-4e66-a7fc-48d19eebaa4f",
+ ],
+ idAccAccountingPeriod: "801f9ede-c698-4e66-a7fc-48d19eebaa4f",
+ postingStatus: "Posted",
+ lineItems: [
+ {
+ name: "Net Income",
+ value: 100000,
+ type: "Operating Activities",
+ parentItem: "801f9ede-c698-4e66-a7fc-48d19eebaa4f",
+ remoteId: "report_item_1234",
+ remoteGeneratedAt: new Date("2024-07-01T12:00:00Z"),
+ companyInfoId: "801f9ede-c698-4e66-a7fc-48d19eebaa4f",
+ createdAt: new Date("2024-06-15T12:00:00Z"),
+ modifiedAt: new Date("2024-06-15T12:00:00Z"),
+ },
+ ],
+ fieldMappings: {},
+ },
});
// Handle the result
@@ -20077,7 +20448,7 @@ paths:
application/json:
schema:
$ref: '#/components/schemas/UnifiedAccountingJournalentryOutput'
- tags: *ref_73
+ tags: *ref_74
x-speakeasy-group: accounting.journalentries
x-codeSamples:
- lang: typescript
@@ -20194,7 +20565,7 @@ paths:
type: array
items:
$ref: '#/components/schemas/UnifiedAccountingPaymentOutput'
- tags: &ref_74
+ tags: &ref_75
- accounting/payments
x-speakeasy-group: accounting.payments
x-speakeasy-pagination:
@@ -20285,13 +20656,14 @@ paths:
application/json:
schema:
$ref: '#/components/schemas/UnifiedAccountingPaymentOutput'
- tags: *ref_74
+ tags: *ref_75
x-speakeasy-group: accounting.payments
x-codeSamples:
- lang: typescript
label: createAccountingPayment
source: |-
import { Panora } from "@panora/sdk";
+ import { UnifiedAccountingPaymentInputCurrency } from "@panora/sdk/models/components";
const panora = new Panora({
apiKey: "",
@@ -20301,7 +20673,35 @@ paths:
const result = await panora.accounting.payments.create({
xConnectionToken: "",
remoteData: false,
- unifiedAccountingPaymentInput: {},
+ unifiedAccountingPaymentInput: {
+ invoiceId: "801f9ede-c698-4e66-a7fc-48d19eebaa4f",
+ transactionDate: new Date("2024-06-15T12:00:00Z"),
+ contactId: "801f9ede-c698-4e66-a7fc-48d19eebaa4f",
+ accountId: "801f9ede-c698-4e66-a7fc-48d19eebaa4f",
+ currency: UnifiedAccountingPaymentInputCurrency.Usd,
+ exchangeRate: "1.2",
+ totalAmount: 10000,
+ type: "Credit Card",
+ companyInfoId: "801f9ede-c698-4e66-a7fc-48d19eebaa4f",
+ accountingPeriodId: "801f9ede-c698-4e66-a7fc-48d19eebaa4f",
+ trackingCategories: [
+ "801f9ede-c698-4e66-a7fc-48d19eebaa4f",
+ ],
+ lineItems: [
+ {
+ name: "Net Income",
+ value: 100000,
+ type: "Operating Activities",
+ parentItem: "801f9ede-c698-4e66-a7fc-48d19eebaa4f",
+ remoteId: "report_item_1234",
+ remoteGeneratedAt: new Date("2024-07-01T12:00:00Z"),
+ companyInfoId: "801f9ede-c698-4e66-a7fc-48d19eebaa4f",
+ createdAt: new Date("2024-06-15T12:00:00Z"),
+ modifiedAt: new Date("2024-06-15T12:00:00Z"),
+ },
+ ],
+ fieldMappings: {},
+ },
});
// Handle the result
@@ -20390,7 +20790,7 @@ paths:
application/json:
schema:
$ref: '#/components/schemas/UnifiedAccountingPaymentOutput'
- tags: *ref_74
+ tags: *ref_75
x-speakeasy-group: accounting.payments
x-codeSamples:
- lang: typescript
@@ -20508,7 +20908,7 @@ paths:
items:
$ref: >-
#/components/schemas/UnifiedAccountingPhonenumberOutput
- tags: &ref_75
+ tags: &ref_76
- accounting/phonenumbers
x-speakeasy-group: accounting.phonenumbers
x-speakeasy-pagination:
@@ -20601,7 +21001,7 @@ paths:
application/json:
schema:
$ref: '#/components/schemas/UnifiedAccountingPhonenumberOutput'
- tags: *ref_75
+ tags: *ref_76
x-speakeasy-group: accounting.phonenumbers
x-codeSamples:
- lang: typescript
@@ -20719,7 +21119,7 @@ paths:
items:
$ref: >-
#/components/schemas/UnifiedAccountingPurchaseorderOutput
- tags: &ref_76
+ tags: &ref_77
- accounting/purchaseorders
x-speakeasy-group: accounting.purchaseorders
x-speakeasy-pagination:
@@ -20810,13 +21210,14 @@ paths:
application/json:
schema:
$ref: '#/components/schemas/UnifiedAccountingPurchaseorderOutput'
- tags: *ref_76
+ tags: *ref_77
x-speakeasy-group: accounting.purchaseorders
x-codeSamples:
- lang: typescript
label: createAccountingPurchaseOrder
source: |-
import { Panora } from "@panora/sdk";
+ import { UnifiedAccountingPurchaseorderInputCurrency } from "@panora/sdk/models/components";
const panora = new Panora({
apiKey: "",
@@ -20826,7 +21227,38 @@ paths:
const result = await panora.accounting.purchaseorders.create({
xConnectionToken: "",
remoteData: false,
- unifiedAccountingPurchaseorderInput: {},
+ unifiedAccountingPurchaseorderInput: {
+ status: "Pending",
+ issueDate: new Date("2024-06-15T12:00:00Z"),
+ purchaseOrderNumber: "PO-001",
+ deliveryDate: new Date("2024-07-15T12:00:00Z"),
+ deliveryAddress: "801f9ede-c698-4e66-a7fc-48d19eebaa4f",
+ customer: "801f9ede-c698-4e66-a7fc-48d19eebaa4f",
+ vendor: "801f9ede-c698-4e66-a7fc-48d19eebaa4f",
+ memo: "Purchase order for Q3 inventory",
+ companyId: "801f9ede-c698-4e66-a7fc-48d19eebaa4f",
+ totalAmount: 100000,
+ currency: UnifiedAccountingPurchaseorderInputCurrency.Usd,
+ exchangeRate: "1.2",
+ trackingCategories: [
+ "801f9ede-c698-4e66-a7fc-48d19eebaa4f",
+ ],
+ accountingPeriodId: "801f9ede-c698-4e66-a7fc-48d19eebaa4f",
+ lineItems: [
+ {
+ name: "Net Income",
+ value: 100000,
+ type: "Operating Activities",
+ parentItem: "801f9ede-c698-4e66-a7fc-48d19eebaa4f",
+ remoteId: "report_item_1234",
+ remoteGeneratedAt: new Date("2024-07-01T12:00:00Z"),
+ companyInfoId: "801f9ede-c698-4e66-a7fc-48d19eebaa4f",
+ createdAt: new Date("2024-06-15T12:00:00Z"),
+ modifiedAt: new Date("2024-06-15T12:00:00Z"),
+ },
+ ],
+ fieldMappings: {},
+ },
});
// Handle the result
@@ -20915,7 +21347,7 @@ paths:
application/json:
schema:
$ref: '#/components/schemas/UnifiedAccountingPurchaseorderOutput'
- tags: *ref_76
+ tags: *ref_77
x-speakeasy-group: accounting.purchaseorders
x-codeSamples:
- lang: typescript
@@ -21032,7 +21464,7 @@ paths:
type: array
items:
$ref: '#/components/schemas/UnifiedAccountingTaxrateOutput'
- tags: &ref_77
+ tags: &ref_78
- accounting/taxrates
x-speakeasy-group: accounting.taxrates
x-speakeasy-pagination:
@@ -21125,7 +21557,7 @@ paths:
application/json:
schema:
$ref: '#/components/schemas/UnifiedAccountingTaxrateOutput'
- tags: *ref_77
+ tags: *ref_78
x-speakeasy-group: accounting.taxrates
x-codeSamples:
- lang: typescript
@@ -21243,7 +21675,7 @@ paths:
items:
$ref: >-
#/components/schemas/UnifiedAccountingTrackingcategoryOutput
- tags: &ref_78
+ tags: &ref_79
- accounting/trackingcategories
x-speakeasy-group: accounting.trackingcategories
x-speakeasy-pagination:
@@ -21336,7 +21768,7 @@ paths:
application/json:
schema:
$ref: '#/components/schemas/UnifiedAccountingTrackingcategoryOutput'
- tags: *ref_78
+ tags: *ref_79
x-speakeasy-group: accounting.trackingcategories
x-codeSamples:
- lang: typescript
@@ -21454,7 +21886,7 @@ paths:
items:
$ref: >-
#/components/schemas/UnifiedAccountingTransactionOutput
- tags: &ref_79
+ tags: &ref_80
- accounting/transactions
x-speakeasy-group: accounting.transactions
x-speakeasy-pagination:
@@ -21547,7 +21979,7 @@ paths:
application/json:
schema:
$ref: '#/components/schemas/UnifiedAccountingTransactionOutput'
- tags: *ref_79
+ tags: *ref_80
x-speakeasy-group: accounting.transactions
x-codeSamples:
- lang: typescript
@@ -21665,7 +22097,7 @@ paths:
items:
$ref: >-
#/components/schemas/UnifiedAccountingVendorcreditOutput
- tags: &ref_80
+ tags: &ref_81
- accounting/vendorcredits
x-speakeasy-group: accounting.vendorcredits
x-speakeasy-pagination:
@@ -21758,7 +22190,7 @@ paths:
application/json:
schema:
$ref: '#/components/schemas/UnifiedAccountingVendorcreditOutput'
- tags: *ref_80
+ tags: *ref_81
x-speakeasy-group: accounting.vendorcredits
x-codeSamples:
- lang: typescript
@@ -21875,7 +22307,7 @@ paths:
type: array
items:
$ref: '#/components/schemas/UnifiedFilestorageDriveOutput'
- tags: &ref_81
+ tags: &ref_82
- filestorage/drives
x-speakeasy-group: filestorage.drives
x-speakeasy-pagination:
@@ -21968,7 +22400,7 @@ paths:
application/json:
schema:
$ref: '#/components/schemas/UnifiedFilestorageDriveOutput'
- tags: *ref_81
+ tags: *ref_82
x-speakeasy-group: filestorage.drives
x-codeSamples:
- lang: typescript
@@ -22085,7 +22517,7 @@ paths:
type: array
items:
$ref: '#/components/schemas/UnifiedFilestorageFileOutput'
- tags: &ref_82
+ tags: &ref_83
- filestorage/files
x-speakeasy-group: filestorage.files
x-speakeasy-pagination:
@@ -22176,7 +22608,7 @@ paths:
application/json:
schema:
$ref: '#/components/schemas/UnifiedFilestorageFileOutput'
- tags: *ref_82
+ tags: *ref_83
x-speakeasy-group: filestorage.files
x-codeSamples:
- lang: typescript
@@ -22317,7 +22749,7 @@ paths:
application/json:
schema:
$ref: '#/components/schemas/UnifiedFilestorageFileOutput'
- tags: *ref_82
+ tags: *ref_83
x-speakeasy-group: filestorage.files
x-codeSamples:
- lang: typescript
@@ -22434,7 +22866,7 @@ paths:
type: array
items:
$ref: '#/components/schemas/UnifiedFilestorageFolderOutput'
- tags: &ref_83
+ tags: &ref_84
- filestorage/folders
x-speakeasy-group: filestorage.folders
x-speakeasy-pagination:
@@ -22525,7 +22957,7 @@ paths:
application/json:
schema:
$ref: '#/components/schemas/UnifiedFilestorageFolderOutput'
- tags: *ref_83
+ tags: *ref_84
x-speakeasy-group: filestorage.folders
x-codeSamples:
- lang: typescript
@@ -22669,7 +23101,7 @@ paths:
application/json:
schema:
$ref: '#/components/schemas/UnifiedFilestorageFolderOutput'
- tags: *ref_83
+ tags: *ref_84
x-speakeasy-group: filestorage.folders
x-codeSamples:
- lang: typescript
@@ -22786,7 +23218,7 @@ paths:
type: array
items:
$ref: '#/components/schemas/UnifiedFilestorageGroupOutput'
- tags: &ref_84
+ tags: &ref_85
- filestorage/groups
x-speakeasy-group: filestorage.groups
x-speakeasy-pagination:
@@ -22879,7 +23311,7 @@ paths:
application/json:
schema:
$ref: '#/components/schemas/UnifiedFilestorageGroupOutput'
- tags: *ref_84
+ tags: *ref_85
x-speakeasy-group: filestorage.groups
x-codeSamples:
- lang: typescript
@@ -22996,7 +23428,7 @@ paths:
type: array
items:
$ref: '#/components/schemas/UnifiedFilestorageUserOutput'
- tags: &ref_85
+ tags: &ref_86
- filestorage/users
x-speakeasy-group: filestorage.users
x-speakeasy-pagination:
@@ -23089,7 +23521,7 @@ paths:
application/json:
schema:
$ref: '#/components/schemas/UnifiedFilestorageUserOutput'
- tags: *ref_85
+ tags: *ref_86
x-speakeasy-group: filestorage.users
x-codeSamples:
- lang: typescript
@@ -23206,7 +23638,7 @@ paths:
type: array
items:
$ref: '#/components/schemas/UnifiedEcommerceProductOutput'
- tags: &ref_86
+ tags: &ref_87
- ecommerce/products
x-speakeasy-group: ecommerce.products
x-speakeasy-pagination:
@@ -23297,7 +23729,7 @@ paths:
application/json:
schema:
$ref: '#/components/schemas/UnifiedEcommerceProductOutput'
- tags: *ref_86
+ tags: *ref_87
x-speakeasy-group: ecommerce.products
x-codeSamples:
- lang: typescript
@@ -23417,7 +23849,7 @@ paths:
application/json:
schema:
$ref: '#/components/schemas/UnifiedEcommerceProductOutput'
- tags: *ref_86
+ tags: *ref_87
x-speakeasy-group: ecommerce.products
x-codeSamples:
- lang: typescript
@@ -23531,7 +23963,7 @@ paths:
type: array
items:
$ref: '#/components/schemas/UnifiedEcommerceOrderOutput'
- tags: &ref_87
+ tags: &ref_88
- ecommerce/orders
x-speakeasy-group: ecommerce.orders
x-speakeasy-pagination:
@@ -23622,7 +24054,7 @@ paths:
application/json:
schema:
$ref: '#/components/schemas/UnifiedEcommerceOrderOutput'
- tags: *ref_87
+ tags: *ref_88
x-speakeasy-group: ecommerce.orders
x-codeSamples:
- lang: typescript
@@ -23656,7 +24088,17 @@ paths:
fulfillmentStatus: UnifiedEcommerceOrderInputFulfillmentStatus.Pending,
customerId: "801f9ede-c698-4e66-a7fc-48d19eebaa4f",
items: [
- {},
+ {
+ name: "Net Income",
+ value: 100000,
+ type: "Operating Activities",
+ parentItem: "801f9ede-c698-4e66-a7fc-48d19eebaa4f",
+ remoteId: "12345",
+ remoteGeneratedAt: new Date("2024-07-01T12:00:00Z"),
+ companyInfoId: "801f9ede-c698-4e66-a7fc-48d19eebaa4f",
+ createdAt: new Date("2024-06-15T12:00:00Z"),
+ modifiedAt: new Date("2024-06-15T12:00:00Z"),
+ },
],
fieldMappings: {},
},
@@ -23746,7 +24188,7 @@ paths:
application/json:
schema:
$ref: '#/components/schemas/UnifiedEcommerceOrderOutput'
- tags: *ref_87
+ tags: *ref_88
x-speakeasy-group: ecommerce.orders
x-codeSamples:
- lang: typescript
@@ -23860,7 +24302,7 @@ paths:
type: array
items:
$ref: '#/components/schemas/UnifiedEcommerceCustomerOutput'
- tags: &ref_88
+ tags: &ref_89
- ecommerce/customers
x-speakeasy-group: ecommerce.customers
x-speakeasy-pagination:
@@ -23951,7 +24393,7 @@ paths:
application/json:
schema:
$ref: '#/components/schemas/UnifiedEcommerceCustomerOutput'
- tags: *ref_88
+ tags: *ref_89
x-speakeasy-group: ecommerce.customers
x-codeSamples:
- lang: typescript
@@ -24066,7 +24508,7 @@ paths:
items:
$ref: >-
#/components/schemas/UnifiedEcommerceFulfillmentOutput
- tags: &ref_89
+ tags: &ref_90
- ecommerce/fulfillments
x-speakeasy-group: ecommerce.fulfillments
x-speakeasy-pagination:
@@ -24157,7 +24599,7 @@ paths:
application/json:
schema:
$ref: '#/components/schemas/UnifiedEcommerceFulfillmentOutput'
- tags: *ref_89
+ tags: *ref_90
x-speakeasy-group: ecommerce.fulfillments
x-codeSamples:
- lang: typescript
@@ -24272,7 +24714,7 @@ paths:
items:
$ref: >-
#/components/schemas/UnifiedTicketingAttachmentOutput
- tags: &ref_90
+ tags: &ref_91
- ticketing/attachments
x-speakeasy-group: ticketing.attachments
x-speakeasy-pagination:
@@ -24362,7 +24804,7 @@ paths:
application/json:
schema:
$ref: '#/components/schemas/UnifiedTicketingAttachmentOutput'
- tags: *ref_90
+ tags: *ref_91
x-speakeasy-group: ticketing.attachments
x-codeSamples:
- lang: typescript
@@ -24494,7 +24936,7 @@ paths:
application/json:
schema:
$ref: '#/components/schemas/UnifiedTicketingAttachmentOutput'
- tags: *ref_90
+ tags: *ref_91
x-speakeasy-group: ticketing.attachments
x-codeSamples:
- lang: typescript
@@ -24817,7 +25259,7 @@ components:
type: string
nullable: true
example: USER
- enum: &ref_120
+ enum: &ref_121
- USER
- CONTACT
description: >-
@@ -24841,12 +25283,12 @@ components:
The UUID of the user which the comment belongs to (if no contact_id specified)
attachments:
type: array
- items: &ref_121
+ items: &ref_122
oneOf:
- type: string
- $ref: '#/components/schemas/UnifiedTicketingAttachmentOutput'
nullable: true
- example: &ref_122
+ example: &ref_123
- 801f9ede-c698-4e66-a7fc-48d19eebaa4f
description: The attachements UUIDs tied to the comment
required:
@@ -24862,7 +25304,7 @@ components:
status:
type: string
example: OPEN
- enum: &ref_91
+ enum: &ref_92
- OPEN
- CLOSED
nullable: true
@@ -24881,7 +25323,7 @@ components:
type:
type: string
example: BUG
- enum: &ref_92
+ enum: &ref_93
- BUG
- SUBTASK
- TASK
@@ -24896,21 +25338,21 @@ components:
description: The UUID of the parent ticket
collections:
type: array
- items: &ref_93
+ items: &ref_94
oneOf:
- type: string
- $ref: '#/components/schemas/UnifiedTicketingCollectionOutput'
- example: &ref_94
+ example: &ref_95
- 801f9ede-c698-4e66-a7fc-48d19eebaa4f
nullable: true
description: The collection UUIDs the ticket belongs to
tags:
type: array
- items: &ref_95
+ items: &ref_96
oneOf:
- type: string
- $ref: '#/components/schemas/UnifiedTicketingTagOutput'
- example: &ref_96
+ example: &ref_97
- my_tag
- urgent_tag
nullable: true
@@ -24924,7 +25366,7 @@ components:
priority:
type: string
example: HIGH
- enum: &ref_97
+ enum: &ref_98
- HIGH
- MEDIUM
- LOW
@@ -24932,7 +25374,7 @@ components:
description: >-
The priority of the ticket. Authorized values are HIGH, MEDIUM or LOW.
assigned_to:
- example: &ref_98
+ example: &ref_99
- 801f9ede-c698-4e66-a7fc-48d19eebaa4f
nullable: true
description: The users UUIDs the ticket is assigned to
@@ -24940,7 +25382,7 @@ components:
items:
type: string
comment:
- example: &ref_99
+ example: &ref_100
content: Assigned the issue !
nullable: true
description: The comment of the ticket
@@ -24958,17 +25400,17 @@ components:
description: The UUID of the contact which the ticket belongs to
attachments:
type: array
- items: &ref_100
+ items: &ref_101
oneOf:
- type: string
- $ref: '#/components/schemas/UnifiedTicketingAttachmentInput'
- example: &ref_101
+ example: &ref_102
- 801f9ede-c698-4e66-a7fc-48d19eebaa4f
description: The attachements UUIDs tied to the ticket
nullable: true
field_mappings:
type: object
- example: &ref_102
+ example: &ref_103
fav_dish: broccoli
fav_color: red
nullable: true
@@ -25020,7 +25462,7 @@ components:
status:
type: string
example: OPEN
- enum: *ref_91
+ enum: *ref_92
nullable: true
description: The status of the ticket. Authorized values are OPEN or CLOSED.
description:
@@ -25037,7 +25479,7 @@ components:
type:
type: string
example: BUG
- enum: *ref_92
+ enum: *ref_93
nullable: true
description: >-
The type of the ticket. Authorized values are PROBLEM, QUESTION, or TASK
@@ -25048,14 +25490,14 @@ components:
description: The UUID of the parent ticket
collections:
type: array
- items: *ref_93
- example: *ref_94
+ items: *ref_94
+ example: *ref_95
nullable: true
description: The collection UUIDs the ticket belongs to
tags:
type: array
- items: *ref_95
- example: *ref_96
+ items: *ref_96
+ example: *ref_97
nullable: true
description: The tags names of the ticket
completed_at:
@@ -25067,19 +25509,19 @@ components:
priority:
type: string
example: HIGH
- enum: *ref_97
+ enum: *ref_98
nullable: true
description: >-
The priority of the ticket. Authorized values are HIGH, MEDIUM or LOW.
assigned_to:
- example: *ref_98
+ example: *ref_99
nullable: true
description: The users UUIDs the ticket is assigned to
type: array
items:
type: string
comment:
- example: *ref_99
+ example: *ref_100
nullable: true
description: The comment of the ticket
allOf:
@@ -25096,13 +25538,13 @@ components:
description: The UUID of the contact which the ticket belongs to
attachments:
type: array
- items: *ref_100
- example: *ref_101
+ items: *ref_101
+ example: *ref_102
description: The attachements UUIDs tied to the ticket
nullable: true
field_mappings:
type: object
- example: *ref_102
+ example: *ref_103
nullable: true
description: >-
The custom field mappings of the ticket between the remote 3rd party & Panora
@@ -25451,7 +25893,7 @@ components:
industry:
type: string
example: ACCOUNTING
- enum: &ref_103
+ enum: &ref_104
- ACCOUNTING
- AIRLINES_AVIATION
- ALTERNATIVE_DISPUTE_RESOLUTION
@@ -25614,7 +26056,7 @@ components:
nullable: true
email_addresses:
description: The email addresses of the company
- example: &ref_104
+ example: &ref_105
- email_address: acme@gmail.com
email_address_type: WORK
nullable: true
@@ -25623,7 +26065,7 @@ components:
$ref: '#/components/schemas/Email'
addresses:
description: The addresses of the company
- example: &ref_105
+ example: &ref_106
- street_1: 5th Avenue
city: New York
state: NY
@@ -25635,7 +26077,7 @@ components:
$ref: '#/components/schemas/Address'
phone_numbers:
description: The phone numbers of the company
- example: &ref_106
+ example: &ref_107
- phone_number: '+33660606067'
phone_type: WORK
nullable: true
@@ -25644,7 +26086,7 @@ components:
$ref: '#/components/schemas/Phone'
field_mappings:
type: object
- example: &ref_107
+ example: &ref_108
fav_dish: broccoli
fav_color: red
description: >-
@@ -25692,7 +26134,7 @@ components:
industry:
type: string
example: ACCOUNTING
- enum: *ref_103
+ enum: *ref_104
description: >-
The industry of the company. Authorized values can be found in the Industry enum.
nullable: true
@@ -25708,28 +26150,28 @@ components:
nullable: true
email_addresses:
description: The email addresses of the company
- example: *ref_104
+ example: *ref_105
nullable: true
type: array
items:
$ref: '#/components/schemas/Email'
addresses:
description: The addresses of the company
- example: *ref_105
+ example: *ref_106
nullable: true
type: array
items:
$ref: '#/components/schemas/Address'
phone_numbers:
description: The phone numbers of the company
- example: *ref_106
+ example: *ref_107
nullable: true
type: array
items:
$ref: '#/components/schemas/Phone'
field_mappings:
type: object
- example: *ref_107
+ example: *ref_108
description: >-
The custom field mappings of the company between the remote 3rd party & Panora
nullable: true
@@ -25752,7 +26194,7 @@ components:
email_addresses:
nullable: true
description: The email addresses of the contact
- example: &ref_108
+ example: &ref_109
- email: john.doe@example.com
type: WORK
type: array
@@ -25761,7 +26203,7 @@ components:
phone_numbers:
nullable: true
description: The phone numbers of the contact
- example: &ref_109
+ example: &ref_110
- phone: '1234567890'
type: WORK
type: array
@@ -25770,7 +26212,7 @@ components:
addresses:
nullable: true
description: The addresses of the contact
- example: &ref_110
+ example: &ref_111
- street: 123 Main St
city: Anytown
state: CA
@@ -25787,7 +26229,7 @@ components:
example: 801f9ede-c698-4e66-a7fc-48d19eebaa4f
field_mappings:
type: object
- example: &ref_111
+ example: &ref_112
fav_dish: broccoli
fav_color: red
nullable: true
@@ -25843,21 +26285,21 @@ components:
email_addresses:
nullable: true
description: The email addresses of the contact
- example: *ref_108
+ example: *ref_109
type: array
items:
$ref: '#/components/schemas/Email'
phone_numbers:
nullable: true
description: The phone numbers of the contact
- example: *ref_109
+ example: *ref_110
type: array
items:
$ref: '#/components/schemas/Phone'
addresses:
nullable: true
description: The addresses of the contact
- example: *ref_110
+ example: *ref_111
type: array
items:
$ref: '#/components/schemas/Address'
@@ -25868,7 +26310,7 @@ components:
example: 801f9ede-c698-4e66-a7fc-48d19eebaa4f
field_mappings:
type: object
- example: *ref_111
+ example: *ref_112
nullable: true
description: >-
The custom field mappings of the contact between the remote 3rd party & Panora
@@ -25912,7 +26354,7 @@ components:
field_mappings:
type: object
nullable: true
- example: &ref_112
+ example: &ref_113
fav_dish: broccoli
fav_color: red
description: >-
@@ -25988,7 +26430,7 @@ components:
field_mappings:
type: object
nullable: true
- example: *ref_112
+ example: *ref_113
description: >-
The custom field mappings of the company between the remote 3rd party & Panora
additionalProperties: true
@@ -26008,7 +26450,7 @@ components:
type: string
nullable: true
example: INBOUND
- enum: &ref_113
+ enum: &ref_114
- INBOUND
- OUTBOUND
description: >-
@@ -26034,7 +26476,7 @@ components:
type: string
nullable: true
example: MEETING
- enum: &ref_114
+ enum: &ref_115
- EMAIL
- CALL
- MEETING
@@ -26052,7 +26494,7 @@ components:
description: The UUID of the company tied to the engagement
contacts:
nullable: true
- example: &ref_115
+ example: &ref_116
- 801f9ede-c698-4e66-a7fc-48d19eebaa4f
description: The UUIDs of contacts tied to the engagement object
type: array
@@ -26061,7 +26503,7 @@ components:
field_mappings:
type: object
nullable: true
- example: &ref_116
+ example: &ref_117
fav_dish: broccoli
fav_color: red
description: >-
@@ -26112,7 +26554,7 @@ components:
type: string
nullable: true
example: INBOUND
- enum: *ref_113
+ enum: *ref_114
description: >-
The direction of the engagement. Authorized values are INBOUND or OUTBOUND
subject:
@@ -26136,7 +26578,7 @@ components:
type: string
nullable: true
example: MEETING
- enum: *ref_114
+ enum: *ref_115
description: >-
The type of the engagement. Authorized values are EMAIL, CALL or MEETING
user_id:
@@ -26151,7 +26593,7 @@ components:
description: The UUID of the company tied to the engagement
contacts:
nullable: true
- example: *ref_115
+ example: *ref_116
description: The UUIDs of contacts tied to the engagement object
type: array
items:
@@ -26159,7 +26601,7 @@ components:
field_mappings:
type: object
nullable: true
- example: *ref_116
+ example: *ref_117
description: >-
The custom field mappings of the engagement between the remote 3rd party & Panora
additionalProperties: true
@@ -26195,7 +26637,7 @@ components:
description: The UUID of the deal tied to the note
field_mappings:
type: object
- example: &ref_117
+ example: &ref_118
fav_dish: broccoli
fav_color: red
nullable: true
@@ -26264,7 +26706,7 @@ components:
description: The UUID of the deal tied to the note
field_mappings:
type: object
- example: *ref_117
+ example: *ref_118
nullable: true
description: >-
The custom field mappings of the note between the remote 3rd party & Panora
@@ -26334,7 +26776,7 @@ components:
status:
type: string
example: PENDING
- enum: &ref_118
+ enum: &ref_119
- PENDING
- COMPLETED
description: The status of the task. Authorized values are PENDING, COMPLETED.
@@ -26366,7 +26808,7 @@ components:
nullable: true
field_mappings:
type: object
- example: &ref_119
+ example: &ref_120
fav_dish: broccoli
fav_color: red
description: >-
@@ -26424,7 +26866,7 @@ components:
status:
type: string
example: PENDING
- enum: *ref_118
+ enum: *ref_119
description: The status of the task. Authorized values are PENDING, COMPLETED.
nullable: true
due_date:
@@ -26454,7 +26896,7 @@ components:
nullable: true
field_mappings:
type: object
- example: *ref_119
+ example: *ref_120
description: >-
The custom field mappings of the task between the remote 3rd party & Panora
nullable: true
@@ -26593,7 +27035,7 @@ components:
type: string
nullable: true
example: USER
- enum: *ref_120
+ enum: *ref_121
description: >-
The creator type of the comment. Authorized values are either USER or CONTACT
ticket_id:
@@ -26615,9 +27057,9 @@ components:
The UUID of the user which the comment belongs to (if no contact_id specified)
attachments:
type: array
- items: *ref_121
+ items: *ref_122
nullable: true
- example: *ref_122
+ example: *ref_123
description: The attachements UUIDs tied to the comment
id:
type: string
@@ -27243,149 +27685,41 @@ components:
- method
- path
UnifiedHrisBankinfoOutput:
- type: object
- properties: {}
- UnifiedHrisBenefitOutput:
- type: object
- properties: {}
- UnifiedHrisCompanyOutput:
- type: object
- properties: {}
- UnifiedHrisDependentOutput:
- type: object
- properties: {}
- UnifiedHrisEmployeepayrollrunOutput:
- type: object
- properties: {}
- UnifiedHrisEmployeeOutput:
- type: object
- properties: {}
- UnifiedHrisEmployeeInput:
- type: object
- properties: {}
- UnifiedHrisEmployerbenefitOutput:
- type: object
- properties: {}
- UnifiedHrisEmploymentOutput:
- type: object
- properties: {}
- UnifiedHrisGroupOutput:
- type: object
- properties: {}
- UnifiedHrisLocationOutput:
- type: object
- properties: {}
- UnifiedHrisPaygroupOutput:
- type: object
- properties: {}
- UnifiedHrisPayrollrunOutput:
- type: object
- properties: {}
- UnifiedHrisTimeoffOutput:
- type: object
- properties: {}
- UnifiedHrisTimeoffInput:
- type: object
- properties: {}
- UnifiedHrisTimeoffbalanceOutput:
- type: object
- properties: {}
- UnifiedMarketingautomationActionOutput:
- type: object
- properties: {}
- UnifiedMarketingautomationActionInput:
- type: object
- properties: {}
- UnifiedMarketingautomationAutomationOutput:
- type: object
- properties: {}
- UnifiedMarketingautomationAutomationInput:
- type: object
- properties: {}
- UnifiedMarketingautomationCampaignOutput:
- type: object
- properties: {}
- UnifiedMarketingautomationCampaignInput:
- type: object
- properties: {}
- UnifiedMarketingautomationContactOutput:
- type: object
- properties: {}
- UnifiedMarketingautomationContactInput:
- type: object
- properties: {}
- UnifiedMarketingautomationEmailOutput:
- type: object
- properties: {}
- UnifiedMarketingautomationEventOutput:
- type: object
- properties: {}
- UnifiedMarketingautomationListOutput:
- type: object
- properties: {}
- UnifiedMarketingautomationListInput:
- type: object
- properties: {}
- UnifiedMarketingautomationMessageOutput:
- type: object
- properties: {}
- UnifiedMarketingautomationTemplateOutput:
- type: object
- properties: {}
- UnifiedMarketingautomationTemplateInput:
- type: object
- properties: {}
- UnifiedMarketingautomationUserOutput:
- type: object
- properties: {}
- UnifiedAtsActivityOutput:
type: object
properties:
- activity_type:
+ account_type:
type: string
- enum: &ref_123
- - NOTE
- - EMAIL
- - OTHER
- example: NOTE
+ example: CHECKING
+ enum:
+ - SAVINGS
+ - CHECKING
nullable: true
- description: The type of activity
- subject:
+ description: The type of the bank account
+ bank_name:
type: string
- example: Email subject
+ example: Bank of America
nullable: true
- description: The subject of the activity
- body:
+ description: The name of the bank
+ account_number:
type: string
- example: Dear Diana, I love you
+ example: '1234567890'
nullable: true
- description: The body of the activity
- visibility:
+ description: The account number
+ routing_number:
type: string
- enum: &ref_124
- - ADMIN_ONLY
- - PUBLIC
- - PRIVATE
- example: PUBLIC
+ example: '021000021'
nullable: true
- description: The visibility of the activity
- candidate_id:
+ description: The routing number of the bank
+ employee_id:
type: string
example: 801f9ede-c698-4e66-a7fc-48d19eebaa4f
nullable: true
- description: The UUID of the candidate
- remote_created_at:
- type: string
- format: date-time
- example: '2024-10-01T12:00:00Z'
- nullable: true
- description: The remote creation date of the activity
+ description: The UUID of the associated employee
field_mappings:
type: object
- example: &ref_125
- fav_dish: broccoli
- fav_color: red
- additionalProperties: true
+ example:
+ custom_field_1: value1
+ custom_field_2: value2
nullable: true
description: >-
The custom field mappings of the object between the remote 3rd party & Panora
@@ -27393,281 +27727,287 @@ components:
type: string
example: 801f9ede-c698-4e66-a7fc-48d19eebaa4f
nullable: true
- description: The UUID of the activity
+ description: The UUID of the bank info record
remote_id:
type: string
example: id_1
nullable: true
- description: The remote ID of the activity in the context of the 3rd Party
+ description: The remote ID of the bank info in the context of the 3rd Party
remote_data:
type: object
example:
- fav_dish: broccoli
- fav_color: red
+ raw_data:
+ additional_field: some value
nullable: true
- additionalProperties: true
- description: The remote data of the activity in the context of the 3rd Party
+ description: The remote data of the bank info in the context of the 3rd Party
+ remote_created_at:
+ format: date-time
+ type: string
+ example: '2024-10-01T12:00:00Z'
+ nullable: true
+ description: The date when the bank info was created in the 3rd party system
created_at:
format: date-time
type: string
example: '2024-10-01T12:00:00Z'
nullable: true
- description: The created date of the object
+ description: The created date of the bank info record
modified_at:
format: date-time
type: string
example: '2024-10-01T12:00:00Z'
nullable: true
- description: The modified date of the object
- UnifiedAtsActivityInput:
+ description: The last modified date of the bank info record
+ remote_was_deleted:
+ type: boolean
+ example: false
+ nullable: true
+ description: Indicates if the bank info was deleted in the remote system
+ required:
+ - id
+ - created_at
+ - modified_at
+ - remote_was_deleted
+ UnifiedHrisBenefitOutput:
type: object
properties:
- activity_type:
+ provider_name:
type: string
- enum: *ref_123
- example: NOTE
+ example: Health Insurance Provider
nullable: true
- description: The type of activity
- subject:
+ description: The name of the benefit provider
+ employee_id:
type: string
- example: Email subject
+ example: 801f9ede-c698-4e66-a7fc-48d19eebaa4f
nullable: true
- description: The subject of the activity
- body:
- type: string
- example: Dear Diana, I love you
+ description: The UUID of the associated employee
+ employee_contribution:
+ type: number
+ example: 100
nullable: true
- description: The body of the activity
- visibility:
+ description: The employee contribution amount
+ company_contribution:
+ type: number
+ example: 200
+ nullable: true
+ description: The company contribution amount
+ start_date:
+ format: date-time
type: string
- enum: *ref_124
- example: PUBLIC
+ example: '2024-01-01T00:00:00Z'
nullable: true
- description: The visibility of the activity
- candidate_id:
+ description: The start date of the benefit
+ end_date:
+ format: date-time
type: string
- example: 801f9ede-c698-4e66-a7fc-48d19eebaa4f
+ example: '2024-12-31T23:59:59Z'
nullable: true
- description: The UUID of the candidate
- remote_created_at:
+ description: The end date of the benefit
+ employer_benefit_id:
type: string
- format: date-time
- example: '2024-10-01T12:00:00Z'
+ example: 801f9ede-c698-4e66-a7fc-48d19eebaa4f
nullable: true
- description: The remote creation date of the activity
+ description: The UUID of the associated employer benefit
field_mappings:
type: object
- example: *ref_125
- additionalProperties: true
+ example:
+ custom_field_1: value1
+ custom_field_2: value2
nullable: true
description: >-
The custom field mappings of the object between the remote 3rd party & Panora
- UnifiedAtsApplicationOutput:
- type: object
- properties:
- applied_at:
- format: date-time
+ id:
type: string
+ example: 801f9ede-c698-4e66-a7fc-48d19eebaa4f
nullable: true
- description: The application date
- example: '2024-10-01T12:00:00Z'
- rejected_at:
- format: date-time
+ description: The UUID of the benefit record
+ remote_id:
type: string
+ example: benefit_1234
nullable: true
- description: The rejection date
- example: '2024-10-01T12:00:00Z'
- offers:
+ description: The remote ID of the benefit in the context of the 3rd Party
+ remote_data:
+ type: object
+ example:
+ raw_data:
+ additional_field: some value
nullable: true
- description: The offers UUIDs for the application
- example: &ref_126
- - 801f9ede-c698-4e66-a7fc-48d19eebaa4f
- - 12345678-1234-1234-1234-123456789012
- type: array
- items:
- type: string
- source:
+ description: The remote data of the benefit in the context of the 3rd Party
+ remote_created_at:
+ format: date-time
type: string
+ example: '2024-10-01T12:00:00Z'
nullable: true
- description: The source of the application
- example: Source Name
- credited_to:
+ description: The date when the benefit was created in the 3rd party system
+ created_at:
+ format: date-time
type: string
+ example: '2024-10-01T12:00:00Z'
nullable: true
- description: The UUID of the person credited for the application
- example: 801f9ede-c698-4e66-a7fc-48d19eebaa4f
- current_stage:
+ description: The created date of the benefit record
+ modified_at:
+ format: date-time
type: string
+ example: '2024-10-01T12:00:00Z'
nullable: true
- description: The UUID of the current stage of the application
- example: 801f9ede-c698-4e66-a7fc-48d19eebaa4f
- reject_reason:
- type: string
+ description: The last modified date of the benefit record
+ remote_was_deleted:
+ type: boolean
+ example: false
nullable: true
- description: The rejection reason for the application
- example: Candidate not experienced enough
- candidate_id:
+ description: Indicates if the benefit was deleted in the remote system
+ UnifiedHrisCompanyOutput:
+ type: object
+ properties:
+ legal_name:
type: string
+ example: Acme Corporation
nullable: true
- description: The UUID of the candidate
- example: 801f9ede-c698-4e66-a7fc-48d19eebaa4f
- job_id:
+ description: The legal name of the company
+ locations:
+ example:
+ - 801f9ede-c698-4e66-a7fc-48d19eebaa4f
+ nullable: true
+ description: UUIDs of the of the Location associated with the company
+ type: array
+ items:
+ type: string
+ display_name:
type: string
- description: The UUID of the job
- example: 801f9ede-c698-4e66-a7fc-48d19eebaa4f
+ example: Acme Corp
+ nullable: true
+ description: The display name of the company
+ eins:
+ example:
+ - 12-3456789
+ - 98-7654321
+ nullable: true
+ description: The Employer Identification Numbers (EINs) of the company
+ type: array
+ items:
+ type: string
field_mappings:
type: object
- example: &ref_127
- fav_dish: broccoli
- fav_color: red
- additionalProperties: true
+ example:
+ custom_field_1: value1
+ custom_field_2: value2
nullable: true
description: >-
The custom field mappings of the object between the remote 3rd party & Panora
id:
type: string
- nullable: true
- description: The UUID of the application
example: 801f9ede-c698-4e66-a7fc-48d19eebaa4f
+ nullable: true
+ description: The UUID of the company record
remote_id:
type: string
+ example: company_1234
nullable: true
- description: The remote ID of the application in the context of the 3rd Party
- example: id_1
+ description: The remote ID of the company in the context of the 3rd Party
remote_data:
type: object
example:
- fav_dish: broccoli
- fav_color: red
+ raw_data:
+ additional_field: some value
nullable: true
- additionalProperties: true
- description: The remote data of the application in the context of the 3rd Party
- created_at:
+ description: The remote data of the company in the context of the 3rd Party
+ remote_created_at:
format: date-time
type: string
example: '2024-10-01T12:00:00Z'
nullable: true
- description: The created date of the object
- modified_at:
+ description: The date when the company was created in the 3rd party system
+ created_at:
format: date-time
type: string
example: '2024-10-01T12:00:00Z'
nullable: true
- description: The modified date of the object
- remote_created_at:
+ description: The created date of the company record
+ modified_at:
format: date-time
type: string
+ example: '2024-10-01T12:00:00Z'
nullable: true
- description: The remote created date of the object
- remote_modified_at:
- format: date-time
- type: string
+ description: The last modified date of the company record
+ remote_was_deleted:
+ type: boolean
+ example: false
nullable: true
- description: The remote modified date of the object
- UnifiedAtsApplicationInput:
+ description: Indicates if the company was deleted in the remote system
+ UnifiedHrisDependentOutput:
type: object
properties:
- applied_at:
- format: date-time
+ first_name:
type: string
+ example: John
nullable: true
- description: The application date
- example: '2024-10-01T12:00:00Z'
- rejected_at:
- format: date-time
+ description: The first name of the dependent
+ last_name:
type: string
+ example: Doe
nullable: true
- description: The rejection date
- example: '2024-10-01T12:00:00Z'
- offers:
- nullable: true
- description: The offers UUIDs for the application
- example: *ref_126
- type: array
- items:
- type: string
- source:
+ description: The last name of the dependent
+ middle_name:
type: string
+ example: Michael
nullable: true
- description: The source of the application
- example: Source Name
- credited_to:
+ description: The middle name of the dependent
+ relationship:
type: string
+ example: CHILD
+ enum:
+ - CHILD
+ - SPOUSE
+ - DOMESTIC_PARTNER
nullable: true
- description: The UUID of the person credited for the application
- example: 801f9ede-c698-4e66-a7fc-48d19eebaa4f
- current_stage:
+ description: The relationship of the dependent to the employee
+ date_of_birth:
+ format: date-time
type: string
+ example: '2020-01-01'
nullable: true
- description: The UUID of the current stage of the application
- example: 801f9ede-c698-4e66-a7fc-48d19eebaa4f
- reject_reason:
+ description: The date of birth of the dependent
+ gender:
type: string
+ example: MALE
+ enum:
+ - MALE
+ - FEMALE
+ - NON-BINARY
+ - OTHER
+ - PREFER_NOT_TO_DISCLOSE
nullable: true
- description: The rejection reason for the application
- example: Candidate not experienced enough
- candidate_id:
+ description: The gender of the dependent
+ phone_number:
type: string
+ example: '+1234567890'
nullable: true
- description: The UUID of the candidate
- example: 801f9ede-c698-4e66-a7fc-48d19eebaa4f
- job_id:
+ description: The phone number of the dependent
+ home_location:
type: string
- description: The UUID of the job
example: 801f9ede-c698-4e66-a7fc-48d19eebaa4f
- field_mappings:
- type: object
- example: *ref_127
- additionalProperties: true
- nullable: true
- description: >-
- The custom field mappings of the object between the remote 3rd party & Panora
- UnifiedAtsAttachmentOutput:
- type: object
- properties:
- file_url:
- type: string
- example: https://example.com/file.pdf
- nullable: true
- description: The URL of the file
- file_name:
- type: string
- example: file.pdf
- nullable: true
- description: The name of the file
- attachment_type:
- type: string
- example: RESUME
- enum: &ref_128
- - RESUME
- - COVER_LETTER
- - OFFER_LETTER
- - OTHER
nullable: true
- description: The type of the file
- remote_created_at:
- type: string
- example: '2024-10-01T12:00:00Z'
- format: date-time
+ description: The UUID of the home location
+ is_student:
+ type: boolean
+ example: true
nullable: true
- description: The remote creation date of the attachment
- remote_modified_at:
+ description: Indicates if the dependent is a student
+ ssn:
type: string
- example: '2024-10-01T12:00:00Z'
- format: date-time
+ example: 123-45-6789
nullable: true
- description: The remote modification date of the attachment
- candidate_id:
+ description: The Social Security Number of the dependent
+ employee_id:
type: string
example: 801f9ede-c698-4e66-a7fc-48d19eebaa4f
nullable: true
- description: The UUID of the candidate
+ description: The UUID of the associated employee
field_mappings:
type: object
- example: &ref_129
- fav_dish: broccoli
- fav_color: red
- additionalProperties: true
+ example:
+ custom_field_1: value1
+ custom_field_2: value2
nullable: true
description: >-
The custom field mappings of the object between the remote 3rd party & Panora
@@ -27675,210 +28015,155 @@ components:
type: string
example: 801f9ede-c698-4e66-a7fc-48d19eebaa4f
nullable: true
- description: The UUID of the attachment
+ description: The UUID of the dependent record
remote_id:
type: string
- example: 801f9ede-c698-4e66-a7fc-48d19eebaa4f
+ example: dependent_1234
nullable: true
- description: The remote ID of the attachment
+ description: The remote ID of the dependent in the context of the 3rd Party
remote_data:
type: object
example:
- fav_dish: broccoli
- fav_color: red
+ raw_data:
+ additional_field: some value
nullable: true
- additionalProperties: true
- description: The remote data of the attachment in the context of the 3rd Party
+ description: The remote data of the dependent in the context of the 3rd Party
+ remote_created_at:
+ format: date-time
+ type: string
+ example: '2024-10-01T12:00:00Z'
+ nullable: true
+ description: The date when the dependent was created in the 3rd party system
created_at:
format: date-time
type: string
example: '2024-10-01T12:00:00Z'
nullable: true
- description: The created date of the object
+ description: The created date of the dependent record
modified_at:
format: date-time
type: string
example: '2024-10-01T12:00:00Z'
nullable: true
- description: The modified date of the object
- UnifiedAtsAttachmentInput:
+ description: The last modified date of the dependent record
+ remote_was_deleted:
+ type: boolean
+ example: false
+ nullable: true
+ description: Indicates if the dependent was deleted in the remote system
+ DeductionItem:
type: object
properties:
- file_url:
+ name:
type: string
- example: https://example.com/file.pdf
+ example: Health Insurance
nullable: true
- description: The URL of the file
- file_name:
- type: string
- example: file.pdf
+ description: The name of the deduction
+ employee_deduction:
+ type: number
+ example: 100
nullable: true
- description: The name of the file
- attachment_type:
- type: string
- example: RESUME
- enum: *ref_128
+ description: The amount of employee deduction
+ company_deduction:
+ type: number
+ example: 200
nullable: true
- description: The type of the file
- remote_created_at:
- type: string
- example: '2024-10-01T12:00:00Z'
- format: date-time
+ description: The amount of company deduction
+ EarningItem:
+ type: object
+ properties:
+ amount:
+ type: number
+ example: 1000
nullable: true
- description: The remote creation date of the attachment
- remote_modified_at:
+ description: The amount of the earning
+ type:
type: string
- example: '2024-10-01T12:00:00Z'
- format: date-time
+ example: Salary
nullable: true
- description: The remote modification date of the attachment
- candidate_id:
+ description: The type of the earning
+ TaxItem:
+ type: object
+ properties:
+ name:
type: string
- example: 801f9ede-c698-4e66-a7fc-48d19eebaa4f
+ example: Federal Income Tax
nullable: true
- description: The UUID of the candidate
- field_mappings:
- type: object
- example: *ref_129
- additionalProperties: true
+ description: The name of the tax
+ amount:
+ type: number
+ example: 250
nullable: true
- description: >-
- The custom field mappings of the object between the remote 3rd party & Panora
- Url:
+ description: The amount of the tax
+ employer_tax:
+ type: boolean
+ example: true
+ nullable: true
+ description: Indicates if this is an employer tax
+ UnifiedHrisEmployeepayrollrunOutput:
type: object
properties:
- url:
+ employee_id:
type: string
+ example: 801f9ede-c698-4e66-a7fc-48d19eebaa4f
nullable: true
- description: The url.
- url_type:
+ description: The UUID of the associated employee
+ payroll_run_id:
type: string
+ example: 801f9ede-c698-4e66-a7fc-48d19eebaa4f
nullable: true
- description: The url type. It takes [WEBSITE | BLOG | LINKEDIN | GITHUB | OTHER]
- required:
- - url
- - url_type
- UnifiedAtsCandidateOutput:
- type: object
- properties:
- first_name:
- type: string
- example: Joe
- nullable: true
- description: The first name of the candidate
- last_name:
- type: string
- example: Doe
- nullable: true
- description: The last name of the candidate
- company:
- type: string
- example: Acme
+ description: The UUID of the associated payroll run
+ gross_pay:
+ type: number
+ example: 5000
nullable: true
- description: The company of the candidate
- title:
- type: string
- example: Analyst
+ description: The gross pay amount
+ net_pay:
+ type: number
+ example: 4000
nullable: true
- description: The title of the candidate
- locations:
+ description: The net pay amount
+ start_date:
+ format: date-time
type: string
- example: New York
- nullable: true
- description: The locations of the candidate
- is_private:
- type: boolean
- example: false
- nullable: true
- description: Whether the candidate is private
- email_reachable:
- type: boolean
- example: true
+ example: '2023-01-01T00:00:00Z'
nullable: true
- description: Whether the candidate is reachable by email
- remote_created_at:
- type: string
- example: '2024-10-01T12:00:00Z'
+ description: The start date of the pay period
+ end_date:
format: date-time
- nullable: true
- description: The remote creation date of the candidate
- remote_modified_at:
type: string
- example: '2024-10-01T12:00:00Z'
- format: date-time
+ example: '2023-01-15T23:59:59Z'
nullable: true
- description: The remote modification date of the candidate
- last_interaction_at:
- type: string
- example: '2024-10-01T12:00:00Z'
+ description: The end date of the pay period
+ check_date:
format: date-time
+ type: string
+ example: '2023-01-20T00:00:00Z'
nullable: true
- description: The last interaction date with the candidate
- attachments:
- type: array
- items: &ref_130
- oneOf:
- - type: string
- - $ref: '#/components/schemas/UnifiedAtsAttachmentOutput'
- example: &ref_131
- - 801f9ede-c698-4e66-a7fc-48d19eebaa4f
- nullable: true
- description: The attachments UUIDs of the candidate
- applications:
- type: array
- items: &ref_132
- oneOf:
- - type: string
- - $ref: '#/components/schemas/UnifiedAtsApplicationOutput'
- example: &ref_133
- - 801f9ede-c698-4e66-a7fc-48d19eebaa4f
- nullable: true
- description: The applications UUIDs of the candidate
- tags:
- type: array
- items: &ref_134
- oneOf:
- - type: string
- - $ref: '#/components/schemas/UnifiedAtsTagOutput'
- example: &ref_135
- - tag_1
- - tag_2
- nullable: true
- description: The tags of the candidate
- urls:
- example: &ref_136
- - url: mywebsite.com
- url_type: WEBSITE
+ description: The date the check was issued
+ deductions:
nullable: true
- description: >-
- The urls of the candidate, possible values for Url type are WEBSITE, BLOG, LINKEDIN, GITHUB, or OTHER
+ description: The list of deductions for this payroll run
type: array
items:
- $ref: '#/components/schemas/Url'
- phone_numbers:
- example: &ref_137
- - phone_number: '+33660688899'
- phone_type: WORK
+ $ref: '#/components/schemas/DeductionItem'
+ earnings:
nullable: true
- description: The phone numbers of the candidate
+ description: The list of earnings for this payroll run
type: array
items:
- $ref: '#/components/schemas/Phone'
- email_addresses:
- example: &ref_138
- - email_address: joedoe@gmail.com
- email_address_type: WORK
+ $ref: '#/components/schemas/EarningItem'
+ taxes:
nullable: true
- description: The email addresses of the candidate
+ description: The list of taxes for this payroll run
type: array
items:
- $ref: '#/components/schemas/Email'
+ $ref: '#/components/schemas/TaxItem'
field_mappings:
type: object
- example: &ref_139
- fav_dish: broccoli
- fav_color: red
- additionalProperties: true
+ example:
+ custom_field_1: value1
+ custom_field_2: value2
nullable: true
description: >-
The custom field mappings of the object between the remote 3rd party & Panora
@@ -27886,149 +28171,208 @@ components:
type: string
example: 801f9ede-c698-4e66-a7fc-48d19eebaa4f
nullable: true
- description: The UUID of the candidate
+ description: The UUID of the employee payroll run record
remote_id:
type: string
- example: id_1
+ example: payroll_run_1234
nullable: true
- description: The id of the candidate in the context of the 3rd Party
+ description: >-
+ The remote ID of the employee payroll run in the context of the 3rd Party
remote_data:
type: object
example:
- fav_dish: broccoli
- fav_color: red
+ raw_data:
+ additional_field: some value
nullable: true
- additionalProperties: true
- description: The remote data of the candidate in the context of the 3rd Party
+ description: >-
+ The remote data of the employee payroll run in the context of the 3rd Party
+ remote_created_at:
+ format: date-time
+ type: string
+ example: '2024-10-01T12:00:00Z'
+ nullable: true
+ description: >-
+ The date when the employee payroll run was created in the 3rd party system
created_at:
format: date-time
type: string
example: '2024-10-01T12:00:00Z'
nullable: true
- description: The created date of the object
+ description: The created date of the employee payroll run record
modified_at:
format: date-time
type: string
example: '2024-10-01T12:00:00Z'
nullable: true
- description: The modified date of the object
- UnifiedAtsCandidateInput:
+ description: The last modified date of the employee payroll run record
+ remote_was_deleted:
+ type: boolean
+ example: false
+ nullable: true
+ description: >-
+ Indicates if the employee payroll run was deleted in the remote system
+ UnifiedHrisEmployeeOutput:
type: object
properties:
+ groups:
+ example: &ref_124
+ - Group1
+ - Group2
+ nullable: true
+ description: The groups the employee belongs to
+ type: array
+ items:
+ type: string
+ locations:
+ example: &ref_125
+ - 801f9ede-c698-4e66-a7fc-48d19eebaa4f
+ nullable: true
+ description: UUIDs of the of the Location associated with the company
+ type: array
+ items:
+ type: string
+ employee_number:
+ type: string
+ example: EMP001
+ nullable: true
+ description: The employee number
+ company_id:
+ type: string
+ example: 801f9ede-c698-4e66-a7fc-48d19eebaa4f
+ nullable: true
+ description: The UUID of the associated company
first_name:
type: string
- example: Joe
+ example: John
nullable: true
- description: The first name of the candidate
+ description: The first name of the employee
last_name:
type: string
example: Doe
nullable: true
- description: The last name of the candidate
- company:
+ description: The last name of the employee
+ preferred_name:
type: string
- example: Acme
+ example: Johnny
nullable: true
- description: The company of the candidate
- title:
+ description: The preferred name of the employee
+ display_full_name:
type: string
- example: Analyst
+ example: John Doe
nullable: true
- description: The title of the candidate
- locations:
+ description: The full display name of the employee
+ username:
type: string
- example: New York
+ example: johndoe
nullable: true
- description: The locations of the candidate
- is_private:
- type: boolean
- example: false
+ description: The username of the employee
+ work_email:
+ type: string
+ example: john.doe@company.com
nullable: true
- description: Whether the candidate is private
- email_reachable:
- type: boolean
- example: true
+ description: The work email of the employee
+ personal_email:
+ type: string
+ example: john.doe@personal.com
nullable: true
- description: Whether the candidate is reachable by email
- remote_created_at:
+ description: The personal email of the employee
+ mobile_phone_number:
type: string
- example: '2024-10-01T12:00:00Z'
- format: date-time
+ example: '+1234567890'
nullable: true
- description: The remote creation date of the candidate
- remote_modified_at:
+ description: The mobile phone number of the employee
+ employments:
+ example: &ref_126
+ - 801f9ede-c698-4e66-a7fc-48d19eebaa4f
+ - 801f9ede-c698-4e66-a7fc-48d19eebaa4f
+ nullable: true
+ description: The employments of the employee
+ type: array
+ items:
+ type: string
+ ssn:
type: string
- example: '2024-10-01T12:00:00Z'
- format: date-time
+ example: 123-45-6789
nullable: true
- description: The remote modification date of the candidate
- last_interaction_at:
+ description: The Social Security Number of the employee
+ gender:
type: string
- example: '2024-10-01T12:00:00Z'
- format: date-time
+ example: MALE
+ enum: &ref_127
+ - MALE
+ - FEMALE
+ - NON-BINARY
+ - OTHER
+ - PREFER_NOT_TO_DISCLOSE
nullable: true
- description: The last interaction date with the candidate
- attachments:
- type: array
- items: *ref_130
- example: *ref_131
+ description: The gender of the employee
+ ethnicity:
+ type: string
+ example: AMERICAN_INDIAN_OR_ALASKA_NATIVE
+ enum: &ref_128
+ - AMERICAN_INDIAN_OR_ALASKA_NATIVE
+ - ASIAN_OR_INDIAN_SUBCONTINENT
+ - BLACK_OR_AFRICAN_AMERICAN
+ - HISPANIC_OR_LATINO
+ - NATIVE_HAWAIIAN_OR_OTHER_PACIFIC_ISLANDER
+ - TWO_OR_MORE_RACES
+ - WHITE
+ - PREFER_NOT_TO_DISCLOSE
nullable: true
- description: The attachments UUIDs of the candidate
- applications:
- type: array
- items: *ref_132
- example: *ref_133
+ description: The ethnicity of the employee
+ marital_status:
+ type: string
+ example: Married
+ enum: &ref_129
+ - SINGLE
+ - MARRIED_FILING_JOINTLY
+ - MARRIED_FILING_SEPARATELY
+ - HEAD_OF_HOUSEHOLD
+ - QUALIFYING_WIDOW_OR_WIDOWER_WITH_DEPENDENT_CHILD
nullable: true
- description: The applications UUIDs of the candidate
- tags:
- type: array
- items: *ref_134
- example: *ref_135
+ description: The marital status of the employee
+ date_of_birth:
+ format: date-time
+ type: string
+ example: '1990-01-01'
nullable: true
- description: The tags of the candidate
- urls:
- example: *ref_136
+ description: The date of birth of the employee
+ start_date:
+ format: date-time
+ type: string
+ example: '2020-01-01'
nullable: true
- description: >-
- The urls of the candidate, possible values for Url type are WEBSITE, BLOG, LINKEDIN, GITHUB, or OTHER
- type: array
- items:
- $ref: '#/components/schemas/Url'
- phone_numbers:
- example: *ref_137
+ description: The start date of the employee
+ employment_status:
+ type: string
+ example: ACTIVE
+ enum: &ref_130
+ - ACTIVE
+ - PENDING
+ - INACTIVE
nullable: true
- description: The phone numbers of the candidate
- type: array
- items:
- $ref: '#/components/schemas/Phone'
- email_addresses:
- example: *ref_138
+ description: The employment status of the employee
+ termination_date:
+ format: date-time
+ type: string
+ example: '2025-01-01'
nullable: true
- description: The email addresses of the candidate
- type: array
- items:
- $ref: '#/components/schemas/Email'
- field_mappings:
- type: object
- example: *ref_139
- additionalProperties: true
+ description: The termination date of the employee
+ avatar_url:
+ type: string
+ example: https://example.com/avatar.jpg
nullable: true
- description: >-
- The custom field mappings of the object between the remote 3rd party & Panora
- UnifiedAtsDepartmentOutput:
- type: object
- properties:
- name:
+ description: The URL of the employee's avatar
+ manager_id:
type: string
- example: Sales
+ example: 801f9ede-c698-4e66-a7fc-48d19eebaa4f
nullable: true
- description: The name of the department
+ description: UUID of the manager (employee) of the employee
field_mappings:
type: object
- example:
- fav_dish: broccoli
- fav_color: red
- additionalProperties: true
+ example: &ref_131
+ custom_field_1: value1
+ custom_field_2: value2
nullable: true
description: >-
The custom field mappings of the object between the remote 3rd party & Panora
@@ -28036,227 +28380,213 @@ components:
type: string
example: 801f9ede-c698-4e66-a7fc-48d19eebaa4f
nullable: true
- description: The UUID of the department
+ description: The UUID of the employee record
remote_id:
type: string
- example: id_1
+ example: employee_1234
nullable: true
- description: The remote ID of the department in the context of the 3rd Party
+ description: The remote ID of the employee in the context of the 3rd Party
remote_data:
type: object
example:
- key1: value1
- key2: 42
- key3: true
+ raw_data:
+ additional_field: some value
nullable: true
- additionalProperties: true
- description: The remote data of the department in the context of the 3rd Party
+ description: The remote data of the employee in the context of the 3rd Party
+ remote_created_at:
+ format: date-time
+ type: string
+ example: '2024-10-01T12:00:00Z'
+ nullable: true
+ description: The date when the employee was created in the 3rd party system
created_at:
format: date-time
type: string
example: '2024-10-01T12:00:00Z'
nullable: true
- description: The created date of the object
+ description: The created date of the employee record
modified_at:
format: date-time
type: string
- example: '2023-10-01T12:00:00Z'
+ example: '2024-10-01T12:00:00Z'
nullable: true
- description: The modified date of the object
- UnifiedAtsInterviewOutput:
+ description: The last modified date of the employee record
+ remote_was_deleted:
+ type: boolean
+ example: false
+ nullable: true
+ description: Indicates if the employee was deleted in the remote system
+ UnifiedHrisEmployeeInput:
type: object
properties:
- status:
- type: string
- enum: &ref_140
- - SCHEDULED
- - AWAITING_FEEDBACK
- - COMPLETED
- example: SCHEDULED
- nullable: true
- description: The status of the interview
- application_id:
- type: string
- example: 801f9ede-c698-4e66-a7fc-48d19eebaa4f
- nullable: true
- description: The UUID of the application
- job_interview_stage_id:
- type: string
- example: 801f9ede-c698-4e66-a7fc-48d19eebaa4f
- nullable: true
- description: The UUID of the job interview stage
- organized_by:
- type: string
- example: 801f9ede-c698-4e66-a7fc-48d19eebaa4f
+ groups:
+ example: *ref_124
nullable: true
- description: The UUID of the organizer
- interviewers:
- example: &ref_141
- - 801f9ede-c698-4e66-a7fc-48d19eebaa4f
+ description: The groups the employee belongs to
+ type: array
+ items:
+ type: string
+ locations:
+ example: *ref_125
nullable: true
- description: The UUIDs of the interviewers
+ description: UUIDs of the of the Location associated with the company
type: array
items:
type: string
- location:
+ employee_number:
type: string
- example: San Francisco
+ example: EMP001
nullable: true
- description: The location of the interview
- start_at:
- format: date-time
+ description: The employee number
+ company_id:
type: string
- example: '2024-10-01T12:00:00Z'
+ example: 801f9ede-c698-4e66-a7fc-48d19eebaa4f
nullable: true
- description: The start date and time of the interview
- end_at:
- format: date-time
+ description: The UUID of the associated company
+ first_name:
type: string
- example: '2024-10-01T12:00:00Z'
+ example: John
nullable: true
- description: The end date and time of the interview
- remote_created_at:
- format: date-time
+ description: The first name of the employee
+ last_name:
type: string
- example: '2024-10-01T12:00:00Z'
+ example: Doe
nullable: true
- description: The remote creation date of the interview
- remote_updated_at:
- format: date-time
+ description: The last name of the employee
+ preferred_name:
type: string
- example: '2024-10-01T12:00:00Z'
- nullable: true
- description: The remote modification date of the interview
- field_mappings:
- type: object
- example: &ref_142
- fav_dish: broccoli
- fav_color: red
- additionalProperties: true
+ example: Johnny
nullable: true
- description: >-
- The custom field mappings of the object between the remote 3rd party & Panora
- id:
+ description: The preferred name of the employee
+ display_full_name:
type: string
- example: 801f9ede-c698-4e66-a7fc-48d19eebaa4f
+ example: John Doe
nullable: true
- description: The UUID of the interview
- remote_id:
+ description: The full display name of the employee
+ username:
type: string
- example: id_1
- nullable: true
- description: The remote ID of the interview in the context of the 3rd Party
- remote_data:
- type: object
- example:
- fav_dish: broccoli
- fav_color: red
+ example: johndoe
nullable: true
- additionalProperties: true
- description: The remote data of the interview in the context of the 3rd Party
- created_at:
- format: date-time
+ description: The username of the employee
+ work_email:
type: string
- example: '2024-10-01T12:00:00Z'
+ example: john.doe@company.com
nullable: true
- description: The created date of the object
- modified_at:
- format: date-time
+ description: The work email of the employee
+ personal_email:
type: string
- example: '2024-10-01T12:00:00Z'
+ example: john.doe@personal.com
nullable: true
- description: The modified date of the object
- UnifiedAtsInterviewInput:
- type: object
- properties:
- status:
+ description: The personal email of the employee
+ mobile_phone_number:
type: string
- enum: *ref_140
- example: SCHEDULED
+ example: '+1234567890'
nullable: true
- description: The status of the interview
- application_id:
- type: string
- example: 801f9ede-c698-4e66-a7fc-48d19eebaa4f
+ description: The mobile phone number of the employee
+ employments:
+ example: *ref_126
nullable: true
- description: The UUID of the application
- job_interview_stage_id:
+ description: The employments of the employee
+ type: array
+ items:
+ type: string
+ ssn:
type: string
- example: 801f9ede-c698-4e66-a7fc-48d19eebaa4f
+ example: 123-45-6789
nullable: true
- description: The UUID of the job interview stage
- organized_by:
+ description: The Social Security Number of the employee
+ gender:
type: string
- example: 801f9ede-c698-4e66-a7fc-48d19eebaa4f
+ example: MALE
+ enum: *ref_127
nullable: true
- description: The UUID of the organizer
- interviewers:
- example: *ref_141
+ description: The gender of the employee
+ ethnicity:
+ type: string
+ example: AMERICAN_INDIAN_OR_ALASKA_NATIVE
+ enum: *ref_128
nullable: true
- description: The UUIDs of the interviewers
- type: array
- items:
- type: string
- location:
+ description: The ethnicity of the employee
+ marital_status:
type: string
- example: San Francisco
+ example: Married
+ enum: *ref_129
nullable: true
- description: The location of the interview
- start_at:
+ description: The marital status of the employee
+ date_of_birth:
format: date-time
type: string
- example: '2024-10-01T12:00:00Z'
+ example: '1990-01-01'
nullable: true
- description: The start date and time of the interview
- end_at:
+ description: The date of birth of the employee
+ start_date:
format: date-time
type: string
- example: '2024-10-01T12:00:00Z'
+ example: '2020-01-01'
nullable: true
- description: The end date and time of the interview
- remote_created_at:
- format: date-time
+ description: The start date of the employee
+ employment_status:
type: string
- example: '2024-10-01T12:00:00Z'
+ example: ACTIVE
+ enum: *ref_130
nullable: true
- description: The remote creation date of the interview
- remote_updated_at:
+ description: The employment status of the employee
+ termination_date:
format: date-time
type: string
- example: '2024-10-01T12:00:00Z'
+ example: '2025-01-01'
nullable: true
- description: The remote modification date of the interview
+ description: The termination date of the employee
+ avatar_url:
+ type: string
+ example: https://example.com/avatar.jpg
+ nullable: true
+ description: The URL of the employee's avatar
+ manager_id:
+ type: string
+ example: 801f9ede-c698-4e66-a7fc-48d19eebaa4f
+ nullable: true
+ description: UUID of the manager (employee) of the employee
field_mappings:
type: object
- example: *ref_142
- additionalProperties: true
+ example: *ref_131
nullable: true
description: >-
The custom field mappings of the object between the remote 3rd party & Panora
- UnifiedAtsJobinterviewstageOutput:
+ UnifiedHrisEmployerbenefitOutput:
type: object
properties:
+ benefit_plan_type:
+ type: string
+ example: Health Insurance
+ enum:
+ - MEDICAL
+ - HEALTH_SAVINGS
+ - INSURANCE
+ - RETIREMENT
+ - OTHER
+ nullable: true
+ description: The type of the benefit plan
name:
type: string
- example: Second Call
+ example: Company Health Plan
nullable: true
- description: The name of the job interview stage
- stage_order:
- type: number
- example: 1
+ description: The name of the employer benefit
+ description:
+ type: string
+ example: Comprehensive health insurance coverage for employees
nullable: true
- description: The order of the stage
- job_id:
+ description: The description of the employer benefit
+ deduction_code:
type: string
- example: 801f9ede-c698-4e66-a7fc-48d19eebaa4f
+ example: HEALTH-001
nullable: true
- description: The UUID of the job
+ description: The deduction code for the employer benefit
field_mappings:
type: object
example:
- fav_dish: broccoli
- fav_color: red
- additionalProperties: true
+ custom_field_1: value1
+ custom_field_2: value2
nullable: true
description: >-
The custom field mappings of the object between the remote 3rd party & Panora
@@ -28264,127 +28594,298 @@ components:
type: string
example: 801f9ede-c698-4e66-a7fc-48d19eebaa4f
nullable: true
- description: The UUID of the job interview stage
+ description: The UUID of the employer benefit record
remote_id:
type: string
- example: id_1
+ example: benefit_1234
nullable: true
description: >-
- The remote ID of the job interview stage in the context of the 3rd Party
+ The remote ID of the employer benefit in the context of the 3rd Party
remote_data:
type: object
example:
- fav_dish: broccoli
- fav_color: red
+ raw_data:
+ additional_field: some value
nullable: true
- additionalProperties: true
description: >-
- The remote data of the job interview stage in the context of the 3rd Party
+ The remote data of the employer benefit in the context of the 3rd Party
+ remote_created_at:
+ format: date-time
+ type: string
+ example: '2024-10-01T12:00:00Z'
+ nullable: true
+ description: >-
+ The date when the employer benefit was created in the 3rd party system
created_at:
format: date-time
type: string
example: '2024-10-01T12:00:00Z'
nullable: true
- description: The created date of the object
+ description: The created date of the employer benefit record
modified_at:
format: date-time
type: string
example: '2024-10-01T12:00:00Z'
nullable: true
- description: The modified date of the object
- UnifiedAtsJobOutput:
+ description: The last modified date of the employer benefit record
+ remote_was_deleted:
+ type: boolean
+ example: false
+ nullable: true
+ description: Indicates if the employer benefit was deleted in the remote system
+ UnifiedHrisEmploymentOutput:
type: object
properties:
- name:
- type: string
- example: Financial Analyst
- nullable: true
- description: The name of the job
- description:
+ job_title:
type: string
- example: Extract financial data and write detailed investment thesis
+ example: Software Engineer
nullable: true
- description: The description of the job
- code:
- type: string
- example: JOB123
+ description: The job title of the employment
+ pay_rate:
+ type: number
+ example: 100000
nullable: true
- description: The code of the job
- status:
+ description: The pay rate of the employment
+ pay_period:
type: string
+ example: MONTHLY
enum:
- - OPEN
- - CLOSED
- - DRAFT
- - ARCHIVED
- - PENDING
- example: OPEN
- nullable: true
- description: The status of the job
- type:
- type: string
- example: POSTING
+ - HOUR
+ - DAY
+ - WEEK
+ - EVERY_TWO_WEEKS
+ - SEMIMONTHLY
+ - MONTH
+ - QUARTER
+ - EVERY_SIX_MONTHS
+ - YEAR
+ nullable: true
+ description: The pay period of the employment
+ pay_frequency:
+ type: string
+ example: WEEKLY
enum:
- - POSTING
- - REQUISITION
- - PROFILE
- nullable: true
- description: The type of the job
- confidential:
- type: boolean
- example: true
- nullable: true
- description: Whether the job is confidential
- departments:
- example:
- - 801f9ede-c698-4e66-a7fc-48d19eebaa4f
- nullable: true
- description: The departments UUIDs associated with the job
- type: array
- items:
- type: string
- offices:
- example:
- - 801f9ede-c698-4e66-a7fc-48d19eebaa4f
- nullable: true
- description: The offices UUIDs associated with the job
- type: array
- items:
- type: string
- managers:
- example:
- - 801f9ede-c698-4e66-a7fc-48d19eebaa4f
- nullable: true
- description: The managers UUIDs associated with the job
- type: array
- items:
- type: string
- recruiters:
- example:
- - 801f9ede-c698-4e66-a7fc-48d19eebaa4f
+ - WEEKLY
+ - BIWEEKLY
+ - MONTHLY
+ - QUARTERLY
+ - SEMIANNUALLY
+ - ANNUALLY
+ - THIRTEEN-MONTHLY
+ - PRO_RATA
+ - SEMIMONTHLY
+ nullable: true
+ description: The pay frequency of the employment
+ pay_currency:
+ type: string
+ example: USD
+ enum:
+ - AED
+ - AFN
+ - ALL
+ - AMD
+ - ANG
+ - AOA
+ - ARS
+ - AUD
+ - AWG
+ - AZN
+ - BAM
+ - BBD
+ - BDT
+ - BGN
+ - BHD
+ - BIF
+ - BMD
+ - BND
+ - BOB
+ - BRL
+ - BSD
+ - BTN
+ - BWP
+ - BYN
+ - BZD
+ - CAD
+ - CDF
+ - CHF
+ - CLP
+ - CNY
+ - COP
+ - CRC
+ - CUP
+ - CVE
+ - CZK
+ - DJF
+ - DKK
+ - DOP
+ - DZD
+ - EGP
+ - ERN
+ - ETB
+ - EUR
+ - FJD
+ - FKP
+ - FOK
+ - GBP
+ - GEL
+ - GGP
+ - GHS
+ - GIP
+ - GMD
+ - GNF
+ - GTQ
+ - GYD
+ - HKD
+ - HNL
+ - HRK
+ - HTG
+ - HUF
+ - IDR
+ - ILS
+ - IMP
+ - INR
+ - IQD
+ - IRR
+ - ISK
+ - JEP
+ - JMD
+ - JOD
+ - JPY
+ - KES
+ - KGS
+ - KHR
+ - KID
+ - KMF
+ - KRW
+ - KWD
+ - KYD
+ - KZT
+ - LAK
+ - LBP
+ - LKR
+ - LRD
+ - LSL
+ - LYD
+ - MAD
+ - MDL
+ - MGA
+ - MKD
+ - MMK
+ - MNT
+ - MOP
+ - MRU
+ - MUR
+ - MVR
+ - MWK
+ - MXN
+ - MYR
+ - MZN
+ - NAD
+ - NGN
+ - NIO
+ - NOK
+ - NPR
+ - NZD
+ - OMR
+ - PAB
+ - PEN
+ - PGK
+ - PHP
+ - PKR
+ - PLN
+ - PYG
+ - QAR
+ - RON
+ - RSD
+ - RUB
+ - RWF
+ - SAR
+ - SBD
+ - SCR
+ - SDG
+ - SEK
+ - SGD
+ - SHP
+ - SLE
+ - SLL
+ - SOS
+ - SRD
+ - SSP
+ - STN
+ - SYP
+ - SZL
+ - THB
+ - TJS
+ - TMT
+ - TND
+ - TOP
+ - TRY
+ - TTD
+ - TVD
+ - TWD
+ - TZS
+ - UAH
+ - UGX
+ - USD
+ - UYU
+ - UZS
+ - VES
+ - VND
+ - VUV
+ - WST
+ - XAF
+ - XCD
+ - XDR
+ - XOF
+ - XPF
+ - YER
+ - ZAR
+ - ZMW
+ - ZWL
nullable: true
- description: The recruiters UUIDs associated with the job
- type: array
- items:
- type: string
- remote_created_at:
+ description: The currency of the pay
+ flsa_status:
type: string
- example: '2024-10-01T12:00:00Z'
+ example: EXEMPT
+ enum:
+ - EXEMPT
+ - SALARIED_NONEXEMPT
+ - NONEXEMPT
+ - OWNER
+ nullable: true
+ description: The FLSA status of the employment
+ effective_date:
format: date-time
+ type: string
+ example: '2023-01-01'
nullable: true
- description: The remote creation date of the job
- remote_updated_at:
+ description: The effective date of the employment
+ employment_type:
type: string
- example: '2024-10-01T12:00:00Z'
- format: date-time
+ example: FULL_TIME
+ enum:
+ - FULL_TIME
+ - PART_TIME
+ - INTERN
+ - CONTRACTOR
+ - FREELANCE
nullable: true
- description: The remote modification date of the job
+ description: The type of employment
+ pay_group_id:
+ type: string
+ example: 801f9ede-c698-4e66-a7fc-48d19eebaa4f
+ nullable: true
+ description: The UUID of the associated pay group
+ employee_id:
+ type: string
+ example: 801f9ede-c698-4e66-a7fc-48d19eebaa4f
+ nullable: true
+ description: The UUID of the associated employee
field_mappings:
type: object
example:
- fav_dish: broccoli
- fav_color: red
- additionalProperties: true
+ custom_field_1: value1
+ custom_field_2: value2
nullable: true
description: >-
The custom field mappings of the object between the remote 3rd party & Panora
@@ -28392,313 +28893,450 @@ components:
type: string
example: 801f9ede-c698-4e66-a7fc-48d19eebaa4f
nullable: true
- description: The UUID of the job
+ description: The UUID of the employment record
remote_id:
type: string
- example: id_1
+ example: employment_1234
nullable: true
- description: The remote ID of the job in the context of the 3rd Party
+ description: The remote ID of the employment in the context of the 3rd Party
remote_data:
type: object
example:
- key1: value1
- key2: 42
- key3: true
+ raw_data:
+ additional_field: some value
nullable: true
- additionalProperties: true
- description: The remote data of the job in the context of the 3rd Party
+ description: The remote data of the employment in the context of the 3rd Party
+ remote_created_at:
+ format: date-time
+ type: string
+ example: '2024-10-01T12:00:00Z'
+ nullable: true
+ description: The date when the employment was created in the 3rd party system
created_at:
format: date-time
type: string
example: '2024-10-01T12:00:00Z'
nullable: true
- description: The created date of the object
+ description: The created date of the employment record
modified_at:
format: date-time
type: string
- example: '2023-10-01T12:00:00Z'
+ example: '2024-10-01T12:00:00Z'
nullable: true
- description: The modified date of the object
- UnifiedAtsOfferOutput:
+ description: The last modified date of the employment record
+ remote_was_deleted:
+ type: boolean
+ example: false
+ nullable: true
+ description: Indicates if the employment was deleted in the remote system
+ UnifiedHrisGroupOutput:
type: object
properties:
- created_by:
+ parent_group:
type: string
example: 801f9ede-c698-4e66-a7fc-48d19eebaa4f
- description: The UUID of the creator
nullable: true
+ description: The UUID of the parent group
+ name:
+ type: string
+ example: Engineering Team
+ nullable: true
+ description: The name of the group
+ type:
+ type: string
+ example: DEPARTMENT
+ enum:
+ - TEAM
+ - DEPARTMENT
+ - COST_CENTER
+ - BUSINESS_UNIT
+ - GROUP
+ nullable: true
+ description: The type of the group
+ field_mappings:
+ type: object
+ example:
+ custom_field_1: value1
+ custom_field_2: value2
+ nullable: true
+ description: >-
+ The custom field mappings of the object between the remote 3rd party & Panora
+ id:
+ type: string
+ example: 801f9ede-c698-4e66-a7fc-48d19eebaa4f
+ nullable: true
+ description: The UUID of the group record
+ remote_id:
+ type: string
+ example: group_1234
+ nullable: true
+ description: The remote ID of the group in the context of the 3rd Party
+ remote_data:
+ type: object
+ example:
+ raw_data:
+ additional_field: some value
+ nullable: true
+ description: The remote data of the group in the context of the 3rd Party
remote_created_at:
format: date-time
type: string
example: '2024-10-01T12:00:00Z'
- description: The remote creation date of the offer
nullable: true
- closed_at:
+ description: The date when the group was created in the 3rd party system
+ created_at:
format: date-time
type: string
example: '2024-10-01T12:00:00Z'
- description: The closing date of the offer
nullable: true
- sent_at:
+ description: The created date of the group record
+ modified_at:
format: date-time
type: string
example: '2024-10-01T12:00:00Z'
- description: The sending date of the offer
nullable: true
- start_date:
- format: date-time
+ description: The last modified date of the group record
+ remote_was_deleted:
+ type: boolean
+ example: false
+ nullable: true
+ description: Indicates if the group was deleted in the remote system
+ UnifiedHrisLocationOutput:
+ type: object
+ properties:
+ name:
type: string
- example: '2024-10-01T12:00:00Z'
- description: The start date of the offer
+ example: Headquarters
nullable: true
- status:
+ description: The name of the location
+ phone_number:
type: string
- example: DRAFT
- enum:
- - DRAFT
- - APPROVAL_SENT
- - APPROVED
- - SENT
- - SENT_MANUALLY
- - OPENED
- - DENIED
- - SIGNED
- - DEPRECATED
- description: The status of the offer
+ example: '+1234567890'
nullable: true
- application_id:
+ description: The phone number of the location
+ street_1:
type: string
- example: 801f9ede-c698-4e66-a7fc-48d19eebaa4f
- description: The UUID of the application
+ example: 123 Main St
nullable: true
- field_mappings:
- type: object
- example:
- fav_dish: broccoli
- fav_color: red
- description: >-
- The custom field mappings of the object between the remote 3rd party & Panora
+ description: The first line of the street address
+ street_2:
+ type: string
+ example: Suite 456
nullable: true
- additionalProperties: true
- id:
+ description: The second line of the street address
+ city:
type: string
- example: 801f9ede-c698-4e66-a7fc-48d19eebaa4f
- description: The UUID of the offer
+ example: San Francisco
nullable: true
- remote_id:
+ description: The city of the location
+ state:
type: string
- example: id_1
- description: The remote ID of the offer in the context of the 3rd Party
+ example: CA
nullable: true
- remote_data:
- type: object
- example:
- fav_dish: broccoli
- fav_color: red
- description: The remote data of the offer in the context of the 3rd Party
+ description: The state or region of the location
+ zip_code:
+ type: string
+ example: '94105'
nullable: true
- additionalProperties: true
- created_at:
- type: object
- example: '2024-10-01T12:00:00Z'
- description: The created date of the object
+ description: The zip or postal code of the location
+ country:
+ type: string
+ example: USA
nullable: true
- modified_at:
- type: object
- example: '2024-10-01T12:00:00Z'
- description: The modified date of the object
+ description: The country of the location
+ location_type:
+ type: string
+ example: WORK
+ enum:
+ - WORK
+ - HOME
nullable: true
- UnifiedAtsOfficeOutput:
- type: object
- properties:
- name:
+ description: The type of the location
+ company_id:
type: string
- example: Condo Office 5th
+ example: 801f9ede-c698-4e66-a7fc-48d19eebaa4f
nullable: true
- description: The name of the office
- location:
+ description: The UUID of the company associated with the location
+ employee_id:
type: string
- example: New York
+ example: 801f9ede-c698-4e66-a7fc-48d19eebaa4f
nullable: true
- description: The location of the office
+ description: The UUID of the employee associated with the location
field_mappings:
type: object
example:
- fav_dish: broccoli
- fav_color: red
- additionalProperties: true
+ custom_field_1: value1
+ custom_field_2: value2
nullable: true
description: >-
The custom field mappings of the object between the remote 3rd party & Panora
id:
type: string
example: 801f9ede-c698-4e66-a7fc-48d19eebaa4f
- description: The UUID of the office
+ nullable: true
+ description: The UUID of the location record
remote_id:
type: string
- example: id_1
+ example: location_1234
nullable: true
- description: The remote ID of the office in the context of the 3rd Party
+ description: The remote ID of the location in the context of the 3rd Party
remote_data:
type: object
example:
- fav_dish: broccoli
- fav_color: red
+ raw_data:
+ additional_field: some value
nullable: true
- additionalProperties: true
- description: The remote data of the office in the context of the 3rd Party
+ description: The remote data of the location in the context of the 3rd Party
+ remote_created_at:
+ format: date-time
+ type: string
+ example: '2024-10-01T12:00:00Z'
+ nullable: true
+ description: The date when the location was created in the 3rd party system
created_at:
format: date-time
type: string
example: '2024-10-01T12:00:00Z'
nullable: true
- description: The created date of the object
+ description: The created date of the location record
modified_at:
format: date-time
type: string
example: '2024-10-01T12:00:00Z'
nullable: true
- description: The modified date of the object
- UnifiedAtsRejectreasonOutput:
+ description: The last modified date of the location record
+ remote_was_deleted:
+ type: boolean
+ example: false
+ nullable: true
+ description: Indicates if the location was deleted in the remote system
+ UnifiedHrisPaygroupOutput:
type: object
properties:
- name:
+ pay_group_name:
type: string
- example: Candidate inexperienced
+ example: Monthly Salaried
nullable: true
- description: The name of the reject reason
+ description: The name of the pay group
field_mappings:
type: object
example:
- fav_dish: broccoli
- fav_color: red
- additionalProperties: true
+ custom_field_1: value1
+ custom_field_2: value2
nullable: true
description: >-
The custom field mappings of the object between the remote 3rd party & Panora
id:
type: string
- nullable: true
- description: The UUID of the reject reason
example: 801f9ede-c698-4e66-a7fc-48d19eebaa4f
+ nullable: true
+ description: The UUID of the pay group record
remote_id:
type: string
+ example: paygroup_1234
nullable: true
- description: The remote ID of the reject reason in the context of the 3rd Party
- example: id_1
+ description: The remote ID of the pay group in the context of the 3rd Party
remote_data:
type: object
example:
- fav_dish: broccoli
- fav_color: red
+ raw_data:
+ additional_field: some value
nullable: true
- additionalProperties: true
- description: The remote data of the reject reason in the context of the 3rd Party
+ description: The remote data of the pay group in the context of the 3rd Party
+ remote_created_at:
+ format: date-time
+ type: string
+ example: '2024-10-01T12:00:00Z'
+ nullable: true
+ description: The date when the pay group was created in the 3rd party system
created_at:
format: date-time
type: string
example: '2024-10-01T12:00:00Z'
nullable: true
- description: The created date of the object
+ description: The created date of the pay group record
modified_at:
format: date-time
type: string
example: '2024-10-01T12:00:00Z'
nullable: true
- description: The modified date of the object
- UnifiedAtsScorecardOutput:
+ description: The last modified date of the pay group record
+ remote_was_deleted:
+ type: boolean
+ example: false
+ nullable: true
+ description: Indicates if the pay group was deleted in the remote system
+ UnifiedHrisPayrollrunOutput:
type: object
properties:
- overall_recommendation:
+ run_state:
type: string
+ example: PAID
enum:
- - DEFINITELY_NO
- - 'NO'
- - 'YES'
- - STRONG_YES
- - NO_DECISION
- example: 'YES'
+ - PAID
+ - DRAFT
+ - APPROVED
+ - FAILED
+ - CLOSE
nullable: true
- description: The overall recommendation
- application_id:
+ description: The state of the payroll run
+ run_type:
type: string
- example: 801f9ede-c698-4e66-a7fc-48d19eebaa4f
+ example: REGULAR
+ enum:
+ - REGULAR
+ - OFF_CYCLE
+ - CORRECTION
+ - TERMINATION
+ - SIGN_ON_BONUS
nullable: true
- description: The UUID of the application
- interview_id:
+ description: The type of the payroll run
+ start_date:
+ format: date-time
type: string
- example: 801f9ede-c698-4e66-a7fc-48d19eebaa4f
+ example: '2024-01-01T00:00:00Z'
nullable: true
- description: The UUID of the interview
- remote_created_at:
- type: string
- example: '2024-10-01T12:00:00Z'
+ description: The start date of the payroll run
+ end_date:
format: date-time
- nullable: true
- description: The remote creation date of the scorecard
- submitted_at:
type: string
- example: '2024-10-01T12:00:00Z'
+ example: '2024-01-15T23:59:59Z'
+ nullable: true
+ description: The end date of the payroll run
+ check_date:
format: date-time
+ type: string
+ example: '2024-01-20T00:00:00Z'
nullable: true
- description: The submission date of the scorecard
+ description: The check date of the payroll run
field_mappings:
type: object
example:
- fav_dish: broccoli
- fav_color: red
- additionalProperties: true
+ custom_field_1: value1
+ custom_field_2: value2
nullable: true
description: >-
The custom field mappings of the object between the remote 3rd party & Panora
id:
type: string
example: 801f9ede-c698-4e66-a7fc-48d19eebaa4f
- description: The UUID of the scorecard
+ nullable: true
+ description: The UUID of the payroll run record
remote_id:
type: string
- example: id_1
+ example: payroll_run_1234
nullable: true
- description: The remote ID of the scorecard in the context of the 3rd Party
+ description: The remote ID of the payroll run in the context of the 3rd Party
remote_data:
type: object
example:
- fav_dish: broccoli
- fav_color: red
+ raw_data:
+ additional_field: some value
nullable: true
- additionalProperties: true
- description: The remote data of the scorecard in the context of the 3rd Party
+ description: The remote data of the payroll run in the context of the 3rd Party
+ remote_created_at:
+ format: date-time
+ type: string
+ example: '2024-10-01T12:00:00Z'
+ nullable: true
+ description: The date when the payroll run was created in the 3rd party system
created_at:
format: date-time
type: string
example: '2024-10-01T12:00:00Z'
nullable: true
- description: The created date of the object
+ description: The created date of the payroll run record
modified_at:
format: date-time
type: string
example: '2024-10-01T12:00:00Z'
nullable: true
- description: The modified date of the object
- UnifiedAtsTagOutput:
+ description: The last modified date of the payroll run record
+ remote_was_deleted:
+ type: boolean
+ example: false
+ nullable: true
+ description: Indicates if the payroll run was deleted in the remote system
+ employee_payroll_runs:
+ example:
+ - 801f9ede-c698-4e66-a7fc-48d19eebaa4f
+ nullable: true
+ description: >-
+ The UUIDs of the employee payroll runs associated with this payroll run
+ type: array
+ items:
+ type: string
+ UnifiedHrisTimeoffOutput:
type: object
properties:
- name:
+ employee:
type: string
- example: Important
+ example: 801f9ede-c698-4e66-a7fc-48d19eebaa4f
nullable: true
- description: The name of the tag
- id_ats_candidate:
+ description: The UUID of the employee taking time off
+ approver:
type: string
example: 801f9ede-c698-4e66-a7fc-48d19eebaa4f
nullable: true
- description: The UUID of the candidate
+ description: The UUID of the approver for the time off request
+ status:
+ type: string
+ example: REQUESTED
+ enum: &ref_132
+ - REQUESTED
+ - APPROVED
+ - DECLINED
+ - CANCELLED
+ - DELETED
+ nullable: true
+ description: The status of the time off request
+ employee_note:
+ type: string
+ example: Annual vacation
+ nullable: true
+ description: A note from the employee about the time off request
+ units:
+ type: string
+ example: DAYS
+ enum: &ref_133
+ - HOURS
+ - DAYS
+ nullable: true
+ description: The units used for the time off (e.g., Days, Hours)
+ amount:
+ type: number
+ example: 5
+ nullable: true
+ description: The amount of time off requested
+ request_type:
+ type: string
+ example: VACATION
+ enum: &ref_134
+ - VACATION
+ - SICK
+ - PERSONAL
+ - JURY_DUTY
+ - VOLUNTEER
+ - BEREAVEMENT
+ nullable: true
+ description: The type of time off request
+ start_time:
+ format: date-time
+ type: string
+ example: '2024-07-01T09:00:00Z'
+ nullable: true
+ description: The start time of the time off
+ end_time:
+ format: date-time
+ type: string
+ example: '2024-07-05T17:00:00Z'
+ nullable: true
+ description: The end time of the time off
field_mappings:
type: object
- example:
- fav_dish: broccoli
- fav_color: red
- additionalProperties: true
+ example: &ref_135
+ custom_field_1: value1
+ custom_field_2: value2
nullable: true
description: >-
The custom field mappings of the object between the remote 3rd party & Panora
@@ -28706,298 +29344,6716 @@ components:
type: string
example: 801f9ede-c698-4e66-a7fc-48d19eebaa4f
nullable: true
- description: The UUID of the tag
+ description: The UUID of the time off record
remote_id:
type: string
- example: id_1
+ example: timeoff_1234
nullable: true
- description: The remote ID of the tag in the context of the 3rd Party
+ description: The remote ID of the time off in the context of the 3rd Party
remote_data:
type: object
example:
- fav_dish: broccoli
- fav_color: red
+ raw_data:
+ additional_field: some value
nullable: true
- additionalProperties: true
- description: The remote data of the tag in the context of the 3rd Party
+ description: The remote data of the time off in the context of the 3rd Party
+ remote_created_at:
+ format: date-time
+ type: string
+ example: '2024-06-15T12:00:00Z'
+ nullable: true
+ description: The date when the time off was created in the 3rd party system
created_at:
format: date-time
type: string
+ example: '2024-06-15T12:00:00Z'
nullable: true
- example: '2024-10-01T12:00:00Z'
- description: The creation date of the tag
+ description: The created date of the time off record
modified_at:
format: date-time
type: string
+ example: '2024-06-15T12:00:00Z'
nullable: true
- example: '2024-10-01T12:00:00Z'
- description: The modification date of the tag
- UnifiedAtsUserOutput:
+ description: The last modified date of the time off record
+ remote_was_deleted:
+ type: boolean
+ example: false
+ nullable: true
+ description: Indicates if the time off was deleted in the remote system
+ UnifiedHrisTimeoffInput:
type: object
properties:
- first_name:
+ employee:
type: string
- example: John
- description: The first name of the user
+ example: 801f9ede-c698-4e66-a7fc-48d19eebaa4f
nullable: true
- last_name:
+ description: The UUID of the employee taking time off
+ approver:
type: string
- example: Doe
- description: The last name of the user
+ example: 801f9ede-c698-4e66-a7fc-48d19eebaa4f
+ nullable: true
+ description: The UUID of the approver for the time off request
+ status:
+ type: string
+ example: REQUESTED
+ enum: *ref_132
+ nullable: true
+ description: The status of the time off request
+ employee_note:
+ type: string
+ example: Annual vacation
+ nullable: true
+ description: A note from the employee about the time off request
+ units:
+ type: string
+ example: DAYS
+ enum: *ref_133
+ nullable: true
+ description: The units used for the time off (e.g., Days, Hours)
+ amount:
+ type: number
+ example: 5
+ nullable: true
+ description: The amount of time off requested
+ request_type:
+ type: string
+ example: VACATION
+ enum: *ref_134
+ nullable: true
+ description: The type of time off request
+ start_time:
+ format: date-time
+ type: string
+ example: '2024-07-01T09:00:00Z'
+ nullable: true
+ description: The start time of the time off
+ end_time:
+ format: date-time
+ type: string
+ example: '2024-07-05T17:00:00Z'
+ nullable: true
+ description: The end time of the time off
+ field_mappings:
+ type: object
+ example: *ref_135
+ nullable: true
+ description: >-
+ The custom field mappings of the object between the remote 3rd party & Panora
+ UnifiedHrisTimeoffbalanceOutput:
+ type: object
+ properties:
+ balance:
+ type: number
+ example: 80
+ nullable: true
+ description: The current balance of time off
+ employee_id:
+ type: string
+ example: 801f9ede-c698-4e66-a7fc-48d19eebaa4f
+ nullable: true
+ description: The UUID of the associated employee
+ used:
+ type: number
+ example: 40
+ nullable: true
+ description: The amount of time off used
+ policy_type:
+ type: string
+ example: VACATION
+ enum:
+ - VACATION
+ - SICK
+ - PERSONAL
+ - JURY_DUTY
+ - VOLUNTEER
+ - BEREAVEMENT
+ nullable: true
+ description: The type of time off policy
+ field_mappings:
+ type: object
+ example:
+ custom_field_1: value1
+ custom_field_2: value2
+ nullable: true
+ description: >-
+ The custom field mappings of the object between the remote 3rd party & Panora
+ id:
+ type: string
+ example: 801f9ede-c698-4e66-a7fc-48d19eebaa4f
+ nullable: true
+ description: The UUID of the time off balance record
+ remote_id:
+ type: string
+ example: timeoff_balance_1234
+ nullable: true
+ description: >-
+ The remote ID of the time off balance in the context of the 3rd Party
+ remote_data:
+ type: object
+ example:
+ raw_data:
+ additional_field: some value
+ nullable: true
+ description: >-
+ The remote data of the time off balance in the context of the 3rd Party
+ remote_created_at:
+ type: string
+ example: '2024-06-15T12:00:00Z'
+ nullable: true
+ description: >-
+ The date when the time off balance was created in the 3rd party system
+ created_at:
+ type: string
+ example: '2024-06-15T12:00:00Z'
+ nullable: true
+ description: The created date of the time off balance record
+ modified_at:
+ type: string
+ example: '2024-06-15T12:00:00Z'
+ nullable: true
+ description: The last modified date of the time off balance record
+ remote_was_deleted:
+ type: boolean
+ example: false
+ nullable: true
+ description: Indicates if the time off balance was deleted in the remote system
+ UnifiedHrisTimesheetEntryOutput:
+ type: object
+ properties:
+ hours_worked:
+ type: number
+ example: 40
+ nullable: true
+ description: The number of hours worked
+ start_time:
+ format: date-time
+ type: string
+ example: '2024-10-01T08:00:00Z'
+ nullable: true
+ description: The start time of the timesheet entry
+ end_time:
+ format: date-time
+ type: string
+ example: '2024-10-01T16:00:00Z'
+ nullable: true
+ description: The end time of the timesheet entry
+ employee_id:
+ type: string
+ example: 801f9ede-c698-4e66-a7fc-48d19eebaa4f
+ nullable: true
+ description: The UUID of the associated employee
+ remote_was_deleted:
+ type: boolean
+ example: false
+ description: Indicates if the timesheet entry was deleted in the remote system
+ field_mappings:
+ type: object
+ example: &ref_136
+ custom_field_1: value1
+ custom_field_2: value2
+ nullable: true
+ description: >-
+ The custom field mappings of the object between the remote 3rd party & Panora
+ id:
+ type: string
+ example: 801f9ede-c698-4e66-a7fc-48d19eebaa4f
+ nullable: true
+ description: The UUID of the timesheet entry record
+ remote_id:
+ type: string
+ example: id_1
+ nullable: true
+ description: The remote ID of the timesheet entry
+ remote_created_at:
+ format: date-time
+ type: string
+ example: '2024-10-01T12:00:00Z'
+ nullable: true
+ description: The date when the timesheet entry was created in the remote system
+ created_at:
+ format: date-time
+ type: string
+ example: '2024-10-01T12:00:00Z'
+ description: The created date of the timesheet entry
+ modified_at:
+ format: date-time
+ type: string
+ example: '2024-10-01T12:00:00Z'
+ description: The last modified date of the timesheet entry
+ remote_data:
+ type: object
+ example:
+ raw_data:
+ additional_field: some value
+ nullable: true
+ description: >-
+ The remote data of the timesheet entry in the context of the 3rd Party
+ UnifiedHrisTimesheetEntryInput:
+ type: object
+ properties:
+ hours_worked:
+ type: number
+ example: 40
+ nullable: true
+ description: The number of hours worked
+ start_time:
+ format: date-time
+ type: string
+ example: '2024-10-01T08:00:00Z'
+ nullable: true
+ description: The start time of the timesheet entry
+ end_time:
+ format: date-time
+ type: string
+ example: '2024-10-01T16:00:00Z'
+ nullable: true
+ description: The end time of the timesheet entry
+ employee_id:
+ type: string
+ example: 801f9ede-c698-4e66-a7fc-48d19eebaa4f
+ nullable: true
+ description: The UUID of the associated employee
+ remote_was_deleted:
+ type: boolean
+ example: false
+ description: Indicates if the timesheet entry was deleted in the remote system
+ field_mappings:
+ type: object
+ example: *ref_136
+ nullable: true
+ description: >-
+ The custom field mappings of the object between the remote 3rd party & Panora
+ UnifiedMarketingautomationActionOutput:
+ type: object
+ properties: {}
+ UnifiedMarketingautomationActionInput:
+ type: object
+ properties: {}
+ UnifiedMarketingautomationAutomationOutput:
+ type: object
+ properties: {}
+ UnifiedMarketingautomationAutomationInput:
+ type: object
+ properties: {}
+ UnifiedMarketingautomationCampaignOutput:
+ type: object
+ properties: {}
+ UnifiedMarketingautomationCampaignInput:
+ type: object
+ properties: {}
+ UnifiedMarketingautomationContactOutput:
+ type: object
+ properties: {}
+ UnifiedMarketingautomationContactInput:
+ type: object
+ properties: {}
+ UnifiedMarketingautomationEmailOutput:
+ type: object
+ properties: {}
+ UnifiedMarketingautomationEventOutput:
+ type: object
+ properties: {}
+ UnifiedMarketingautomationListOutput:
+ type: object
+ properties: {}
+ UnifiedMarketingautomationListInput:
+ type: object
+ properties: {}
+ UnifiedMarketingautomationMessageOutput:
+ type: object
+ properties: {}
+ UnifiedMarketingautomationTemplateOutput:
+ type: object
+ properties: {}
+ UnifiedMarketingautomationTemplateInput:
+ type: object
+ properties: {}
+ UnifiedMarketingautomationUserOutput:
+ type: object
+ properties: {}
+ UnifiedAtsActivityOutput:
+ type: object
+ properties:
+ activity_type:
+ type: string
+ enum: &ref_137
+ - NOTE
+ - EMAIL
+ - OTHER
+ example: NOTE
+ nullable: true
+ description: The type of activity
+ subject:
+ type: string
+ example: Email subject
+ nullable: true
+ description: The subject of the activity
+ body:
+ type: string
+ example: Dear Diana, I love you
+ nullable: true
+ description: The body of the activity
+ visibility:
+ type: string
+ enum: &ref_138
+ - ADMIN_ONLY
+ - PUBLIC
+ - PRIVATE
+ example: PUBLIC
+ nullable: true
+ description: The visibility of the activity
+ candidate_id:
+ type: string
+ example: 801f9ede-c698-4e66-a7fc-48d19eebaa4f
+ nullable: true
+ description: The UUID of the candidate
+ remote_created_at:
+ type: string
+ format: date-time
+ example: '2024-10-01T12:00:00Z'
+ nullable: true
+ description: The remote creation date of the activity
+ field_mappings:
+ type: object
+ example: &ref_139
+ fav_dish: broccoli
+ fav_color: red
+ additionalProperties: true
+ nullable: true
+ description: >-
+ The custom field mappings of the object between the remote 3rd party & Panora
+ id:
+ type: string
+ example: 801f9ede-c698-4e66-a7fc-48d19eebaa4f
+ nullable: true
+ description: The UUID of the activity
+ remote_id:
+ type: string
+ example: id_1
+ nullable: true
+ description: The remote ID of the activity in the context of the 3rd Party
+ remote_data:
+ type: object
+ example:
+ fav_dish: broccoli
+ fav_color: red
+ nullable: true
+ additionalProperties: true
+ description: The remote data of the activity in the context of the 3rd Party
+ created_at:
+ format: date-time
+ type: string
+ example: '2024-10-01T12:00:00Z'
+ nullable: true
+ description: The created date of the object
+ modified_at:
+ format: date-time
+ type: string
+ example: '2024-10-01T12:00:00Z'
+ nullable: true
+ description: The modified date of the object
+ UnifiedAtsActivityInput:
+ type: object
+ properties:
+ activity_type:
+ type: string
+ enum: *ref_137
+ example: NOTE
+ nullable: true
+ description: The type of activity
+ subject:
+ type: string
+ example: Email subject
+ nullable: true
+ description: The subject of the activity
+ body:
+ type: string
+ example: Dear Diana, I love you
+ nullable: true
+ description: The body of the activity
+ visibility:
+ type: string
+ enum: *ref_138
+ example: PUBLIC
+ nullable: true
+ description: The visibility of the activity
+ candidate_id:
+ type: string
+ example: 801f9ede-c698-4e66-a7fc-48d19eebaa4f
+ nullable: true
+ description: The UUID of the candidate
+ remote_created_at:
+ type: string
+ format: date-time
+ example: '2024-10-01T12:00:00Z'
+ nullable: true
+ description: The remote creation date of the activity
+ field_mappings:
+ type: object
+ example: *ref_139
+ additionalProperties: true
+ nullable: true
+ description: >-
+ The custom field mappings of the object between the remote 3rd party & Panora
+ UnifiedAtsApplicationOutput:
+ type: object
+ properties:
+ applied_at:
+ format: date-time
+ type: string
+ nullable: true
+ description: The application date
+ example: '2024-10-01T12:00:00Z'
+ rejected_at:
+ format: date-time
+ type: string
+ nullable: true
+ description: The rejection date
+ example: '2024-10-01T12:00:00Z'
+ offers:
+ nullable: true
+ description: The offers UUIDs for the application
+ example: &ref_140
+ - 801f9ede-c698-4e66-a7fc-48d19eebaa4f
+ - 12345678-1234-1234-1234-123456789012
+ type: array
+ items:
+ type: string
+ source:
+ type: string
+ nullable: true
+ description: The source of the application
+ example: Source Name
+ credited_to:
+ type: string
+ nullable: true
+ description: The UUID of the person credited for the application
+ example: 801f9ede-c698-4e66-a7fc-48d19eebaa4f
+ current_stage:
+ type: string
+ nullable: true
+ description: The UUID of the current stage of the application
+ example: 801f9ede-c698-4e66-a7fc-48d19eebaa4f
+ reject_reason:
+ type: string
+ nullable: true
+ description: The rejection reason for the application
+ example: Candidate not experienced enough
+ candidate_id:
+ type: string
+ nullable: true
+ description: The UUID of the candidate
+ example: 801f9ede-c698-4e66-a7fc-48d19eebaa4f
+ job_id:
+ type: string
+ description: The UUID of the job
+ example: 801f9ede-c698-4e66-a7fc-48d19eebaa4f
+ field_mappings:
+ type: object
+ example: &ref_141
+ fav_dish: broccoli
+ fav_color: red
+ additionalProperties: true
+ nullable: true
+ description: >-
+ The custom field mappings of the object between the remote 3rd party & Panora
+ id:
+ type: string
+ nullable: true
+ description: The UUID of the application
+ example: 801f9ede-c698-4e66-a7fc-48d19eebaa4f
+ remote_id:
+ type: string
+ nullable: true
+ description: The remote ID of the application in the context of the 3rd Party
+ example: id_1
+ remote_data:
+ type: object
+ example:
+ fav_dish: broccoli
+ fav_color: red
+ nullable: true
+ additionalProperties: true
+ description: The remote data of the application in the context of the 3rd Party
+ created_at:
+ format: date-time
+ type: string
+ example: '2024-10-01T12:00:00Z'
+ nullable: true
+ description: The created date of the object
+ modified_at:
+ format: date-time
+ type: string
+ example: '2024-10-01T12:00:00Z'
+ nullable: true
+ description: The modified date of the object
+ remote_created_at:
+ format: date-time
+ type: string
+ nullable: true
+ description: The remote created date of the object
+ remote_modified_at:
+ format: date-time
+ type: string
+ nullable: true
+ description: The remote modified date of the object
+ UnifiedAtsApplicationInput:
+ type: object
+ properties:
+ applied_at:
+ format: date-time
+ type: string
+ nullable: true
+ description: The application date
+ example: '2024-10-01T12:00:00Z'
+ rejected_at:
+ format: date-time
+ type: string
+ nullable: true
+ description: The rejection date
+ example: '2024-10-01T12:00:00Z'
+ offers:
+ nullable: true
+ description: The offers UUIDs for the application
+ example: *ref_140
+ type: array
+ items:
+ type: string
+ source:
+ type: string
+ nullable: true
+ description: The source of the application
+ example: Source Name
+ credited_to:
+ type: string
+ nullable: true
+ description: The UUID of the person credited for the application
+ example: 801f9ede-c698-4e66-a7fc-48d19eebaa4f
+ current_stage:
+ type: string
+ nullable: true
+ description: The UUID of the current stage of the application
+ example: 801f9ede-c698-4e66-a7fc-48d19eebaa4f
+ reject_reason:
+ type: string
+ nullable: true
+ description: The rejection reason for the application
+ example: Candidate not experienced enough
+ candidate_id:
+ type: string
+ nullable: true
+ description: The UUID of the candidate
+ example: 801f9ede-c698-4e66-a7fc-48d19eebaa4f
+ job_id:
+ type: string
+ description: The UUID of the job
+ example: 801f9ede-c698-4e66-a7fc-48d19eebaa4f
+ field_mappings:
+ type: object
+ example: *ref_141
+ additionalProperties: true
+ nullable: true
+ description: >-
+ The custom field mappings of the object between the remote 3rd party & Panora
+ UnifiedAtsAttachmentOutput:
+ type: object
+ properties:
+ file_url:
+ type: string
+ example: https://example.com/file.pdf
+ nullable: true
+ description: The URL of the file
+ file_name:
+ type: string
+ example: file.pdf
+ nullable: true
+ description: The name of the file
+ attachment_type:
+ type: string
+ example: RESUME
+ enum: &ref_142
+ - RESUME
+ - COVER_LETTER
+ - OFFER_LETTER
+ - OTHER
+ nullable: true
+ description: The type of the file
+ remote_created_at:
+ type: string
+ example: '2024-10-01T12:00:00Z'
+ format: date-time
+ nullable: true
+ description: The remote creation date of the attachment
+ remote_modified_at:
+ type: string
+ example: '2024-10-01T12:00:00Z'
+ format: date-time
+ nullable: true
+ description: The remote modification date of the attachment
+ candidate_id:
+ type: string
+ example: 801f9ede-c698-4e66-a7fc-48d19eebaa4f
+ nullable: true
+ description: The UUID of the candidate
+ field_mappings:
+ type: object
+ example: &ref_143
+ fav_dish: broccoli
+ fav_color: red
+ additionalProperties: true
+ nullable: true
+ description: >-
+ The custom field mappings of the object between the remote 3rd party & Panora
+ id:
+ type: string
+ example: 801f9ede-c698-4e66-a7fc-48d19eebaa4f
+ nullable: true
+ description: The UUID of the attachment
+ remote_id:
+ type: string
+ example: 801f9ede-c698-4e66-a7fc-48d19eebaa4f
+ nullable: true
+ description: The remote ID of the attachment
+ remote_data:
+ type: object
+ example:
+ fav_dish: broccoli
+ fav_color: red
+ nullable: true
+ additionalProperties: true
+ description: The remote data of the attachment in the context of the 3rd Party
+ created_at:
+ format: date-time
+ type: string
+ example: '2024-10-01T12:00:00Z'
+ nullable: true
+ description: The created date of the object
+ modified_at:
+ format: date-time
+ type: string
+ example: '2024-10-01T12:00:00Z'
+ nullable: true
+ description: The modified date of the object
+ UnifiedAtsAttachmentInput:
+ type: object
+ properties:
+ file_url:
+ type: string
+ example: https://example.com/file.pdf
+ nullable: true
+ description: The URL of the file
+ file_name:
+ type: string
+ example: file.pdf
+ nullable: true
+ description: The name of the file
+ attachment_type:
+ type: string
+ example: RESUME
+ enum: *ref_142
+ nullable: true
+ description: The type of the file
+ remote_created_at:
+ type: string
+ example: '2024-10-01T12:00:00Z'
+ format: date-time
+ nullable: true
+ description: The remote creation date of the attachment
+ remote_modified_at:
+ type: string
+ example: '2024-10-01T12:00:00Z'
+ format: date-time
+ nullable: true
+ description: The remote modification date of the attachment
+ candidate_id:
+ type: string
+ example: 801f9ede-c698-4e66-a7fc-48d19eebaa4f
+ nullable: true
+ description: The UUID of the candidate
+ field_mappings:
+ type: object
+ example: *ref_143
+ additionalProperties: true
+ nullable: true
+ description: >-
+ The custom field mappings of the object between the remote 3rd party & Panora
+ Url:
+ type: object
+ properties:
+ url:
+ type: string
+ nullable: true
+ description: The url.
+ url_type:
+ type: string
+ nullable: true
+ description: The url type. It takes [WEBSITE | BLOG | LINKEDIN | GITHUB | OTHER]
+ required:
+ - url
+ - url_type
+ UnifiedAtsCandidateOutput:
+ type: object
+ properties:
+ first_name:
+ type: string
+ example: Joe
+ nullable: true
+ description: The first name of the candidate
+ last_name:
+ type: string
+ example: Doe
+ nullable: true
+ description: The last name of the candidate
+ company:
+ type: string
+ example: Acme
+ nullable: true
+ description: The company of the candidate
+ title:
+ type: string
+ example: Analyst
+ nullable: true
+ description: The title of the candidate
+ locations:
+ type: string
+ example: New York
+ nullable: true
+ description: The locations of the candidate
+ is_private:
+ type: boolean
+ example: false
+ nullable: true
+ description: Whether the candidate is private
+ email_reachable:
+ type: boolean
+ example: true
+ nullable: true
+ description: Whether the candidate is reachable by email
+ remote_created_at:
+ type: string
+ example: '2024-10-01T12:00:00Z'
+ format: date-time
+ nullable: true
+ description: The remote creation date of the candidate
+ remote_modified_at:
+ type: string
+ example: '2024-10-01T12:00:00Z'
+ format: date-time
+ nullable: true
+ description: The remote modification date of the candidate
+ last_interaction_at:
+ type: string
+ example: '2024-10-01T12:00:00Z'
+ format: date-time
+ nullable: true
+ description: The last interaction date with the candidate
+ attachments:
+ type: array
+ items: &ref_144
+ oneOf:
+ - type: string
+ - $ref: '#/components/schemas/UnifiedAtsAttachmentOutput'
+ example: &ref_145
+ - 801f9ede-c698-4e66-a7fc-48d19eebaa4f
+ nullable: true
+ description: The attachments UUIDs of the candidate
+ applications:
+ type: array
+ items: &ref_146
+ oneOf:
+ - type: string
+ - $ref: '#/components/schemas/UnifiedAtsApplicationOutput'
+ example: &ref_147
+ - 801f9ede-c698-4e66-a7fc-48d19eebaa4f
+ nullable: true
+ description: The applications UUIDs of the candidate
+ tags:
+ type: array
+ items: &ref_148
+ oneOf:
+ - type: string
+ - $ref: '#/components/schemas/UnifiedAtsTagOutput'
+ example: &ref_149
+ - tag_1
+ - tag_2
+ nullable: true
+ description: The tags of the candidate
+ urls:
+ example: &ref_150
+ - url: mywebsite.com
+ url_type: WEBSITE
+ nullable: true
+ description: >-
+ The urls of the candidate, possible values for Url type are WEBSITE, BLOG, LINKEDIN, GITHUB, or OTHER
+ type: array
+ items:
+ $ref: '#/components/schemas/Url'
+ phone_numbers:
+ example: &ref_151
+ - phone_number: '+33660688899'
+ phone_type: WORK
+ nullable: true
+ description: The phone numbers of the candidate
+ type: array
+ items:
+ $ref: '#/components/schemas/Phone'
+ email_addresses:
+ example: &ref_152
+ - email_address: joedoe@gmail.com
+ email_address_type: WORK
+ nullable: true
+ description: The email addresses of the candidate
+ type: array
+ items:
+ $ref: '#/components/schemas/Email'
+ field_mappings:
+ type: object
+ example: &ref_153
+ fav_dish: broccoli
+ fav_color: red
+ additionalProperties: true
+ nullable: true
+ description: >-
+ The custom field mappings of the object between the remote 3rd party & Panora
+ id:
+ type: string
+ example: 801f9ede-c698-4e66-a7fc-48d19eebaa4f
+ nullable: true
+ description: The UUID of the candidate
+ remote_id:
+ type: string
+ example: id_1
+ nullable: true
+ description: The id of the candidate in the context of the 3rd Party
+ remote_data:
+ type: object
+ example:
+ fav_dish: broccoli
+ fav_color: red
+ nullable: true
+ additionalProperties: true
+ description: The remote data of the candidate in the context of the 3rd Party
+ created_at:
+ format: date-time
+ type: string
+ example: '2024-10-01T12:00:00Z'
+ nullable: true
+ description: The created date of the object
+ modified_at:
+ format: date-time
+ type: string
+ example: '2024-10-01T12:00:00Z'
+ nullable: true
+ description: The modified date of the object
+ UnifiedAtsCandidateInput:
+ type: object
+ properties:
+ first_name:
+ type: string
+ example: Joe
+ nullable: true
+ description: The first name of the candidate
+ last_name:
+ type: string
+ example: Doe
+ nullable: true
+ description: The last name of the candidate
+ company:
+ type: string
+ example: Acme
+ nullable: true
+ description: The company of the candidate
+ title:
+ type: string
+ example: Analyst
+ nullable: true
+ description: The title of the candidate
+ locations:
+ type: string
+ example: New York
+ nullable: true
+ description: The locations of the candidate
+ is_private:
+ type: boolean
+ example: false
+ nullable: true
+ description: Whether the candidate is private
+ email_reachable:
+ type: boolean
+ example: true
+ nullable: true
+ description: Whether the candidate is reachable by email
+ remote_created_at:
+ type: string
+ example: '2024-10-01T12:00:00Z'
+ format: date-time
+ nullable: true
+ description: The remote creation date of the candidate
+ remote_modified_at:
+ type: string
+ example: '2024-10-01T12:00:00Z'
+ format: date-time
+ nullable: true
+ description: The remote modification date of the candidate
+ last_interaction_at:
+ type: string
+ example: '2024-10-01T12:00:00Z'
+ format: date-time
+ nullable: true
+ description: The last interaction date with the candidate
+ attachments:
+ type: array
+ items: *ref_144
+ example: *ref_145
+ nullable: true
+ description: The attachments UUIDs of the candidate
+ applications:
+ type: array
+ items: *ref_146
+ example: *ref_147
+ nullable: true
+ description: The applications UUIDs of the candidate
+ tags:
+ type: array
+ items: *ref_148
+ example: *ref_149
+ nullable: true
+ description: The tags of the candidate
+ urls:
+ example: *ref_150
+ nullable: true
+ description: >-
+ The urls of the candidate, possible values for Url type are WEBSITE, BLOG, LINKEDIN, GITHUB, or OTHER
+ type: array
+ items:
+ $ref: '#/components/schemas/Url'
+ phone_numbers:
+ example: *ref_151
+ nullable: true
+ description: The phone numbers of the candidate
+ type: array
+ items:
+ $ref: '#/components/schemas/Phone'
+ email_addresses:
+ example: *ref_152
+ nullable: true
+ description: The email addresses of the candidate
+ type: array
+ items:
+ $ref: '#/components/schemas/Email'
+ field_mappings:
+ type: object
+ example: *ref_153
+ additionalProperties: true
+ nullable: true
+ description: >-
+ The custom field mappings of the object between the remote 3rd party & Panora
+ UnifiedAtsDepartmentOutput:
+ type: object
+ properties:
+ name:
+ type: string
+ example: Sales
+ nullable: true
+ description: The name of the department
+ field_mappings:
+ type: object
+ example:
+ fav_dish: broccoli
+ fav_color: red
+ additionalProperties: true
+ nullable: true
+ description: >-
+ The custom field mappings of the object between the remote 3rd party & Panora
+ id:
+ type: string
+ example: 801f9ede-c698-4e66-a7fc-48d19eebaa4f
+ nullable: true
+ description: The UUID of the department
+ remote_id:
+ type: string
+ example: id_1
+ nullable: true
+ description: The remote ID of the department in the context of the 3rd Party
+ remote_data:
+ type: object
+ example:
+ key1: value1
+ key2: 42
+ key3: true
+ nullable: true
+ additionalProperties: true
+ description: The remote data of the department in the context of the 3rd Party
+ created_at:
+ format: date-time
+ type: string
+ example: '2024-10-01T12:00:00Z'
+ nullable: true
+ description: The created date of the object
+ modified_at:
+ format: date-time
+ type: string
+ example: '2023-10-01T12:00:00Z'
+ nullable: true
+ description: The modified date of the object
+ UnifiedAtsInterviewOutput:
+ type: object
+ properties:
+ status:
+ type: string
+ enum: &ref_154
+ - SCHEDULED
+ - AWAITING_FEEDBACK
+ - COMPLETED
+ example: SCHEDULED
+ nullable: true
+ description: The status of the interview
+ application_id:
+ type: string
+ example: 801f9ede-c698-4e66-a7fc-48d19eebaa4f
+ nullable: true
+ description: The UUID of the application
+ job_interview_stage_id:
+ type: string
+ example: 801f9ede-c698-4e66-a7fc-48d19eebaa4f
+ nullable: true
+ description: The UUID of the job interview stage
+ organized_by:
+ type: string
+ example: 801f9ede-c698-4e66-a7fc-48d19eebaa4f
+ nullable: true
+ description: The UUID of the organizer
+ interviewers:
+ example: &ref_155
+ - 801f9ede-c698-4e66-a7fc-48d19eebaa4f
+ nullable: true
+ description: The UUIDs of the interviewers
+ type: array
+ items:
+ type: string
+ location:
+ type: string
+ example: San Francisco
+ nullable: true
+ description: The location of the interview
+ start_at:
+ format: date-time
+ type: string
+ example: '2024-10-01T12:00:00Z'
+ nullable: true
+ description: The start date and time of the interview
+ end_at:
+ format: date-time
+ type: string
+ example: '2024-10-01T12:00:00Z'
+ nullable: true
+ description: The end date and time of the interview
+ remote_created_at:
+ format: date-time
+ type: string
+ example: '2024-10-01T12:00:00Z'
+ nullable: true
+ description: The remote creation date of the interview
+ remote_updated_at:
+ format: date-time
+ type: string
+ example: '2024-10-01T12:00:00Z'
+ nullable: true
+ description: The remote modification date of the interview
+ field_mappings:
+ type: object
+ example: &ref_156
+ fav_dish: broccoli
+ fav_color: red
+ additionalProperties: true
+ nullable: true
+ description: >-
+ The custom field mappings of the object between the remote 3rd party & Panora
+ id:
+ type: string
+ example: 801f9ede-c698-4e66-a7fc-48d19eebaa4f
+ nullable: true
+ description: The UUID of the interview
+ remote_id:
+ type: string
+ example: id_1
+ nullable: true
+ description: The remote ID of the interview in the context of the 3rd Party
+ remote_data:
+ type: object
+ example:
+ fav_dish: broccoli
+ fav_color: red
+ nullable: true
+ additionalProperties: true
+ description: The remote data of the interview in the context of the 3rd Party
+ created_at:
+ format: date-time
+ type: string
+ example: '2024-10-01T12:00:00Z'
+ nullable: true
+ description: The created date of the object
+ modified_at:
+ format: date-time
+ type: string
+ example: '2024-10-01T12:00:00Z'
+ nullable: true
+ description: The modified date of the object
+ UnifiedAtsInterviewInput:
+ type: object
+ properties:
+ status:
+ type: string
+ enum: *ref_154
+ example: SCHEDULED
+ nullable: true
+ description: The status of the interview
+ application_id:
+ type: string
+ example: 801f9ede-c698-4e66-a7fc-48d19eebaa4f
+ nullable: true
+ description: The UUID of the application
+ job_interview_stage_id:
+ type: string
+ example: 801f9ede-c698-4e66-a7fc-48d19eebaa4f
+ nullable: true
+ description: The UUID of the job interview stage
+ organized_by:
+ type: string
+ example: 801f9ede-c698-4e66-a7fc-48d19eebaa4f
+ nullable: true
+ description: The UUID of the organizer
+ interviewers:
+ example: *ref_155
+ nullable: true
+ description: The UUIDs of the interviewers
+ type: array
+ items:
+ type: string
+ location:
+ type: string
+ example: San Francisco
+ nullable: true
+ description: The location of the interview
+ start_at:
+ format: date-time
+ type: string
+ example: '2024-10-01T12:00:00Z'
+ nullable: true
+ description: The start date and time of the interview
+ end_at:
+ format: date-time
+ type: string
+ example: '2024-10-01T12:00:00Z'
+ nullable: true
+ description: The end date and time of the interview
+ remote_created_at:
+ format: date-time
+ type: string
+ example: '2024-10-01T12:00:00Z'
+ nullable: true
+ description: The remote creation date of the interview
+ remote_updated_at:
+ format: date-time
+ type: string
+ example: '2024-10-01T12:00:00Z'
+ nullable: true
+ description: The remote modification date of the interview
+ field_mappings:
+ type: object
+ example: *ref_156
+ additionalProperties: true
+ nullable: true
+ description: >-
+ The custom field mappings of the object between the remote 3rd party & Panora
+ UnifiedAtsJobinterviewstageOutput:
+ type: object
+ properties:
+ name:
+ type: string
+ example: Second Call
+ nullable: true
+ description: The name of the job interview stage
+ stage_order:
+ type: number
+ example: 1
+ nullable: true
+ description: The order of the stage
+ job_id:
+ type: string
+ example: 801f9ede-c698-4e66-a7fc-48d19eebaa4f
+ nullable: true
+ description: The UUID of the job
+ field_mappings:
+ type: object
+ example:
+ fav_dish: broccoli
+ fav_color: red
+ additionalProperties: true
+ nullable: true
+ description: >-
+ The custom field mappings of the object between the remote 3rd party & Panora
+ id:
+ type: string
+ example: 801f9ede-c698-4e66-a7fc-48d19eebaa4f
+ nullable: true
+ description: The UUID of the job interview stage
+ remote_id:
+ type: string
+ example: id_1
+ nullable: true
+ description: >-
+ The remote ID of the job interview stage in the context of the 3rd Party
+ remote_data:
+ type: object
+ example:
+ fav_dish: broccoli
+ fav_color: red
+ nullable: true
+ additionalProperties: true
+ description: >-
+ The remote data of the job interview stage in the context of the 3rd Party
+ created_at:
+ format: date-time
+ type: string
+ example: '2024-10-01T12:00:00Z'
+ nullable: true
+ description: The created date of the object
+ modified_at:
+ format: date-time
+ type: string
+ example: '2024-10-01T12:00:00Z'
+ nullable: true
+ description: The modified date of the object
+ UnifiedAtsJobOutput:
+ type: object
+ properties:
+ name:
+ type: string
+ example: Financial Analyst
+ nullable: true
+ description: The name of the job
+ description:
+ type: string
+ example: Extract financial data and write detailed investment thesis
+ nullable: true
+ description: The description of the job
+ code:
+ type: string
+ example: JOB123
+ nullable: true
+ description: The code of the job
+ status:
+ type: string
+ enum:
+ - OPEN
+ - CLOSED
+ - DRAFT
+ - ARCHIVED
+ - PENDING
+ example: OPEN
+ nullable: true
+ description: The status of the job
+ type:
+ type: string
+ example: POSTING
+ enum:
+ - POSTING
+ - REQUISITION
+ - PROFILE
+ nullable: true
+ description: The type of the job
+ confidential:
+ type: boolean
+ example: true
+ nullable: true
+ description: Whether the job is confidential
+ departments:
+ example:
+ - 801f9ede-c698-4e66-a7fc-48d19eebaa4f
+ nullable: true
+ description: The departments UUIDs associated with the job
+ type: array
+ items:
+ type: string
+ offices:
+ example:
+ - 801f9ede-c698-4e66-a7fc-48d19eebaa4f
+ nullable: true
+ description: The offices UUIDs associated with the job
+ type: array
+ items:
+ type: string
+ managers:
+ example:
+ - 801f9ede-c698-4e66-a7fc-48d19eebaa4f
+ nullable: true
+ description: The managers UUIDs associated with the job
+ type: array
+ items:
+ type: string
+ recruiters:
+ example:
+ - 801f9ede-c698-4e66-a7fc-48d19eebaa4f
+ nullable: true
+ description: The recruiters UUIDs associated with the job
+ type: array
+ items:
+ type: string
+ remote_created_at:
+ type: string
+ example: '2024-10-01T12:00:00Z'
+ format: date-time
+ nullable: true
+ description: The remote creation date of the job
+ remote_updated_at:
+ type: string
+ example: '2024-10-01T12:00:00Z'
+ format: date-time
+ nullable: true
+ description: The remote modification date of the job
+ field_mappings:
+ type: object
+ example:
+ fav_dish: broccoli
+ fav_color: red
+ additionalProperties: true
+ nullable: true
+ description: >-
+ The custom field mappings of the object between the remote 3rd party & Panora
+ id:
+ type: string
+ example: 801f9ede-c698-4e66-a7fc-48d19eebaa4f
+ nullable: true
+ description: The UUID of the job
+ remote_id:
+ type: string
+ example: id_1
+ nullable: true
+ description: The remote ID of the job in the context of the 3rd Party
+ remote_data:
+ type: object
+ example:
+ key1: value1
+ key2: 42
+ key3: true
+ nullable: true
+ additionalProperties: true
+ description: The remote data of the job in the context of the 3rd Party
+ created_at:
+ format: date-time
+ type: string
+ example: '2024-10-01T12:00:00Z'
+ nullable: true
+ description: The created date of the object
+ modified_at:
+ format: date-time
+ type: string
+ example: '2023-10-01T12:00:00Z'
+ nullable: true
+ description: The modified date of the object
+ UnifiedAtsOfferOutput:
+ type: object
+ properties:
+ created_by:
+ type: string
+ example: 801f9ede-c698-4e66-a7fc-48d19eebaa4f
+ description: The UUID of the creator
+ nullable: true
+ remote_created_at:
+ format: date-time
+ type: string
+ example: '2024-10-01T12:00:00Z'
+ description: The remote creation date of the offer
+ nullable: true
+ closed_at:
+ format: date-time
+ type: string
+ example: '2024-10-01T12:00:00Z'
+ description: The closing date of the offer
+ nullable: true
+ sent_at:
+ format: date-time
+ type: string
+ example: '2024-10-01T12:00:00Z'
+ description: The sending date of the offer
+ nullable: true
+ start_date:
+ format: date-time
+ type: string
+ example: '2024-10-01T12:00:00Z'
+ description: The start date of the offer
+ nullable: true
+ status:
+ type: string
+ example: DRAFT
+ enum:
+ - DRAFT
+ - APPROVAL_SENT
+ - APPROVED
+ - SENT
+ - SENT_MANUALLY
+ - OPENED
+ - DENIED
+ - SIGNED
+ - DEPRECATED
+ description: The status of the offer
+ nullable: true
+ application_id:
+ type: string
+ example: 801f9ede-c698-4e66-a7fc-48d19eebaa4f
+ description: The UUID of the application
+ nullable: true
+ field_mappings:
+ type: object
+ example:
+ fav_dish: broccoli
+ fav_color: red
+ description: >-
+ The custom field mappings of the object between the remote 3rd party & Panora
+ nullable: true
+ additionalProperties: true
+ id:
+ type: string
+ example: 801f9ede-c698-4e66-a7fc-48d19eebaa4f
+ description: The UUID of the offer
+ nullable: true
+ remote_id:
+ type: string
+ example: id_1
+ description: The remote ID of the offer in the context of the 3rd Party
+ nullable: true
+ remote_data:
+ type: object
+ example:
+ fav_dish: broccoli
+ fav_color: red
+ description: The remote data of the offer in the context of the 3rd Party
+ nullable: true
+ additionalProperties: true
+ created_at:
+ type: object
+ example: '2024-10-01T12:00:00Z'
+ description: The created date of the object
+ nullable: true
+ modified_at:
+ type: object
+ example: '2024-10-01T12:00:00Z'
+ description: The modified date of the object
+ nullable: true
+ UnifiedAtsOfficeOutput:
+ type: object
+ properties:
+ name:
+ type: string
+ example: Condo Office 5th
+ nullable: true
+ description: The name of the office
+ location:
+ type: string
+ example: New York
+ nullable: true
+ description: The location of the office
+ field_mappings:
+ type: object
+ example:
+ fav_dish: broccoli
+ fav_color: red
+ additionalProperties: true
+ nullable: true
+ description: >-
+ The custom field mappings of the object between the remote 3rd party & Panora
+ id:
+ type: string
+ example: 801f9ede-c698-4e66-a7fc-48d19eebaa4f
+ description: The UUID of the office
+ remote_id:
+ type: string
+ example: id_1
+ nullable: true
+ description: The remote ID of the office in the context of the 3rd Party
+ remote_data:
+ type: object
+ example:
+ fav_dish: broccoli
+ fav_color: red
+ nullable: true
+ additionalProperties: true
+ description: The remote data of the office in the context of the 3rd Party
+ created_at:
+ format: date-time
+ type: string
+ example: '2024-10-01T12:00:00Z'
+ nullable: true
+ description: The created date of the object
+ modified_at:
+ format: date-time
+ type: string
+ example: '2024-10-01T12:00:00Z'
+ nullable: true
+ description: The modified date of the object
+ UnifiedAtsRejectreasonOutput:
+ type: object
+ properties:
+ name:
+ type: string
+ example: Candidate inexperienced
+ nullable: true
+ description: The name of the reject reason
+ field_mappings:
+ type: object
+ example:
+ fav_dish: broccoli
+ fav_color: red
+ additionalProperties: true
+ nullable: true
+ description: >-
+ The custom field mappings of the object between the remote 3rd party & Panora
+ id:
+ type: string
+ nullable: true
+ description: The UUID of the reject reason
+ example: 801f9ede-c698-4e66-a7fc-48d19eebaa4f
+ remote_id:
+ type: string
+ nullable: true
+ description: The remote ID of the reject reason in the context of the 3rd Party
+ example: id_1
+ remote_data:
+ type: object
+ example:
+ fav_dish: broccoli
+ fav_color: red
+ nullable: true
+ additionalProperties: true
+ description: The remote data of the reject reason in the context of the 3rd Party
+ created_at:
+ format: date-time
+ type: string
+ example: '2024-10-01T12:00:00Z'
+ nullable: true
+ description: The created date of the object
+ modified_at:
+ format: date-time
+ type: string
+ example: '2024-10-01T12:00:00Z'
+ nullable: true
+ description: The modified date of the object
+ UnifiedAtsScorecardOutput:
+ type: object
+ properties:
+ overall_recommendation:
+ type: string
+ enum:
+ - DEFINITELY_NO
+ - 'NO'
+ - 'YES'
+ - STRONG_YES
+ - NO_DECISION
+ example: 'YES'
+ nullable: true
+ description: The overall recommendation
+ application_id:
+ type: string
+ example: 801f9ede-c698-4e66-a7fc-48d19eebaa4f
+ nullable: true
+ description: The UUID of the application
+ interview_id:
+ type: string
+ example: 801f9ede-c698-4e66-a7fc-48d19eebaa4f
+ nullable: true
+ description: The UUID of the interview
+ remote_created_at:
+ type: string
+ example: '2024-10-01T12:00:00Z'
+ format: date-time
+ nullable: true
+ description: The remote creation date of the scorecard
+ submitted_at:
+ type: string
+ example: '2024-10-01T12:00:00Z'
+ format: date-time
+ nullable: true
+ description: The submission date of the scorecard
+ field_mappings:
+ type: object
+ example:
+ fav_dish: broccoli
+ fav_color: red
+ additionalProperties: true
+ nullable: true
+ description: >-
+ The custom field mappings of the object between the remote 3rd party & Panora
+ id:
+ type: string
+ example: 801f9ede-c698-4e66-a7fc-48d19eebaa4f
+ description: The UUID of the scorecard
+ remote_id:
+ type: string
+ example: id_1
+ nullable: true
+ description: The remote ID of the scorecard in the context of the 3rd Party
+ remote_data:
+ type: object
+ example:
+ fav_dish: broccoli
+ fav_color: red
+ nullable: true
+ additionalProperties: true
+ description: The remote data of the scorecard in the context of the 3rd Party
+ created_at:
+ format: date-time
+ type: string
+ example: '2024-10-01T12:00:00Z'
+ nullable: true
+ description: The created date of the object
+ modified_at:
+ format: date-time
+ type: string
+ example: '2024-10-01T12:00:00Z'
+ nullable: true
+ description: The modified date of the object
+ UnifiedAtsTagOutput:
+ type: object
+ properties:
+ name:
+ type: string
+ example: Important
+ nullable: true
+ description: The name of the tag
+ id_ats_candidate:
+ type: string
+ example: 801f9ede-c698-4e66-a7fc-48d19eebaa4f
+ nullable: true
+ description: The UUID of the candidate
+ field_mappings:
+ type: object
+ example:
+ fav_dish: broccoli
+ fav_color: red
+ additionalProperties: true
+ nullable: true
+ description: >-
+ The custom field mappings of the object between the remote 3rd party & Panora
+ id:
+ type: string
+ example: 801f9ede-c698-4e66-a7fc-48d19eebaa4f
+ nullable: true
+ description: The UUID of the tag
+ remote_id:
+ type: string
+ example: id_1
+ nullable: true
+ description: The remote ID of the tag in the context of the 3rd Party
+ remote_data:
+ type: object
+ example:
+ fav_dish: broccoli
+ fav_color: red
+ nullable: true
+ additionalProperties: true
+ description: The remote data of the tag in the context of the 3rd Party
+ created_at:
+ format: date-time
+ type: string
+ nullable: true
+ example: '2024-10-01T12:00:00Z'
+ description: The creation date of the tag
+ modified_at:
+ format: date-time
+ type: string
+ nullable: true
+ example: '2024-10-01T12:00:00Z'
+ description: The modification date of the tag
+ UnifiedAtsUserOutput:
+ type: object
+ properties:
+ first_name:
+ type: string
+ example: John
+ description: The first name of the user
+ nullable: true
+ last_name:
+ type: string
+ example: Doe
+ description: The last name of the user
nullable: true
email:
type: string
- example: john.doe@example.com
- description: The email of the user
- nullable: true
- disabled:
- type: boolean
- example: false
- description: Whether the user is disabled
+ example: john.doe@example.com
+ description: The email of the user
+ nullable: true
+ disabled:
+ type: boolean
+ example: false
+ description: Whether the user is disabled
+ nullable: true
+ access_role:
+ type: string
+ example: ADMIN
+ enum:
+ - SUPER_ADMIN
+ - ADMIN
+ - TEAM_MEMBER
+ - LIMITED_TEAM_MEMBER
+ - INTERVIEWER
+ description: The access role of the user
+ nullable: true
+ remote_created_at:
+ format: date-time
+ type: string
+ example: '2024-10-01T12:00:00Z'
+ description: The remote creation date of the user
+ nullable: true
+ remote_modified_at:
+ format: date-time
+ type: string
+ example: '2024-10-01T12:00:00Z'
+ description: The remote modification date of the user
+ nullable: true
+ field_mappings:
+ type: object
+ example:
+ fav_dish: broccoli
+ fav_color: red
+ description: >-
+ The custom field mappings of the object between the remote 3rd party & Panora
+ nullable: true
+ additionalProperties: true
+ id:
+ type: string
+ example: 801f9ede-c698-4e66-a7fc-48d19eebaa4f
+ description: The UUID of the user
+ nullable: true
+ remote_id:
+ type: string
+ example: id_1
+ description: The remote ID of the user in the context of the 3rd Party
+ nullable: true
+ remote_data:
+ type: object
+ example:
+ fav_dish: broccoli
+ fav_color: red
+ description: The remote data of the user in the context of the 3rd Party
+ nullable: true
+ additionalProperties: true
+ created_at:
+ format: date-time
+ type: string
+ example: '2024-10-01T12:00:00Z'
+ description: The created date of the object
+ nullable: true
+ modified_at:
+ format: date-time
+ type: string
+ example: '2024-10-01T12:00:00Z'
+ description: The modified date of the object
+ nullable: true
+ UnifiedAtsEeocsOutput:
+ type: object
+ properties:
+ candidate_id:
+ type: string
+ example: 801f9ede-c698-4e66-a7fc-48d19eebaa4f
+ nullable: true
+ description: The UUID of the candidate
+ submitted_at:
+ type: string
+ example: '2024-10-01T12:00:00Z'
+ format: date-time
+ nullable: true
+ description: The submission date of the EEOC
+ race:
+ type: string
+ enum:
+ - 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
+ example: AMERICAN_INDIAN_OR_ALASKAN_NATIVE
+ nullable: true
+ description: The race of the candidate
+ gender:
+ type: string
+ example: MALE
+ enum:
+ - MALE
+ - FEMALE
+ - NON_BINARY
+ - OTHER
+ - DECLINE_TO_SELF_IDENTIFY
+ nullable: true
+ description: The gender of the candidate
+ veteran_status:
+ type: string
+ example: I_AM_NOT_A_PROTECTED_VETERAN
+ enum:
+ - I_AM_NOT_A_PROTECTED_VETERAN
+ - >-
+ I_IDENTIFY_AS_ONE_OR_MORE_OF_THE_CLASSIFICATIONS_OF_A_PROTECTED_VETERAN
+ - I_DONT_WISH_TO_ANSWER
+ nullable: true
+ description: The veteran status of the candidate
+ disability_status:
+ type: string
+ enum:
+ - YES_I_HAVE_A_DISABILITY_OR_PREVIOUSLY_HAD_A_DISABILITY
+ - NO_I_DONT_HAVE_A_DISABILITY
+ - I_DONT_WISH_TO_ANSWER
+ example: YES_I_HAVE_A_DISABILITY_OR_PREVIOUSLY_HAD_A_DISABILITY
+ nullable: true
+ description: The disability status of the candidate
+ field_mappings:
+ type: object
+ example:
+ fav_dish: broccoli
+ fav_color: red
+ additionalProperties: true
+ nullable: true
+ description: >-
+ The custom field mappings of the object between the remote 3rd party & Panora
+ id:
+ type: string
+ example: 801f9ede-c698-4e66-a7fc-48d19eebaa4f
+ nullable: true
+ description: The UUID of the EEOC
+ remote_id:
+ type: string
+ example: id_1
+ nullable: true
+ description: The remote ID of the EEOC in the context of the 3rd Party
+ remote_data:
+ type: object
+ example:
+ fav_dish: broccoli
+ fav_color: red
+ nullable: true
+ additionalProperties: true
+ description: The remote data of the EEOC in the context of the 3rd Party
+ created_at:
+ format: date-time
+ type: string
+ example: '2024-10-01T12:00:00Z'
+ nullable: true
+ description: The created date of the object
+ modified_at:
+ format: date-time
+ type: string
+ example: '2024-10-01T12:00:00Z'
+ nullable: true
+ description: The modified date of the object
+ UnifiedAccountingAccountOutput:
+ type: object
+ properties:
+ name:
+ type: string
+ example: Cash
+ nullable: true
+ description: The name of the account
+ description:
+ type: string
+ example: Main cash account for daily operations
+ nullable: true
+ description: A description of the account
+ classification:
+ type: string
+ example: Asset
+ nullable: true
+ description: The classification of the account
+ type:
+ type: string
+ example: Current Asset
+ nullable: true
+ description: The type of the account
+ status:
+ type: string
+ example: Active
+ nullable: true
+ description: The status of the account
+ current_balance:
+ type: number
+ example: 10000
+ nullable: true
+ description: The current balance of the account
+ currency:
+ type: string
+ example: USD
+ enum: &ref_157
+ - AED
+ - AFN
+ - ALL
+ - AMD
+ - ANG
+ - AOA
+ - ARS
+ - AUD
+ - AWG
+ - AZN
+ - BAM
+ - BBD
+ - BDT
+ - BGN
+ - BHD
+ - BIF
+ - BMD
+ - BND
+ - BOB
+ - BRL
+ - BSD
+ - BTN
+ - BWP
+ - BYN
+ - BZD
+ - CAD
+ - CDF
+ - CHF
+ - CLP
+ - CNY
+ - COP
+ - CRC
+ - CUP
+ - CVE
+ - CZK
+ - DJF
+ - DKK
+ - DOP
+ - DZD
+ - EGP
+ - ERN
+ - ETB
+ - EUR
+ - FJD
+ - FKP
+ - FOK
+ - GBP
+ - GEL
+ - GGP
+ - GHS
+ - GIP
+ - GMD
+ - GNF
+ - GTQ
+ - GYD
+ - HKD
+ - HNL
+ - HRK
+ - HTG
+ - HUF
+ - IDR
+ - ILS
+ - IMP
+ - INR
+ - IQD
+ - IRR
+ - ISK
+ - JEP
+ - JMD
+ - JOD
+ - JPY
+ - KES
+ - KGS
+ - KHR
+ - KID
+ - KMF
+ - KRW
+ - KWD
+ - KYD
+ - KZT
+ - LAK
+ - LBP
+ - LKR
+ - LRD
+ - LSL
+ - LYD
+ - MAD
+ - MDL
+ - MGA
+ - MKD
+ - MMK
+ - MNT
+ - MOP
+ - MRU
+ - MUR
+ - MVR
+ - MWK
+ - MXN
+ - MYR
+ - MZN
+ - NAD
+ - NGN
+ - NIO
+ - NOK
+ - NPR
+ - NZD
+ - OMR
+ - PAB
+ - PEN
+ - PGK
+ - PHP
+ - PKR
+ - PLN
+ - PYG
+ - QAR
+ - RON
+ - RSD
+ - RUB
+ - RWF
+ - SAR
+ - SBD
+ - SCR
+ - SDG
+ - SEK
+ - SGD
+ - SHP
+ - SLE
+ - SLL
+ - SOS
+ - SRD
+ - SSP
+ - STN
+ - SYP
+ - SZL
+ - THB
+ - TJS
+ - TMT
+ - TND
+ - TOP
+ - TRY
+ - TTD
+ - TVD
+ - TWD
+ - TZS
+ - UAH
+ - UGX
+ - USD
+ - UYU
+ - UZS
+ - VES
+ - VND
+ - VUV
+ - WST
+ - XAF
+ - XCD
+ - XDR
+ - XOF
+ - XPF
+ - YER
+ - ZAR
+ - ZMW
+ - ZWL
+ nullable: true
+ description: The currency of the account
+ account_number:
+ type: string
+ example: '1000'
+ nullable: true
+ description: The account number
+ parent_account:
+ type: string
+ example: 801f9ede-c698-4e66-a7fc-48d19eebaa4f
+ nullable: true
+ description: The UUID of the parent account
+ company_info_id:
+ type: string
+ example: 801f9ede-c698-4e66-a7fc-48d19eebaa4f
+ nullable: true
+ description: The UUID of the associated company info
+ field_mappings:
+ type: object
+ example: &ref_158
+ custom_field_1: value1
+ custom_field_2: value2
+ nullable: true
+ description: >-
+ The custom field mappings of the object between the remote 3rd party & Panora
+ id:
+ type: string
+ example: 801f9ede-c698-4e66-a7fc-48d19eebaa4f
+ nullable: true
+ description: The UUID of the account record
+ remote_id:
+ type: string
+ example: account_1234
+ nullable: true
+ description: The remote ID of the account in the context of the 3rd Party
+ remote_data:
+ type: object
+ example:
+ raw_data:
+ additional_field: some value
+ nullable: true
+ description: The remote data of the account in the context of the 3rd Party
+ created_at:
+ format: date-time
+ type: string
+ example: '2024-06-15T12:00:00Z'
+ nullable: true
+ description: The created date of the account record
+ modified_at:
+ format: date-time
+ type: string
+ example: '2024-06-15T12:00:00Z'
+ nullable: true
+ description: The last modified date of the account record
+ UnifiedAccountingAccountInput:
+ type: object
+ properties:
+ name:
+ type: string
+ example: Cash
+ nullable: true
+ description: The name of the account
+ description:
+ type: string
+ example: Main cash account for daily operations
+ nullable: true
+ description: A description of the account
+ classification:
+ type: string
+ example: Asset
+ nullable: true
+ description: The classification of the account
+ type:
+ type: string
+ example: Current Asset
+ nullable: true
+ description: The type of the account
+ status:
+ type: string
+ example: Active
+ nullable: true
+ description: The status of the account
+ current_balance:
+ type: number
+ example: 10000
+ nullable: true
+ description: The current balance of the account
+ currency:
+ type: string
+ example: USD
+ enum: *ref_157
+ nullable: true
+ description: The currency of the account
+ account_number:
+ type: string
+ example: '1000'
+ nullable: true
+ description: The account number
+ parent_account:
+ type: string
+ example: 801f9ede-c698-4e66-a7fc-48d19eebaa4f
+ nullable: true
+ description: The UUID of the parent account
+ company_info_id:
+ type: string
+ example: 801f9ede-c698-4e66-a7fc-48d19eebaa4f
+ nullable: true
+ description: The UUID of the associated company info
+ field_mappings:
+ type: object
+ example: *ref_158
+ nullable: true
+ description: >-
+ The custom field mappings of the object between the remote 3rd party & Panora
+ UnifiedAccountingAddressOutput:
+ type: object
+ properties:
+ type:
+ type: string
+ example: Billing
+ nullable: true
+ description: The type of the address
+ street_1:
+ type: string
+ example: 123 Main St
+ nullable: true
+ description: The first line of the street address
+ street_2:
+ type: string
+ example: Apt 4B
+ nullable: true
+ description: The second line of the street address
+ city:
+ type: string
+ example: New York
+ nullable: true
+ description: The city of the address
+ state:
+ type: string
+ example: NY
+ nullable: true
+ description: The state of the address
+ country_subdivision:
+ type: string
+ example: New York
+ nullable: true
+ description: The country subdivision (e.g., province or state) of the address
+ country:
+ type: string
+ example: USA
+ nullable: true
+ description: The country of the address
+ zip:
+ type: string
+ example: '10001'
+ nullable: true
+ description: The zip or postal code of the address
+ contact_id:
+ type: string
+ example: 801f9ede-c698-4e66-a7fc-48d19eebaa4f
+ nullable: true
+ description: The UUID of the associated contact
+ company_info_id:
+ type: string
+ example: 801f9ede-c698-4e66-a7fc-48d19eebaa4f
+ nullable: true
+ description: The UUID of the associated company info
+ field_mappings:
+ type: object
+ example:
+ custom_field_1: value1
+ custom_field_2: value2
+ nullable: true
+ description: >-
+ The custom field mappings of the object between the remote 3rd party & Panora
+ id:
+ type: string
+ example: 801f9ede-c698-4e66-a7fc-48d19eebaa4f
+ nullable: true
+ description: The UUID of the address record
+ remote_id:
+ type: string
+ example: address_1234
+ nullable: true
+ description: The remote ID of the address in the context of the 3rd Party
+ remote_data:
+ type: object
+ example:
+ raw_data:
+ additional_field: some value
+ nullable: true
+ description: The remote data of the address in the context of the 3rd Party
+ created_at:
+ format: date-time
+ type: string
+ example: '2024-06-15T12:00:00Z'
+ nullable: true
+ description: The created date of the address record
+ modified_at:
+ format: date-time
+ type: string
+ example: '2024-06-15T12:00:00Z'
+ nullable: true
+ description: The last modified date of the address record
+ UnifiedAccountingAttachmentOutput:
+ type: object
+ properties:
+ file_name:
+ type: string
+ example: invoice.pdf
+ nullable: true
+ description: The name of the attached file
+ file_url:
+ type: string
+ example: https://example.com/files/invoice.pdf
+ nullable: true
+ description: The URL where the file can be accessed
+ account_id:
+ type: string
+ example: 801f9ede-c698-4e66-a7fc-48d19eebaa4f
+ nullable: true
+ description: The UUID of the associated account
+ field_mappings:
+ type: object
+ example: &ref_159
+ custom_field_1: value1
+ custom_field_2: value2
+ nullable: true
+ description: >-
+ The custom field mappings of the object between the remote 3rd party & Panora
+ id:
+ type: string
+ example: 801f9ede-c698-4e66-a7fc-48d19eebaa4f
+ nullable: true
+ description: The UUID of the attachment record
+ remote_id:
+ type: string
+ example: attachment_1234
+ nullable: true
+ description: The remote ID of the attachment in the context of the 3rd Party
+ remote_data:
+ type: object
+ example:
+ raw_data:
+ additional_field: some value
+ nullable: true
+ description: The remote data of the attachment in the context of the 3rd Party
+ created_at:
+ format: date-time
+ type: string
+ example: '2024-06-15T12:00:00Z'
+ nullable: true
+ description: The created date of the attachment record
+ modified_at:
+ format: date-time
+ type: string
+ example: '2024-06-15T12:00:00Z'
+ nullable: true
+ description: The last modified date of the attachment record
+ UnifiedAccountingAttachmentInput:
+ type: object
+ properties:
+ file_name:
+ type: string
+ example: invoice.pdf
+ nullable: true
+ description: The name of the attached file
+ file_url:
+ type: string
+ example: https://example.com/files/invoice.pdf
+ nullable: true
+ description: The URL where the file can be accessed
+ account_id:
+ type: string
+ example: 801f9ede-c698-4e66-a7fc-48d19eebaa4f
+ nullable: true
+ description: The UUID of the associated account
+ field_mappings:
+ type: object
+ example: *ref_159
+ nullable: true
+ description: >-
+ The custom field mappings of the object between the remote 3rd party & Panora
+ LineItem:
+ type: object
+ properties:
+ name:
+ type: string
+ example: Net Income
+ nullable: true
+ description: The name of the report item
+ value:
+ type: number
+ example: 100000
+ nullable: true
+ description: The value of the report item
+ type:
+ type: string
+ example: Operating Activities
+ nullable: true
+ description: The type of the report item
+ parent_item:
+ type: string
+ example: 801f9ede-c698-4e66-a7fc-48d19eebaa4f
+ nullable: true
+ description: The UUID of the parent item
+ remote_id:
+ type: string
+ example: report_item_1234
+ nullable: true
+ description: The remote ID of the report item
+ remote_generated_at:
+ format: date-time
+ type: string
+ example: '2024-07-01T12:00:00Z'
+ nullable: true
+ description: The date when the report item was generated in the remote system
+ company_info_id:
+ type: string
+ example: 801f9ede-c698-4e66-a7fc-48d19eebaa4f
+ nullable: true
+ description: The UUID of the associated company info object
+ created_at:
+ format: date-time
+ type: string
+ example: '2024-06-15T12:00:00Z'
+ description: The created date of the report item
+ modified_at:
+ format: date-time
+ type: string
+ example: '2024-06-15T12:00:00Z'
+ description: The last modified date of the report item
+ UnifiedAccountingBalancesheetOutput:
+ type: object
+ properties:
+ name:
+ type: string
+ example: Q2 2024 Balance Sheet
+ nullable: true
+ description: The name of the balance sheet
+ currency:
+ type: string
+ example: USD
+ enum:
+ - AED
+ - AFN
+ - ALL
+ - AMD
+ - ANG
+ - AOA
+ - ARS
+ - AUD
+ - AWG
+ - AZN
+ - BAM
+ - BBD
+ - BDT
+ - BGN
+ - BHD
+ - BIF
+ - BMD
+ - BND
+ - BOB
+ - BRL
+ - BSD
+ - BTN
+ - BWP
+ - BYN
+ - BZD
+ - CAD
+ - CDF
+ - CHF
+ - CLP
+ - CNY
+ - COP
+ - CRC
+ - CUP
+ - CVE
+ - CZK
+ - DJF
+ - DKK
+ - DOP
+ - DZD
+ - EGP
+ - ERN
+ - ETB
+ - EUR
+ - FJD
+ - FKP
+ - FOK
+ - GBP
+ - GEL
+ - GGP
+ - GHS
+ - GIP
+ - GMD
+ - GNF
+ - GTQ
+ - GYD
+ - HKD
+ - HNL
+ - HRK
+ - HTG
+ - HUF
+ - IDR
+ - ILS
+ - IMP
+ - INR
+ - IQD
+ - IRR
+ - ISK
+ - JEP
+ - JMD
+ - JOD
+ - JPY
+ - KES
+ - KGS
+ - KHR
+ - KID
+ - KMF
+ - KRW
+ - KWD
+ - KYD
+ - KZT
+ - LAK
+ - LBP
+ - LKR
+ - LRD
+ - LSL
+ - LYD
+ - MAD
+ - MDL
+ - MGA
+ - MKD
+ - MMK
+ - MNT
+ - MOP
+ - MRU
+ - MUR
+ - MVR
+ - MWK
+ - MXN
+ - MYR
+ - MZN
+ - NAD
+ - NGN
+ - NIO
+ - NOK
+ - NPR
+ - NZD
+ - OMR
+ - PAB
+ - PEN
+ - PGK
+ - PHP
+ - PKR
+ - PLN
+ - PYG
+ - QAR
+ - RON
+ - RSD
+ - RUB
+ - RWF
+ - SAR
+ - SBD
+ - SCR
+ - SDG
+ - SEK
+ - SGD
+ - SHP
+ - SLE
+ - SLL
+ - SOS
+ - SRD
+ - SSP
+ - STN
+ - SYP
+ - SZL
+ - THB
+ - TJS
+ - TMT
+ - TND
+ - TOP
+ - TRY
+ - TTD
+ - TVD
+ - TWD
+ - TZS
+ - UAH
+ - UGX
+ - USD
+ - UYU
+ - UZS
+ - VES
+ - VND
+ - VUV
+ - WST
+ - XAF
+ - XCD
+ - XDR
+ - XOF
+ - XPF
+ - YER
+ - ZAR
+ - ZMW
+ - ZWL
+ nullable: true
+ description: The currency used in the balance sheet
+ company_info_id:
+ type: string
+ example: 801f9ede-c698-4e66-a7fc-48d19eebaa4f
+ nullable: true
+ description: The UUID of the associated company info
+ date:
+ format: date-time
+ type: string
+ example: '2024-06-30T23:59:59Z'
+ nullable: true
+ description: The date of the balance sheet
+ net_assets:
+ type: number
+ example: 1000000
+ nullable: true
+ description: The net assets value
+ assets:
+ example:
+ - Cash
+ - Accounts Receivable
+ - Inventory
+ nullable: true
+ description: The list of assets
+ type: array
+ items:
+ type: string
+ liabilities:
+ example:
+ - Accounts Payable
+ - Long-term Debt
+ nullable: true
+ description: The list of liabilities
+ type: array
+ items:
+ type: string
+ equity:
+ example:
+ - Common Stock
+ - Retained Earnings
+ nullable: true
+ description: The list of equity items
+ type: array
+ items:
+ type: string
+ remote_generated_at:
+ format: date-time
+ type: string
+ example: '2024-07-01T12:00:00Z'
+ nullable: true
+ description: The date when the balance sheet was generated in the remote system
+ line_items:
+ description: The report items associated with this balance sheet
+ type: array
+ items:
+ $ref: '#/components/schemas/LineItem'
+ field_mappings:
+ type: object
+ example:
+ custom_field_1: value1
+ custom_field_2: value2
+ nullable: true
+ description: >-
+ The custom field mappings of the object between the remote 3rd party & Panora
+ id:
+ type: string
+ example: 801f9ede-c698-4e66-a7fc-48d19eebaa4f
+ nullable: true
+ description: The UUID of the balance sheet record
+ remote_id:
+ type: string
+ example: balancesheet_1234
+ nullable: true
+ description: The remote ID of the balance sheet in the context of the 3rd Party
+ remote_data:
+ type: object
+ example:
+ raw_data:
+ additional_field: some value
+ nullable: true
+ description: The remote data of the balance sheet in the context of the 3rd Party
+ created_at:
+ format: date-time
+ type: string
+ example: '2024-06-15T12:00:00Z'
+ nullable: true
+ description: The created date of the balance sheet record
+ modified_at:
+ format: date-time
+ type: string
+ example: '2024-06-15T12:00:00Z'
+ nullable: true
+ description: The last modified date of the balance sheet record
+ UnifiedAccountingCashflowstatementOutput:
+ type: object
+ properties:
+ name:
+ type: string
+ example: Q2 2024 Cash Flow Statement
+ nullable: true
+ description: The name of the cash flow statement
+ currency:
+ type: string
+ example: USD
+ enum:
+ - AED
+ - AFN
+ - ALL
+ - AMD
+ - ANG
+ - AOA
+ - ARS
+ - AUD
+ - AWG
+ - AZN
+ - BAM
+ - BBD
+ - BDT
+ - BGN
+ - BHD
+ - BIF
+ - BMD
+ - BND
+ - BOB
+ - BRL
+ - BSD
+ - BTN
+ - BWP
+ - BYN
+ - BZD
+ - CAD
+ - CDF
+ - CHF
+ - CLP
+ - CNY
+ - COP
+ - CRC
+ - CUP
+ - CVE
+ - CZK
+ - DJF
+ - DKK
+ - DOP
+ - DZD
+ - EGP
+ - ERN
+ - ETB
+ - EUR
+ - FJD
+ - FKP
+ - FOK
+ - GBP
+ - GEL
+ - GGP
+ - GHS
+ - GIP
+ - GMD
+ - GNF
+ - GTQ
+ - GYD
+ - HKD
+ - HNL
+ - HRK
+ - HTG
+ - HUF
+ - IDR
+ - ILS
+ - IMP
+ - INR
+ - IQD
+ - IRR
+ - ISK
+ - JEP
+ - JMD
+ - JOD
+ - JPY
+ - KES
+ - KGS
+ - KHR
+ - KID
+ - KMF
+ - KRW
+ - KWD
+ - KYD
+ - KZT
+ - LAK
+ - LBP
+ - LKR
+ - LRD
+ - LSL
+ - LYD
+ - MAD
+ - MDL
+ - MGA
+ - MKD
+ - MMK
+ - MNT
+ - MOP
+ - MRU
+ - MUR
+ - MVR
+ - MWK
+ - MXN
+ - MYR
+ - MZN
+ - NAD
+ - NGN
+ - NIO
+ - NOK
+ - NPR
+ - NZD
+ - OMR
+ - PAB
+ - PEN
+ - PGK
+ - PHP
+ - PKR
+ - PLN
+ - PYG
+ - QAR
+ - RON
+ - RSD
+ - RUB
+ - RWF
+ - SAR
+ - SBD
+ - SCR
+ - SDG
+ - SEK
+ - SGD
+ - SHP
+ - SLE
+ - SLL
+ - SOS
+ - SRD
+ - SSP
+ - STN
+ - SYP
+ - SZL
+ - THB
+ - TJS
+ - TMT
+ - TND
+ - TOP
+ - TRY
+ - TTD
+ - TVD
+ - TWD
+ - TZS
+ - UAH
+ - UGX
+ - USD
+ - UYU
+ - UZS
+ - VES
+ - VND
+ - VUV
+ - WST
+ - XAF
+ - XCD
+ - XDR
+ - XOF
+ - XPF
+ - YER
+ - ZAR
+ - ZMW
+ - ZWL
+ nullable: true
+ description: The currency used in the cash flow statement
+ company_id:
+ type: string
+ example: 801f9ede-c698-4e66-a7fc-48d19eebaa4f
+ nullable: true
+ description: The UUID of the associated company
+ start_period:
+ format: date-time
+ type: string
+ example: '2024-04-01T00:00:00Z'
+ nullable: true
+ description: The start date of the period covered by the cash flow statement
+ end_period:
+ format: date-time
+ type: string
+ example: '2024-06-30T23:59:59Z'
+ nullable: true
+ description: The end date of the period covered by the cash flow statement
+ cash_at_beginning_of_period:
+ type: number
+ example: 1000000
+ nullable: true
+ description: The cash balance at the beginning of the period
+ cash_at_end_of_period:
+ type: number
+ example: 1200000
+ nullable: true
+ description: The cash balance at the end of the period
+ remote_generated_at:
+ format: date-time
+ type: string
+ example: '2024-07-01T12:00:00Z'
+ nullable: true
+ description: >-
+ The date when the cash flow statement was generated in the remote system
+ line_items:
+ description: The report items associated with this cash flow statement
+ type: array
+ items:
+ $ref: '#/components/schemas/LineItem'
+ field_mappings:
+ type: object
+ example:
+ custom_field_1: value1
+ custom_field_2: value2
+ nullable: true
+ description: >-
+ The custom field mappings of the object between the remote 3rd party & Panora
+ id:
+ type: string
+ example: 801f9ede-c698-4e66-a7fc-48d19eebaa4f
+ nullable: true
+ description: The UUID of the cash flow statement record
+ remote_id:
+ type: string
+ example: cashflowstatement_1234
+ nullable: true
+ description: >-
+ The remote ID of the cash flow statement in the context of the 3rd Party
+ remote_data:
+ type: object
+ example:
+ raw_data:
+ additional_field: some value
+ nullable: true
+ description: >-
+ The remote data of the cash flow statement in the context of the 3rd Party
+ created_at:
+ format: date-time
+ type: string
+ example: '2024-06-15T12:00:00Z'
+ nullable: true
+ description: The created date of the cash flow statement record
+ modified_at:
+ format: date-time
+ type: string
+ example: '2024-06-15T12:00:00Z'
+ nullable: true
+ description: The last modified date of the cash flow statement record
+ UnifiedAccountingCompanyinfoOutput:
+ type: object
+ properties:
+ name:
+ type: string
+ example: Acme Corporation
+ nullable: true
+ description: The name of the company
+ legal_name:
+ type: string
+ example: Acme Corporation LLC
+ nullable: true
+ description: The legal name of the company
+ tax_number:
+ type: string
+ example: '123456789'
+ nullable: true
+ description: The tax number of the company
+ fiscal_year_end_month:
+ type: number
+ example: 12
+ nullable: true
+ description: The month of the fiscal year end (1-12)
+ fiscal_year_end_day:
+ type: number
+ example: 31
+ nullable: true
+ description: The day of the fiscal year end (1-31)
+ currency:
+ type: string
+ example: USD
+ enum:
+ - AED
+ - AFN
+ - ALL
+ - AMD
+ - ANG
+ - AOA
+ - ARS
+ - AUD
+ - AWG
+ - AZN
+ - BAM
+ - BBD
+ - BDT
+ - BGN
+ - BHD
+ - BIF
+ - BMD
+ - BND
+ - BOB
+ - BRL
+ - BSD
+ - BTN
+ - BWP
+ - BYN
+ - BZD
+ - CAD
+ - CDF
+ - CHF
+ - CLP
+ - CNY
+ - COP
+ - CRC
+ - CUP
+ - CVE
+ - CZK
+ - DJF
+ - DKK
+ - DOP
+ - DZD
+ - EGP
+ - ERN
+ - ETB
+ - EUR
+ - FJD
+ - FKP
+ - FOK
+ - GBP
+ - GEL
+ - GGP
+ - GHS
+ - GIP
+ - GMD
+ - GNF
+ - GTQ
+ - GYD
+ - HKD
+ - HNL
+ - HRK
+ - HTG
+ - HUF
+ - IDR
+ - ILS
+ - IMP
+ - INR
+ - IQD
+ - IRR
+ - ISK
+ - JEP
+ - JMD
+ - JOD
+ - JPY
+ - KES
+ - KGS
+ - KHR
+ - KID
+ - KMF
+ - KRW
+ - KWD
+ - KYD
+ - KZT
+ - LAK
+ - LBP
+ - LKR
+ - LRD
+ - LSL
+ - LYD
+ - MAD
+ - MDL
+ - MGA
+ - MKD
+ - MMK
+ - MNT
+ - MOP
+ - MRU
+ - MUR
+ - MVR
+ - MWK
+ - MXN
+ - MYR
+ - MZN
+ - NAD
+ - NGN
+ - NIO
+ - NOK
+ - NPR
+ - NZD
+ - OMR
+ - PAB
+ - PEN
+ - PGK
+ - PHP
+ - PKR
+ - PLN
+ - PYG
+ - QAR
+ - RON
+ - RSD
+ - RUB
+ - RWF
+ - SAR
+ - SBD
+ - SCR
+ - SDG
+ - SEK
+ - SGD
+ - SHP
+ - SLE
+ - SLL
+ - SOS
+ - SRD
+ - SSP
+ - STN
+ - SYP
+ - SZL
+ - THB
+ - TJS
+ - TMT
+ - TND
+ - TOP
+ - TRY
+ - TTD
+ - TVD
+ - TWD
+ - TZS
+ - UAH
+ - UGX
+ - USD
+ - UYU
+ - UZS
+ - VES
+ - VND
+ - VUV
+ - WST
+ - XAF
+ - XCD
+ - XDR
+ - XOF
+ - XPF
+ - YER
+ - ZAR
+ - ZMW
+ - ZWL
+ nullable: true
+ description: The currency used by the company
+ urls:
+ example:
+ - https://www.acmecorp.com
+ - https://store.acmecorp.com
+ nullable: true
+ description: The URLs associated with the company
+ type: array
+ items:
+ type: string
+ tracking_categories:
+ example:
+ - 801f9ede-c698-4e66-a7fc-48d19eebaa4f
+ - 801f9ede-c698-4e66-a7fc-48d19eebaa4f
+ nullable: true
+ description: The UUIDs of the tracking categories used by the company
+ type: array
+ items:
+ type: string
+ field_mappings:
+ type: object
+ example:
+ custom_field_1: value1
+ custom_field_2: value2
+ nullable: true
+ description: >-
+ The custom field mappings of the object between the remote 3rd party & Panora
+ id:
+ type: string
+ example: 801f9ede-c698-4e66-a7fc-48d19eebaa4f
+ nullable: true
+ description: The UUID of the company info record
+ remote_id:
+ type: string
+ example: company_1234
+ nullable: true
+ description: The remote ID of the company info in the context of the 3rd Party
+ remote_data:
+ type: object
+ example:
+ raw_data:
+ additional_field: some value
+ nullable: true
+ description: The remote data of the company info in the context of the 3rd Party
+ remote_created_at:
+ format: date-time
+ type: string
+ example: '2024-06-15T12:00:00Z'
+ nullable: true
+ description: The date when the company info was created in the remote system
+ created_at:
+ format: date-time
+ type: string
+ example: '2024-06-15T12:00:00Z'
+ nullable: true
+ description: The created date of the company info record
+ modified_at:
+ format: date-time
+ type: string
+ example: '2024-06-15T12:00:00Z'
+ nullable: true
+ description: The last modified date of the company info record
+ UnifiedAccountingContactOutput:
+ type: object
+ properties:
+ name:
+ type: string
+ example: John Doe
+ nullable: true
+ description: The name of the contact
+ is_supplier:
+ type: boolean
+ example: true
+ nullable: true
+ description: Indicates if the contact is a supplier
+ is_customer:
+ type: boolean
+ example: false
+ nullable: true
+ description: Indicates if the contact is a customer
+ email_address:
+ type: string
+ example: john.doe@example.com
+ nullable: true
+ description: The email address of the contact
+ tax_number:
+ type: string
+ example: '123456789'
+ nullable: true
+ description: The tax number of the contact
+ status:
+ type: string
+ example: Active
+ nullable: true
+ description: The status of the contact
+ currency:
+ type: string
+ example: USD
+ nullable: true
+ enum: &ref_160
+ - AED
+ - AFN
+ - ALL
+ - AMD
+ - ANG
+ - AOA
+ - ARS
+ - AUD
+ - AWG
+ - AZN
+ - BAM
+ - BBD
+ - BDT
+ - BGN
+ - BHD
+ - BIF
+ - BMD
+ - BND
+ - BOB
+ - BRL
+ - BSD
+ - BTN
+ - BWP
+ - BYN
+ - BZD
+ - CAD
+ - CDF
+ - CHF
+ - CLP
+ - CNY
+ - COP
+ - CRC
+ - CUP
+ - CVE
+ - CZK
+ - DJF
+ - DKK
+ - DOP
+ - DZD
+ - EGP
+ - ERN
+ - ETB
+ - EUR
+ - FJD
+ - FKP
+ - FOK
+ - GBP
+ - GEL
+ - GGP
+ - GHS
+ - GIP
+ - GMD
+ - GNF
+ - GTQ
+ - GYD
+ - HKD
+ - HNL
+ - HRK
+ - HTG
+ - HUF
+ - IDR
+ - ILS
+ - IMP
+ - INR
+ - IQD
+ - IRR
+ - ISK
+ - JEP
+ - JMD
+ - JOD
+ - JPY
+ - KES
+ - KGS
+ - KHR
+ - KID
+ - KMF
+ - KRW
+ - KWD
+ - KYD
+ - KZT
+ - LAK
+ - LBP
+ - LKR
+ - LRD
+ - LSL
+ - LYD
+ - MAD
+ - MDL
+ - MGA
+ - MKD
+ - MMK
+ - MNT
+ - MOP
+ - MRU
+ - MUR
+ - MVR
+ - MWK
+ - MXN
+ - MYR
+ - MZN
+ - NAD
+ - NGN
+ - NIO
+ - NOK
+ - NPR
+ - NZD
+ - OMR
+ - PAB
+ - PEN
+ - PGK
+ - PHP
+ - PKR
+ - PLN
+ - PYG
+ - QAR
+ - RON
+ - RSD
+ - RUB
+ - RWF
+ - SAR
+ - SBD
+ - SCR
+ - SDG
+ - SEK
+ - SGD
+ - SHP
+ - SLE
+ - SLL
+ - SOS
+ - SRD
+ - SSP
+ - STN
+ - SYP
+ - SZL
+ - THB
+ - TJS
+ - TMT
+ - TND
+ - TOP
+ - TRY
+ - TTD
+ - TVD
+ - TWD
+ - TZS
+ - UAH
+ - UGX
+ - USD
+ - UYU
+ - UZS
+ - VES
+ - VND
+ - VUV
+ - WST
+ - XAF
+ - XCD
+ - XDR
+ - XOF
+ - XPF
+ - YER
+ - ZAR
+ - ZMW
+ - ZWL
+ description: The currency associated with the contact
+ remote_updated_at:
+ type: string
+ example: '2024-06-15T12:00:00Z'
+ nullable: true
+ description: The date when the contact was last updated in the remote system
+ company_info_id:
+ type: string
+ example: 801f9ede-c698-4e66-a7fc-48d19eebaa4f
+ nullable: true
+ description: The UUID of the associated company info
+ field_mappings:
+ type: object
+ example: &ref_161
+ custom_field_1: value1
+ custom_field_2: value2
+ nullable: true
+ description: >-
+ The custom field mappings of the object between the remote 3rd party & Panora
+ id:
+ type: string
+ example: 801f9ede-c698-4e66-a7fc-48d19eebaa4f
+ nullable: true
+ description: The UUID of the contact record
+ remote_id:
+ type: string
+ example: contact_1234
+ nullable: true
+ description: The remote ID of the contact in the context of the 3rd Party
+ remote_data:
+ type: object
+ example:
+ raw_data:
+ additional_field: some value
+ nullable: true
+ description: The remote data of the contact in the context of the 3rd Party
+ created_at:
+ format: date-time
+ type: string
+ example: '2024-06-15T12:00:00Z'
+ nullable: true
+ description: The created date of the contact record
+ modified_at:
+ format: date-time
+ type: string
+ example: '2024-06-15T12:00:00Z'
+ nullable: true
+ description: The last modified date of the contact record
+ UnifiedAccountingContactInput:
+ type: object
+ properties:
+ name:
+ type: string
+ example: John Doe
+ nullable: true
+ description: The name of the contact
+ is_supplier:
+ type: boolean
+ example: true
+ nullable: true
+ description: Indicates if the contact is a supplier
+ is_customer:
+ type: boolean
+ example: false
+ nullable: true
+ description: Indicates if the contact is a customer
+ email_address:
+ type: string
+ example: john.doe@example.com
+ nullable: true
+ description: The email address of the contact
+ tax_number:
+ type: string
+ example: '123456789'
+ nullable: true
+ description: The tax number of the contact
+ status:
+ type: string
+ example: Active
+ nullable: true
+ description: The status of the contact
+ currency:
+ type: string
+ example: USD
+ nullable: true
+ enum: *ref_160
+ description: The currency associated with the contact
+ remote_updated_at:
+ type: string
+ example: '2024-06-15T12:00:00Z'
+ nullable: true
+ description: The date when the contact was last updated in the remote system
+ company_info_id:
+ type: string
+ example: 801f9ede-c698-4e66-a7fc-48d19eebaa4f
+ nullable: true
+ description: The UUID of the associated company info
+ field_mappings:
+ type: object
+ example: *ref_161
+ nullable: true
+ description: >-
+ The custom field mappings of the object between the remote 3rd party & Panora
+ UnifiedAccountingCreditnoteOutput:
+ type: object
+ properties:
+ transaction_date:
+ format: date-time
+ type: string
+ example: '2024-06-15T12:00:00Z'
+ nullable: true
+ description: The date of the credit note transaction
+ status:
+ type: string
+ example: Issued
+ nullable: true
+ description: The status of the credit note
+ number:
+ type: string
+ example: CN-001
+ nullable: true
+ description: The number of the credit note
+ contact_id:
+ type: string
+ example: 801f9ede-c698-4e66-a7fc-48d19eebaa4f
+ nullable: true
+ description: The UUID of the associated contact
+ company_id:
+ type: string
+ example: 801f9ede-c698-4e66-a7fc-48d19eebaa4f
+ nullable: true
+ description: The UUID of the associated company
+ exchange_rate:
+ type: string
+ example: '1.2'
+ nullable: true
+ description: The exchange rate applied to the credit note
+ total_amount:
+ type: number
+ example: 10000
+ nullable: true
+ description: The total amount of the credit note
+ remaining_credit:
+ type: number
+ example: 5000
+ nullable: true
+ description: The remaining credit on the credit note
+ tracking_categories:
+ example:
+ - 801f9ede-c698-4e66-a7fc-48d19eebaa4f
+ nullable: true
+ description: The UUIDs of the tracking categories associated with the credit note
+ type: array
+ items:
+ type: string
+ currency:
+ type: string
+ example: USD
+ enum:
+ - AED
+ - AFN
+ - ALL
+ - AMD
+ - ANG
+ - AOA
+ - ARS
+ - AUD
+ - AWG
+ - AZN
+ - BAM
+ - BBD
+ - BDT
+ - BGN
+ - BHD
+ - BIF
+ - BMD
+ - BND
+ - BOB
+ - BRL
+ - BSD
+ - BTN
+ - BWP
+ - BYN
+ - BZD
+ - CAD
+ - CDF
+ - CHF
+ - CLP
+ - CNY
+ - COP
+ - CRC
+ - CUP
+ - CVE
+ - CZK
+ - DJF
+ - DKK
+ - DOP
+ - DZD
+ - EGP
+ - ERN
+ - ETB
+ - EUR
+ - FJD
+ - FKP
+ - FOK
+ - GBP
+ - GEL
+ - GGP
+ - GHS
+ - GIP
+ - GMD
+ - GNF
+ - GTQ
+ - GYD
+ - HKD
+ - HNL
+ - HRK
+ - HTG
+ - HUF
+ - IDR
+ - ILS
+ - IMP
+ - INR
+ - IQD
+ - IRR
+ - ISK
+ - JEP
+ - JMD
+ - JOD
+ - JPY
+ - KES
+ - KGS
+ - KHR
+ - KID
+ - KMF
+ - KRW
+ - KWD
+ - KYD
+ - KZT
+ - LAK
+ - LBP
+ - LKR
+ - LRD
+ - LSL
+ - LYD
+ - MAD
+ - MDL
+ - MGA
+ - MKD
+ - MMK
+ - MNT
+ - MOP
+ - MRU
+ - MUR
+ - MVR
+ - MWK
+ - MXN
+ - MYR
+ - MZN
+ - NAD
+ - NGN
+ - NIO
+ - NOK
+ - NPR
+ - NZD
+ - OMR
+ - PAB
+ - PEN
+ - PGK
+ - PHP
+ - PKR
+ - PLN
+ - PYG
+ - QAR
+ - RON
+ - RSD
+ - RUB
+ - RWF
+ - SAR
+ - SBD
+ - SCR
+ - SDG
+ - SEK
+ - SGD
+ - SHP
+ - SLE
+ - SLL
+ - SOS
+ - SRD
+ - SSP
+ - STN
+ - SYP
+ - SZL
+ - THB
+ - TJS
+ - TMT
+ - TND
+ - TOP
+ - TRY
+ - TTD
+ - TVD
+ - TWD
+ - TZS
+ - UAH
+ - UGX
+ - USD
+ - UYU
+ - UZS
+ - VES
+ - VND
+ - VUV
+ - WST
+ - XAF
+ - XCD
+ - XDR
+ - XOF
+ - XPF
+ - YER
+ - ZAR
+ - ZMW
+ - ZWL
+ nullable: true
+ description: The currency of the credit note
+ payments:
+ example:
+ - PAYMENT-001
+ - PAYMENT-002
+ nullable: true
+ description: The payments associated with the credit note
+ type: array
+ items:
+ type: string
+ applied_payments:
+ example:
+ - APPLIED-001
+ - APPLIED-002
+ nullable: true
+ description: The applied payments associated with the credit note
+ type: array
+ items:
+ type: string
+ accounting_period_id:
+ type: string
+ example: 801f9ede-c698-4e66-a7fc-48d19eebaa4f
+ nullable: true
+ description: The UUID of the associated accounting period
+ field_mappings:
+ type: object
+ example:
+ custom_field_1: value1
+ custom_field_2: value2
+ nullable: true
+ description: >-
+ The custom field mappings of the object between the remote 3rd party & Panora
+ id:
+ type: string
+ example: 801f9ede-c698-4e66-a7fc-48d19eebaa4f
+ nullable: true
+ description: The UUID of the credit note record
+ remote_id:
+ type: string
+ example: creditnote_1234
+ nullable: true
+ description: The remote ID of the credit note in the context of the 3rd Party
+ remote_data:
+ type: object
+ example:
+ raw_data:
+ additional_field: some value
+ nullable: true
+ description: The remote data of the credit note in the context of the 3rd Party
+ remote_created_at:
+ format: date-time
+ type: string
+ example: '2024-06-15T12:00:00Z'
+ nullable: true
+ description: The date when the credit note was created in the remote system
+ remote_updated_at:
+ format: date-time
+ type: string
+ example: '2024-06-15T12:00:00Z'
+ nullable: true
+ description: The date when the credit note was last updated in the remote system
+ created_at:
+ format: date-time
+ type: string
+ example: '2024-06-15T12:00:00Z'
+ nullable: true
+ description: The created date of the credit note record
+ modified_at:
+ format: date-time
+ type: string
+ example: '2024-06-15T12:00:00Z'
+ nullable: true
+ description: The last modified date of the credit note record
+ UnifiedAccountingExpenseOutput:
+ type: object
+ properties:
+ transaction_date:
+ format: date-time
+ type: string
+ example: '2024-06-15T12:00:00Z'
+ nullable: true
+ description: The date of the expense transaction
+ total_amount:
+ type: number
+ example: 10000
+ nullable: true
+ description: The total amount of the expense
+ sub_total:
+ type: number
+ example: 9000
+ nullable: true
+ description: The sub-total amount of the expense (before tax)
+ total_tax_amount:
+ type: number
+ example: 1000
+ nullable: true
+ description: The total tax amount of the expense
+ currency:
+ type: string
+ example: USD
+ enum: &ref_162
+ - AED
+ - AFN
+ - ALL
+ - AMD
+ - ANG
+ - AOA
+ - ARS
+ - AUD
+ - AWG
+ - AZN
+ - BAM
+ - BBD
+ - BDT
+ - BGN
+ - BHD
+ - BIF
+ - BMD
+ - BND
+ - BOB
+ - BRL
+ - BSD
+ - BTN
+ - BWP
+ - BYN
+ - BZD
+ - CAD
+ - CDF
+ - CHF
+ - CLP
+ - CNY
+ - COP
+ - CRC
+ - CUP
+ - CVE
+ - CZK
+ - DJF
+ - DKK
+ - DOP
+ - DZD
+ - EGP
+ - ERN
+ - ETB
+ - EUR
+ - FJD
+ - FKP
+ - FOK
+ - GBP
+ - GEL
+ - GGP
+ - GHS
+ - GIP
+ - GMD
+ - GNF
+ - GTQ
+ - GYD
+ - HKD
+ - HNL
+ - HRK
+ - HTG
+ - HUF
+ - IDR
+ - ILS
+ - IMP
+ - INR
+ - IQD
+ - IRR
+ - ISK
+ - JEP
+ - JMD
+ - JOD
+ - JPY
+ - KES
+ - KGS
+ - KHR
+ - KID
+ - KMF
+ - KRW
+ - KWD
+ - KYD
+ - KZT
+ - LAK
+ - LBP
+ - LKR
+ - LRD
+ - LSL
+ - LYD
+ - MAD
+ - MDL
+ - MGA
+ - MKD
+ - MMK
+ - MNT
+ - MOP
+ - MRU
+ - MUR
+ - MVR
+ - MWK
+ - MXN
+ - MYR
+ - MZN
+ - NAD
+ - NGN
+ - NIO
+ - NOK
+ - NPR
+ - NZD
+ - OMR
+ - PAB
+ - PEN
+ - PGK
+ - PHP
+ - PKR
+ - PLN
+ - PYG
+ - QAR
+ - RON
+ - RSD
+ - RUB
+ - RWF
+ - SAR
+ - SBD
+ - SCR
+ - SDG
+ - SEK
+ - SGD
+ - SHP
+ - SLE
+ - SLL
+ - SOS
+ - SRD
+ - SSP
+ - STN
+ - SYP
+ - SZL
+ - THB
+ - TJS
+ - TMT
+ - TND
+ - TOP
+ - TRY
+ - TTD
+ - TVD
+ - TWD
+ - TZS
+ - UAH
+ - UGX
+ - USD
+ - UYU
+ - UZS
+ - VES
+ - VND
+ - VUV
+ - WST
+ - XAF
+ - XCD
+ - XDR
+ - XOF
+ - XPF
+ - YER
+ - ZAR
+ - ZMW
+ - ZWL
+ nullable: true
+ description: The currency of the expense
+ exchange_rate:
+ type: string
+ example: '1.2'
+ nullable: true
+ description: The exchange rate applied to the expense
+ memo:
+ type: string
+ example: Business lunch with client
+ nullable: true
+ description: A memo or description for the expense
+ account_id:
+ type: string
+ example: 801f9ede-c698-4e66-a7fc-48d19eebaa4f
+ nullable: true
+ description: The UUID of the associated account
+ contact_id:
+ type: string
+ example: 801f9ede-c698-4e66-a7fc-48d19eebaa4f
+ nullable: true
+ description: The UUID of the associated contact
+ company_info_id:
+ type: string
+ example: 801f9ede-c698-4e66-a7fc-48d19eebaa4f
+ nullable: true
+ description: The UUID of the associated company info
+ tracking_categories:
+ example: &ref_163
+ - 801f9ede-c698-4e66-a7fc-48d19eebaa4f
+ nullable: true
+ description: The UUIDs of the tracking categories associated with the expense
+ type: array
+ items:
+ type: string
+ line_items:
+ description: The line items associated with this expense
+ type: array
+ items:
+ $ref: '#/components/schemas/LineItem'
+ field_mappings:
+ type: object
+ example: &ref_164
+ custom_field_1: value1
+ custom_field_2: value2
+ nullable: true
+ description: >-
+ The custom field mappings of the object between the remote 3rd party & Panora
+ id:
+ type: string
+ example: 801f9ede-c698-4e66-a7fc-48d19eebaa4f
+ nullable: true
+ description: The UUID of the expense record
+ remote_id:
+ type: string
+ example: expense_1234
+ nullable: true
+ description: The remote ID of the expense in the context of the 3rd Party
+ remote_data:
+ type: object
+ example:
+ raw_data:
+ additional_field: some value
+ nullable: true
+ description: The remote data of the expense in the context of the 3rd Party
+ remote_created_at:
+ format: date-time
+ type: string
+ example: '2024-06-15T12:00:00Z'
+ nullable: true
+ description: The date when the expense was created in the remote system
+ created_at:
+ format: date-time
+ type: string
+ example: '2024-06-15T12:00:00Z'
+ nullable: true
+ description: The created date of the expense record
+ modified_at:
+ format: date-time
+ type: string
+ example: '2024-06-15T12:00:00Z'
+ nullable: true
+ description: The last modified date of the expense record
+ UnifiedAccountingExpenseInput:
+ type: object
+ properties:
+ transaction_date:
+ format: date-time
+ type: string
+ example: '2024-06-15T12:00:00Z'
+ nullable: true
+ description: The date of the expense transaction
+ total_amount:
+ type: number
+ example: 10000
+ nullable: true
+ description: The total amount of the expense
+ sub_total:
+ type: number
+ example: 9000
+ nullable: true
+ description: The sub-total amount of the expense (before tax)
+ total_tax_amount:
+ type: number
+ example: 1000
+ nullable: true
+ description: The total tax amount of the expense
+ currency:
+ type: string
+ example: USD
+ enum: *ref_162
+ nullable: true
+ description: The currency of the expense
+ exchange_rate:
+ type: string
+ example: '1.2'
+ nullable: true
+ description: The exchange rate applied to the expense
+ memo:
+ type: string
+ example: Business lunch with client
+ nullable: true
+ description: A memo or description for the expense
+ account_id:
+ type: string
+ example: 801f9ede-c698-4e66-a7fc-48d19eebaa4f
+ nullable: true
+ description: The UUID of the associated account
+ contact_id:
+ type: string
+ example: 801f9ede-c698-4e66-a7fc-48d19eebaa4f
+ nullable: true
+ description: The UUID of the associated contact
+ company_info_id:
+ type: string
+ example: 801f9ede-c698-4e66-a7fc-48d19eebaa4f
+ nullable: true
+ description: The UUID of the associated company info
+ tracking_categories:
+ example: *ref_163
+ nullable: true
+ description: The UUIDs of the tracking categories associated with the expense
+ type: array
+ items:
+ type: string
+ line_items:
+ description: The line items associated with this expense
+ type: array
+ items:
+ $ref: '#/components/schemas/LineItem'
+ field_mappings:
+ type: object
+ example: *ref_164
+ nullable: true
+ description: >-
+ The custom field mappings of the object between the remote 3rd party & Panora
+ UnifiedAccountingIncomestatementOutput:
+ type: object
+ properties:
+ name:
+ type: string
+ example: Q2 2024 Income Statement
+ nullable: true
+ description: The name of the income statement
+ currency:
+ type: string
+ example: USD
+ enum:
+ - AED
+ - AFN
+ - ALL
+ - AMD
+ - ANG
+ - AOA
+ - ARS
+ - AUD
+ - AWG
+ - AZN
+ - BAM
+ - BBD
+ - BDT
+ - BGN
+ - BHD
+ - BIF
+ - BMD
+ - BND
+ - BOB
+ - BRL
+ - BSD
+ - BTN
+ - BWP
+ - BYN
+ - BZD
+ - CAD
+ - CDF
+ - CHF
+ - CLP
+ - CNY
+ - COP
+ - CRC
+ - CUP
+ - CVE
+ - CZK
+ - DJF
+ - DKK
+ - DOP
+ - DZD
+ - EGP
+ - ERN
+ - ETB
+ - EUR
+ - FJD
+ - FKP
+ - FOK
+ - GBP
+ - GEL
+ - GGP
+ - GHS
+ - GIP
+ - GMD
+ - GNF
+ - GTQ
+ - GYD
+ - HKD
+ - HNL
+ - HRK
+ - HTG
+ - HUF
+ - IDR
+ - ILS
+ - IMP
+ - INR
+ - IQD
+ - IRR
+ - ISK
+ - JEP
+ - JMD
+ - JOD
+ - JPY
+ - KES
+ - KGS
+ - KHR
+ - KID
+ - KMF
+ - KRW
+ - KWD
+ - KYD
+ - KZT
+ - LAK
+ - LBP
+ - LKR
+ - LRD
+ - LSL
+ - LYD
+ - MAD
+ - MDL
+ - MGA
+ - MKD
+ - MMK
+ - MNT
+ - MOP
+ - MRU
+ - MUR
+ - MVR
+ - MWK
+ - MXN
+ - MYR
+ - MZN
+ - NAD
+ - NGN
+ - NIO
+ - NOK
+ - NPR
+ - NZD
+ - OMR
+ - PAB
+ - PEN
+ - PGK
+ - PHP
+ - PKR
+ - PLN
+ - PYG
+ - QAR
+ - RON
+ - RSD
+ - RUB
+ - RWF
+ - SAR
+ - SBD
+ - SCR
+ - SDG
+ - SEK
+ - SGD
+ - SHP
+ - SLE
+ - SLL
+ - SOS
+ - SRD
+ - SSP
+ - STN
+ - SYP
+ - SZL
+ - THB
+ - TJS
+ - TMT
+ - TND
+ - TOP
+ - TRY
+ - TTD
+ - TVD
+ - TWD
+ - TZS
+ - UAH
+ - UGX
+ - USD
+ - UYU
+ - UZS
+ - VES
+ - VND
+ - VUV
+ - WST
+ - XAF
+ - XCD
+ - XDR
+ - XOF
+ - XPF
+ - YER
+ - ZAR
+ - ZMW
+ - ZWL
+ nullable: true
+ description: The currency used in the income statement
+ start_period:
+ format: date-time
+ type: string
+ example: '2024-04-01T00:00:00Z'
+ nullable: true
+ description: The start date of the period covered by the income statement
+ end_period:
+ format: date-time
+ type: string
+ example: '2024-06-30T23:59:59Z'
+ nullable: true
+ description: The end date of the period covered by the income statement
+ gross_profit:
+ type: number
+ example: 1000000
+ nullable: true
+ description: The gross profit for the period
+ net_operating_income:
+ type: number
+ example: 800000
+ nullable: true
+ description: The net operating income for the period
+ net_income:
+ type: number
+ example: 750000
+ nullable: true
+ description: The net income for the period
+ field_mappings:
+ type: object
+ example:
+ custom_field_1: value1
+ custom_field_2: value2
+ nullable: true
+ description: >-
+ The custom field mappings of the object between the remote 3rd party & Panora
+ id:
+ type: string
+ example: 801f9ede-c698-4e66-a7fc-48d19eebaa4f
+ nullable: true
+ description: The UUID of the income statement record
+ remote_id:
+ type: string
+ example: incomestatement_1234
+ nullable: true
+ description: >-
+ The remote ID of the income statement in the context of the 3rd Party
+ remote_data:
+ type: object
+ example:
+ raw_data:
+ additional_field: some value
+ nullable: true
+ description: >-
+ The remote data of the income statement in the context of the 3rd Party
+ created_at:
+ format: date-time
+ type: string
+ example: '2024-06-15T12:00:00Z'
+ nullable: true
+ description: The created date of the income statement record
+ modified_at:
+ format: date-time
+ type: string
+ example: '2024-06-15T12:00:00Z'
+ nullable: true
+ description: The last modified date of the income statement record
+ UnifiedAccountingInvoiceOutput:
+ type: object
+ properties:
+ type:
+ type: string
+ example: Sales
+ nullable: true
+ description: The type of the invoice
+ number:
+ type: string
+ example: INV-001
+ nullable: true
+ description: The invoice number
+ issue_date:
+ format: date-time
+ type: string
+ example: '2024-06-15T12:00:00Z'
+ nullable: true
+ description: The date the invoice was issued
+ due_date:
+ format: date-time
+ type: string
+ example: '2024-07-15T12:00:00Z'
+ nullable: true
+ description: The due date of the invoice
+ paid_on_date:
+ format: date-time
+ type: string
+ example: '2024-07-10T12:00:00Z'
+ nullable: true
+ description: The date the invoice was paid
+ memo:
+ type: string
+ example: Payment for services rendered
+ nullable: true
+ description: A memo or note on the invoice
+ currency:
+ type: string
+ example: USD
+ enum: &ref_165
+ - AED
+ - AFN
+ - ALL
+ - AMD
+ - ANG
+ - AOA
+ - ARS
+ - AUD
+ - AWG
+ - AZN
+ - BAM
+ - BBD
+ - BDT
+ - BGN
+ - BHD
+ - BIF
+ - BMD
+ - BND
+ - BOB
+ - BRL
+ - BSD
+ - BTN
+ - BWP
+ - BYN
+ - BZD
+ - CAD
+ - CDF
+ - CHF
+ - CLP
+ - CNY
+ - COP
+ - CRC
+ - CUP
+ - CVE
+ - CZK
+ - DJF
+ - DKK
+ - DOP
+ - DZD
+ - EGP
+ - ERN
+ - ETB
+ - EUR
+ - FJD
+ - FKP
+ - FOK
+ - GBP
+ - GEL
+ - GGP
+ - GHS
+ - GIP
+ - GMD
+ - GNF
+ - GTQ
+ - GYD
+ - HKD
+ - HNL
+ - HRK
+ - HTG
+ - HUF
+ - IDR
+ - ILS
+ - IMP
+ - INR
+ - IQD
+ - IRR
+ - ISK
+ - JEP
+ - JMD
+ - JOD
+ - JPY
+ - KES
+ - KGS
+ - KHR
+ - KID
+ - KMF
+ - KRW
+ - KWD
+ - KYD
+ - KZT
+ - LAK
+ - LBP
+ - LKR
+ - LRD
+ - LSL
+ - LYD
+ - MAD
+ - MDL
+ - MGA
+ - MKD
+ - MMK
+ - MNT
+ - MOP
+ - MRU
+ - MUR
+ - MVR
+ - MWK
+ - MXN
+ - MYR
+ - MZN
+ - NAD
+ - NGN
+ - NIO
+ - NOK
+ - NPR
+ - NZD
+ - OMR
+ - PAB
+ - PEN
+ - PGK
+ - PHP
+ - PKR
+ - PLN
+ - PYG
+ - QAR
+ - RON
+ - RSD
+ - RUB
+ - RWF
+ - SAR
+ - SBD
+ - SCR
+ - SDG
+ - SEK
+ - SGD
+ - SHP
+ - SLE
+ - SLL
+ - SOS
+ - SRD
+ - SSP
+ - STN
+ - SYP
+ - SZL
+ - THB
+ - TJS
+ - TMT
+ - TND
+ - TOP
+ - TRY
+ - TTD
+ - TVD
+ - TWD
+ - TZS
+ - UAH
+ - UGX
+ - USD
+ - UYU
+ - UZS
+ - VES
+ - VND
+ - VUV
+ - WST
+ - XAF
+ - XCD
+ - XDR
+ - XOF
+ - XPF
+ - YER
+ - ZAR
+ - ZMW
+ - ZWL
+ nullable: true
+ description: The currency of the invoice
+ exchange_rate:
+ type: string
+ example: '1.2'
+ nullable: true
+ description: The exchange rate applied to the invoice
+ total_discount:
+ type: number
+ example: 1000
+ nullable: true
+ description: The total discount applied to the invoice
+ sub_total:
+ type: number
+ example: 10000
+ nullable: true
+ description: The subtotal of the invoice
+ status:
+ type: string
+ example: Paid
+ nullable: true
+ description: The status of the invoice
+ total_tax_amount:
+ type: number
+ example: 1000
+ nullable: true
+ description: The total tax amount on the invoice
+ total_amount:
+ type: number
+ example: 11000
+ nullable: true
+ description: The total amount of the invoice
+ balance:
+ type: number
+ example: 0
+ nullable: true
+ description: The remaining balance on the invoice
+ contact_id:
+ type: string
+ example: 801f9ede-c698-4e66-a7fc-48d19eebaa4f
+ nullable: true
+ description: The UUID of the associated contact
+ accounting_period_id:
+ type: string
+ example: 801f9ede-c698-4e66-a7fc-48d19eebaa4f
+ nullable: true
+ description: The UUID of the associated accounting period
+ tracking_categories:
+ example: &ref_166
+ - 801f9ede-c698-4e66-a7fc-48d19eebaa4f
+ - 801f9ede-c698-4e66-a7fc-48d19eebaa4f
+ nullable: true
+ description: The UUIDs of the tracking categories associated with the invoice
+ type: array
+ items:
+ type: string
+ line_items:
+ description: The line items associated with this invoice
+ type: array
+ items:
+ $ref: '#/components/schemas/LineItem'
+ field_mappings:
+ type: object
+ example: &ref_167
+ custom_field_1: value1
+ custom_field_2: value2
+ nullable: true
+ description: >-
+ The custom field mappings of the object between the remote 3rd party & Panora
+ id:
+ type: string
+ example: 801f9ede-c698-4e66-a7fc-48d19eebaa4f
+ nullable: true
+ description: The UUID of the invoice record
+ remote_id:
+ type: string
+ example: invoice_1234
+ nullable: true
+ description: The remote ID of the invoice in the context of the 3rd Party
+ remote_data:
+ type: object
+ example:
+ raw_data:
+ additional_field: some value
+ nullable: true
+ description: The remote data of the invoice in the context of the 3rd Party
+ remote_updated_at:
+ format: date-time
+ type: string
+ example: '2024-06-15T12:00:00Z'
+ nullable: true
+ description: The date when the invoice was last updated in the remote system
+ created_at:
+ format: date-time
+ type: string
+ example: '2024-06-15T12:00:00Z'
+ nullable: true
+ description: The created date of the invoice record
+ modified_at:
+ format: date-time
+ type: string
+ example: '2024-06-15T12:00:00Z'
+ nullable: true
+ description: The last modified date of the invoice record
+ UnifiedAccountingInvoiceInput:
+ type: object
+ properties:
+ type:
+ type: string
+ example: Sales
+ nullable: true
+ description: The type of the invoice
+ number:
+ type: string
+ example: INV-001
+ nullable: true
+ description: The invoice number
+ issue_date:
+ format: date-time
+ type: string
+ example: '2024-06-15T12:00:00Z'
+ nullable: true
+ description: The date the invoice was issued
+ due_date:
+ format: date-time
+ type: string
+ example: '2024-07-15T12:00:00Z'
+ nullable: true
+ description: The due date of the invoice
+ paid_on_date:
+ format: date-time
+ type: string
+ example: '2024-07-10T12:00:00Z'
+ nullable: true
+ description: The date the invoice was paid
+ memo:
+ type: string
+ example: Payment for services rendered
+ nullable: true
+ description: A memo or note on the invoice
+ currency:
+ type: string
+ example: USD
+ enum: *ref_165
+ nullable: true
+ description: The currency of the invoice
+ exchange_rate:
+ type: string
+ example: '1.2'
+ nullable: true
+ description: The exchange rate applied to the invoice
+ total_discount:
+ type: number
+ example: 1000
+ nullable: true
+ description: The total discount applied to the invoice
+ sub_total:
+ type: number
+ example: 10000
+ nullable: true
+ description: The subtotal of the invoice
+ status:
+ type: string
+ example: Paid
+ nullable: true
+ description: The status of the invoice
+ total_tax_amount:
+ type: number
+ example: 1000
+ nullable: true
+ description: The total tax amount on the invoice
+ total_amount:
+ type: number
+ example: 11000
+ nullable: true
+ description: The total amount of the invoice
+ balance:
+ type: number
+ example: 0
+ nullable: true
+ description: The remaining balance on the invoice
+ contact_id:
+ type: string
+ example: 801f9ede-c698-4e66-a7fc-48d19eebaa4f
+ nullable: true
+ description: The UUID of the associated contact
+ accounting_period_id:
+ type: string
+ example: 801f9ede-c698-4e66-a7fc-48d19eebaa4f
+ nullable: true
+ description: The UUID of the associated accounting period
+ tracking_categories:
+ example: *ref_166
+ nullable: true
+ description: The UUIDs of the tracking categories associated with the invoice
+ type: array
+ items:
+ type: string
+ line_items:
+ description: The line items associated with this invoice
+ type: array
+ items:
+ $ref: '#/components/schemas/LineItem'
+ field_mappings:
+ type: object
+ example: *ref_167
+ nullable: true
+ description: >-
+ The custom field mappings of the object between the remote 3rd party & Panora
+ UnifiedAccountingItemOutput:
+ type: object
+ properties:
+ name:
+ type: string
+ example: Product A
+ nullable: true
+ description: The name of the accounting item
+ status:
+ type: string
+ example: Active
+ nullable: true
+ description: The status of the accounting item
+ unit_price:
+ type: number
+ example: 1000
+ nullable: true
+ description: The unit price of the item in cents
+ purchase_price:
+ type: number
+ example: 800
+ nullable: true
+ description: The purchase price of the item in cents
+ sales_account:
+ type: string
+ example: 801f9ede-c698-4e66-a7fc-48d19eebaa4f
+ nullable: true
+ description: The UUID of the associated sales account
+ purchase_account:
+ type: string
+ example: 801f9ede-c698-4e66-a7fc-48d19eebaa4f
+ nullable: true
+ description: The UUID of the associated purchase account
+ company_info_id:
+ type: string
+ example: 801f9ede-c698-4e66-a7fc-48d19eebaa4f
+ nullable: true
+ description: The UUID of the associated company info
+ field_mappings:
+ type: object
+ example:
+ custom_field_1: value1
+ custom_field_2: value2
+ nullable: true
+ description: >-
+ The custom field mappings of the object between the remote 3rd party & Panora
+ id:
+ type: string
+ example: 801f9ede-c698-4e66-a7fc-48d19eebaa4f
+ nullable: true
+ description: The UUID of the accounting item record
+ remote_id:
+ type: string
+ example: item_1234
+ nullable: true
+ description: The remote ID of the item in the context of the 3rd Party
+ remote_updated_at:
+ format: date-time
+ type: string
+ example: '2024-06-15T12:00:00Z'
+ nullable: true
+ description: The date when the item was last updated in the remote system
+ remote_data:
+ type: object
+ example:
+ raw_data:
+ additional_field: some value
+ nullable: true
+ description: The remote data of the item in the context of the 3rd Party
+ created_at:
+ format: date-time
+ type: string
+ example: '2024-06-15T12:00:00Z'
+ nullable: true
+ description: The created date of the accounting item record
+ modified_at:
+ format: date-time
+ type: string
+ example: '2024-06-15T12:00:00Z'
+ nullable: true
+ description: The last modified date of the accounting item record
+ UnifiedAccountingJournalentryOutput:
+ type: object
+ properties:
+ transaction_date:
+ format: date-time
+ type: string
+ example: '2024-06-15T12:00:00Z'
+ nullable: true
+ description: The date of the transaction
+ payments:
+ example: &ref_168
+ - payment1
+ - payment2
+ nullable: true
+ description: The payments associated with the journal entry
+ type: array
+ items:
+ type: string
+ applied_payments:
+ example: &ref_169
+ - appliedPayment1
+ - appliedPayment2
+ nullable: true
+ description: The applied payments for the journal entry
+ type: array
+ items:
+ type: string
+ memo:
+ type: string
+ example: Monthly expense journal entry
+ nullable: true
+ description: A memo or note for the journal entry
+ currency:
+ type: string
+ example: USD
+ enum: &ref_170
+ - AED
+ - AFN
+ - ALL
+ - AMD
+ - ANG
+ - AOA
+ - ARS
+ - AUD
+ - AWG
+ - AZN
+ - BAM
+ - BBD
+ - BDT
+ - BGN
+ - BHD
+ - BIF
+ - BMD
+ - BND
+ - BOB
+ - BRL
+ - BSD
+ - BTN
+ - BWP
+ - BYN
+ - BZD
+ - CAD
+ - CDF
+ - CHF
+ - CLP
+ - CNY
+ - COP
+ - CRC
+ - CUP
+ - CVE
+ - CZK
+ - DJF
+ - DKK
+ - DOP
+ - DZD
+ - EGP
+ - ERN
+ - ETB
+ - EUR
+ - FJD
+ - FKP
+ - FOK
+ - GBP
+ - GEL
+ - GGP
+ - GHS
+ - GIP
+ - GMD
+ - GNF
+ - GTQ
+ - GYD
+ - HKD
+ - HNL
+ - HRK
+ - HTG
+ - HUF
+ - IDR
+ - ILS
+ - IMP
+ - INR
+ - IQD
+ - IRR
+ - ISK
+ - JEP
+ - JMD
+ - JOD
+ - JPY
+ - KES
+ - KGS
+ - KHR
+ - KID
+ - KMF
+ - KRW
+ - KWD
+ - KYD
+ - KZT
+ - LAK
+ - LBP
+ - LKR
+ - LRD
+ - LSL
+ - LYD
+ - MAD
+ - MDL
+ - MGA
+ - MKD
+ - MMK
+ - MNT
+ - MOP
+ - MRU
+ - MUR
+ - MVR
+ - MWK
+ - MXN
+ - MYR
+ - MZN
+ - NAD
+ - NGN
+ - NIO
+ - NOK
+ - NPR
+ - NZD
+ - OMR
+ - PAB
+ - PEN
+ - PGK
+ - PHP
+ - PKR
+ - PLN
+ - PYG
+ - QAR
+ - RON
+ - RSD
+ - RUB
+ - RWF
+ - SAR
+ - SBD
+ - SCR
+ - SDG
+ - SEK
+ - SGD
+ - SHP
+ - SLE
+ - SLL
+ - SOS
+ - SRD
+ - SSP
+ - STN
+ - SYP
+ - SZL
+ - THB
+ - TJS
+ - TMT
+ - TND
+ - TOP
+ - TRY
+ - TTD
+ - TVD
+ - TWD
+ - TZS
+ - UAH
+ - UGX
+ - USD
+ - UYU
+ - UZS
+ - VES
+ - VND
+ - VUV
+ - WST
+ - XAF
+ - XCD
+ - XDR
+ - XOF
+ - XPF
+ - YER
+ - ZAR
+ - ZMW
+ - ZWL
+ nullable: true
+ description: The currency of the journal entry
+ exchange_rate:
+ type: string
+ example: '1.2'
+ nullable: true
+ description: The exchange rate applied to the journal entry
+ id_acc_company_info:
+ type: string
+ example: 801f9ede-c698-4e66-a7fc-48d19eebaa4f
+ nullable: false
+ description: The UUID of the associated company info
+ journal_number:
+ type: string
+ example: JE-001
+ nullable: true
+ description: The journal number
+ tracking_categories:
+ example: &ref_171
+ - 801f9ede-c698-4e66-a7fc-48d19eebaa4f
+ nullable: true
+ description: >-
+ The UUIDs of the tracking categories associated with the journal entry
+ type: array
+ items:
+ type: string
+ id_acc_accounting_period:
+ type: string
+ example: 801f9ede-c698-4e66-a7fc-48d19eebaa4f
+ nullable: true
+ description: The UUID of the associated accounting period
+ posting_status:
+ type: string
+ example: Posted
+ nullable: true
+ description: The posting status of the journal entry
+ line_items:
+ description: The line items associated with this journal entry
+ type: array
+ items:
+ $ref: '#/components/schemas/LineItem'
+ field_mappings:
+ type: object
+ example: &ref_172
+ custom_field_1: value1
+ custom_field_2: value2
+ nullable: true
+ description: >-
+ The custom field mappings of the object between the remote 3rd party & Panora
+ id:
+ type: string
+ example: 801f9ede-c698-4e66-a7fc-48d19eebaa4f
+ nullable: true
+ description: The UUID of the journal entry record
+ remote_id:
+ type: string
+ example: journal_entry_1234
+ nullable: false
+ description: The remote ID of the journal entry in the context of the 3rd Party
+ remote_created_at:
+ format: date-time
+ type: string
+ example: '2024-06-15T12:00:00Z'
+ nullable: true
+ description: The date when the journal entry was created in the remote system
+ remote_modiified_at:
+ format: date-time
+ type: string
+ example: '2024-06-15T12:00:00Z'
+ nullable: true
+ description: >-
+ The date when the journal entry was last modified in the remote system
+ remote_data:
+ type: object
+ example:
+ raw_data:
+ additional_field: some value
+ nullable: true
+ description: The remote data of the journal entry in the context of the 3rd Party
+ created_at:
+ format: date-time
+ type: string
+ example: '2024-06-15T12:00:00Z'
+ nullable: true
+ description: The created date of the journal entry record
+ modified_at:
+ format: date-time
+ type: string
+ example: '2024-06-15T12:00:00Z'
+ nullable: true
+ description: The last modified date of the journal entry record
+ UnifiedAccountingJournalentryInput:
+ type: object
+ properties:
+ transaction_date:
+ format: date-time
+ type: string
+ example: '2024-06-15T12:00:00Z'
+ nullable: true
+ description: The date of the transaction
+ payments:
+ example: *ref_168
+ nullable: true
+ description: The payments associated with the journal entry
+ type: array
+ items:
+ type: string
+ applied_payments:
+ example: *ref_169
+ nullable: true
+ description: The applied payments for the journal entry
+ type: array
+ items:
+ type: string
+ memo:
+ type: string
+ example: Monthly expense journal entry
+ nullable: true
+ description: A memo or note for the journal entry
+ currency:
+ type: string
+ example: USD
+ enum: *ref_170
+ nullable: true
+ description: The currency of the journal entry
+ exchange_rate:
+ type: string
+ example: '1.2'
+ nullable: true
+ description: The exchange rate applied to the journal entry
+ id_acc_company_info:
+ type: string
+ example: 801f9ede-c698-4e66-a7fc-48d19eebaa4f
+ nullable: false
+ description: The UUID of the associated company info
+ journal_number:
+ type: string
+ example: JE-001
+ nullable: true
+ description: The journal number
+ tracking_categories:
+ example: *ref_171
+ nullable: true
+ description: >-
+ The UUIDs of the tracking categories associated with the journal entry
+ type: array
+ items:
+ type: string
+ id_acc_accounting_period:
+ type: string
+ example: 801f9ede-c698-4e66-a7fc-48d19eebaa4f
+ nullable: true
+ description: The UUID of the associated accounting period
+ posting_status:
+ type: string
+ example: Posted
+ nullable: true
+ description: The posting status of the journal entry
+ line_items:
+ description: The line items associated with this journal entry
+ type: array
+ items:
+ $ref: '#/components/schemas/LineItem'
+ field_mappings:
+ type: object
+ example: *ref_172
+ nullable: true
+ description: >-
+ The custom field mappings of the object between the remote 3rd party & Panora
+ UnifiedAccountingPaymentOutput:
+ type: object
+ properties:
+ invoice_id:
+ type: string
+ example: 801f9ede-c698-4e66-a7fc-48d19eebaa4f
+ nullable: true
+ description: The UUID of the associated invoice
+ transaction_date:
+ format: date-time
+ type: string
+ example: '2024-06-15T12:00:00Z'
+ nullable: true
+ description: The date of the transaction
+ contact_id:
+ type: string
+ example: 801f9ede-c698-4e66-a7fc-48d19eebaa4f
+ nullable: true
+ description: The UUID of the associated contact
+ account_id:
+ type: string
+ example: 801f9ede-c698-4e66-a7fc-48d19eebaa4f
+ nullable: true
+ description: The UUID of the associated account
+ currency:
+ type: string
+ example: USD
+ enum: &ref_173
+ - AED
+ - AFN
+ - ALL
+ - AMD
+ - ANG
+ - AOA
+ - ARS
+ - AUD
+ - AWG
+ - AZN
+ - BAM
+ - BBD
+ - BDT
+ - BGN
+ - BHD
+ - BIF
+ - BMD
+ - BND
+ - BOB
+ - BRL
+ - BSD
+ - BTN
+ - BWP
+ - BYN
+ - BZD
+ - CAD
+ - CDF
+ - CHF
+ - CLP
+ - CNY
+ - COP
+ - CRC
+ - CUP
+ - CVE
+ - CZK
+ - DJF
+ - DKK
+ - DOP
+ - DZD
+ - EGP
+ - ERN
+ - ETB
+ - EUR
+ - FJD
+ - FKP
+ - FOK
+ - GBP
+ - GEL
+ - GGP
+ - GHS
+ - GIP
+ - GMD
+ - GNF
+ - GTQ
+ - GYD
+ - HKD
+ - HNL
+ - HRK
+ - HTG
+ - HUF
+ - IDR
+ - ILS
+ - IMP
+ - INR
+ - IQD
+ - IRR
+ - ISK
+ - JEP
+ - JMD
+ - JOD
+ - JPY
+ - KES
+ - KGS
+ - KHR
+ - KID
+ - KMF
+ - KRW
+ - KWD
+ - KYD
+ - KZT
+ - LAK
+ - LBP
+ - LKR
+ - LRD
+ - LSL
+ - LYD
+ - MAD
+ - MDL
+ - MGA
+ - MKD
+ - MMK
+ - MNT
+ - MOP
+ - MRU
+ - MUR
+ - MVR
+ - MWK
+ - MXN
+ - MYR
+ - MZN
+ - NAD
+ - NGN
+ - NIO
+ - NOK
+ - NPR
+ - NZD
+ - OMR
+ - PAB
+ - PEN
+ - PGK
+ - PHP
+ - PKR
+ - PLN
+ - PYG
+ - QAR
+ - RON
+ - RSD
+ - RUB
+ - RWF
+ - SAR
+ - SBD
+ - SCR
+ - SDG
+ - SEK
+ - SGD
+ - SHP
+ - SLE
+ - SLL
+ - SOS
+ - SRD
+ - SSP
+ - STN
+ - SYP
+ - SZL
+ - THB
+ - TJS
+ - TMT
+ - TND
+ - TOP
+ - TRY
+ - TTD
+ - TVD
+ - TWD
+ - TZS
+ - UAH
+ - UGX
+ - USD
+ - UYU
+ - UZS
+ - VES
+ - VND
+ - VUV
+ - WST
+ - XAF
+ - XCD
+ - XDR
+ - XOF
+ - XPF
+ - YER
+ - ZAR
+ - ZMW
+ - ZWL
+ nullable: true
+ description: The currency of the payment
+ exchange_rate:
+ type: string
+ example: '1.2'
+ nullable: true
+ description: The exchange rate applied to the payment
+ total_amount:
+ type: number
+ example: 10000
+ nullable: true
+ description: The total amount of the payment in cents
+ type:
+ type: string
+ example: Credit Card
+ nullable: true
+ description: The type of payment
+ company_info_id:
+ type: string
+ example: 801f9ede-c698-4e66-a7fc-48d19eebaa4f
+ nullable: true
+ description: The UUID of the associated company info
+ accounting_period_id:
+ type: string
+ example: 801f9ede-c698-4e66-a7fc-48d19eebaa4f
+ nullable: true
+ description: The UUID of the associated accounting period
+ tracking_categories:
+ example: &ref_174
+ - 801f9ede-c698-4e66-a7fc-48d19eebaa4f
+ nullable: true
+ description: The UUIDs of the tracking categories associated with the payment
+ type: array
+ items:
+ type: string
+ line_items:
+ description: The line items associated with this payment
+ type: array
+ items:
+ $ref: '#/components/schemas/LineItem'
+ field_mappings:
+ type: object
+ example: &ref_175
+ custom_field_1: value1
+ custom_field_2: value2
+ nullable: true
+ description: >-
+ The custom field mappings of the object between the remote 3rd party & Panora
+ id:
+ type: string
+ example: 801f9ede-c698-4e66-a7fc-48d19eebaa4f
+ nullable: true
+ description: The UUID of the payment record
+ remote_id:
+ type: string
+ example: payment_1234
+ nullable: true
+ description: The remote ID of the payment in the context of the 3rd Party
+ remote_updated_at:
+ format: date-time
+ type: string
+ example: '2024-06-15T12:00:00Z'
+ nullable: true
+ description: The date when the payment was last updated in the remote system
+ remote_data:
+ type: object
+ example:
+ raw_data:
+ additional_field: some value
+ nullable: true
+ description: The remote data of the payment in the context of the 3rd Party
+ created_at:
+ format: date-time
+ type: string
+ example: '2024-06-15T12:00:00Z'
+ nullable: true
+ description: The created date of the payment record
+ modified_at:
+ format: date-time
+ type: string
+ example: '2024-06-15T12:00:00Z'
+ nullable: true
+ description: The last modified date of the payment record
+ UnifiedAccountingPaymentInput:
+ type: object
+ properties:
+ invoice_id:
+ type: string
+ example: 801f9ede-c698-4e66-a7fc-48d19eebaa4f
+ nullable: true
+ description: The UUID of the associated invoice
+ transaction_date:
+ format: date-time
+ type: string
+ example: '2024-06-15T12:00:00Z'
+ nullable: true
+ description: The date of the transaction
+ contact_id:
+ type: string
+ example: 801f9ede-c698-4e66-a7fc-48d19eebaa4f
+ nullable: true
+ description: The UUID of the associated contact
+ account_id:
+ type: string
+ example: 801f9ede-c698-4e66-a7fc-48d19eebaa4f
+ nullable: true
+ description: The UUID of the associated account
+ currency:
+ type: string
+ example: USD
+ enum: *ref_173
+ nullable: true
+ description: The currency of the payment
+ exchange_rate:
+ type: string
+ example: '1.2'
+ nullable: true
+ description: The exchange rate applied to the payment
+ total_amount:
+ type: number
+ example: 10000
+ nullable: true
+ description: The total amount of the payment in cents
+ type:
+ type: string
+ example: Credit Card
+ nullable: true
+ description: The type of payment
+ company_info_id:
+ type: string
+ example: 801f9ede-c698-4e66-a7fc-48d19eebaa4f
+ nullable: true
+ description: The UUID of the associated company info
+ accounting_period_id:
+ type: string
+ example: 801f9ede-c698-4e66-a7fc-48d19eebaa4f
+ nullable: true
+ description: The UUID of the associated accounting period
+ tracking_categories:
+ example: *ref_174
+ nullable: true
+ description: The UUIDs of the tracking categories associated with the payment
+ type: array
+ items:
+ type: string
+ line_items:
+ description: The line items associated with this payment
+ type: array
+ items:
+ $ref: '#/components/schemas/LineItem'
+ field_mappings:
+ type: object
+ example: *ref_175
+ nullable: true
+ description: >-
+ The custom field mappings of the object between the remote 3rd party & Panora
+ UnifiedAccountingPhonenumberOutput:
+ type: object
+ properties:
+ number:
+ type: string
+ example: '+1234567890'
+ nullable: true
+ description: The phone number
+ type:
+ type: string
+ example: Mobile
+ nullable: true
+ description: The type of phone number
+ company_info_id:
+ type: string
+ example: 801f9ede-c698-4e66-a7fc-48d19eebaa4f
+ nullable: true
+ description: The UUID of the associated company info
+ contact_id:
+ type: string
+ example: 801f9ede-c698-4e66-a7fc-48d19eebaa4f
+ nullable: false
+ description: The UUID of the associated contact
+ field_mappings:
+ type: object
+ example:
+ custom_field_1: value1
+ custom_field_2: value2
+ nullable: true
+ description: >-
+ The custom field mappings of the object between the remote 3rd party & Panora
+ id:
+ type: string
+ example: 801f9ede-c698-4e66-a7fc-48d19eebaa4f
+ nullable: true
+ description: The UUID of the phone number record
+ remote_id:
+ type: string
+ example: phone_1234
+ nullable: true
+ description: The remote ID of the phone number in the context of the 3rd Party
+ remote_data:
+ type: object
+ example:
+ raw_data:
+ additional_field: some value
+ nullable: true
+ description: The remote data of the phone number in the context of the 3rd Party
+ created_at:
+ format: date-time
+ type: string
+ example: '2024-06-15T12:00:00Z'
+ nullable: true
+ description: The created date of the phone number record
+ modified_at:
+ format: date-time
+ type: string
+ example: '2024-06-15T12:00:00Z'
+ nullable: true
+ description: The last modified date of the phone number record
+ UnifiedAccountingPurchaseorderOutput:
+ type: object
+ properties:
+ status:
+ type: string
+ example: Pending
+ nullable: true
+ description: The status of the purchase order
+ issue_date:
+ format: date-time
+ type: string
+ example: '2024-06-15T12:00:00Z'
+ nullable: true
+ description: The issue date of the purchase order
+ purchase_order_number:
+ type: string
+ example: PO-001
+ nullable: true
+ description: The purchase order number
+ delivery_date:
+ format: date-time
+ type: string
+ example: '2024-07-15T12:00:00Z'
+ nullable: true
+ description: The delivery date for the purchase order
+ delivery_address:
+ type: string
+ example: 801f9ede-c698-4e66-a7fc-48d19eebaa4f
+ nullable: true
+ description: The UUID of the delivery address
+ customer:
+ type: string
+ example: 801f9ede-c698-4e66-a7fc-48d19eebaa4f
+ nullable: true
+ description: The UUID of the customer
+ vendor:
+ type: string
+ example: 801f9ede-c698-4e66-a7fc-48d19eebaa4f
+ nullable: true
+ description: The UUID of the vendor
+ memo:
+ type: string
+ example: Purchase order for Q3 inventory
+ nullable: true
+ description: A memo or note for the purchase order
+ company_id:
+ type: string
+ example: 801f9ede-c698-4e66-a7fc-48d19eebaa4f
+ nullable: true
+ description: The UUID of the company
+ total_amount:
+ type: number
+ example: 100000
+ nullable: true
+ description: The total amount of the purchase order in cents
+ currency:
+ type: string
+ example: USD
+ enum: &ref_176
+ - AED
+ - AFN
+ - ALL
+ - AMD
+ - ANG
+ - AOA
+ - ARS
+ - AUD
+ - AWG
+ - AZN
+ - BAM
+ - BBD
+ - BDT
+ - BGN
+ - BHD
+ - BIF
+ - BMD
+ - BND
+ - BOB
+ - BRL
+ - BSD
+ - BTN
+ - BWP
+ - BYN
+ - BZD
+ - CAD
+ - CDF
+ - CHF
+ - CLP
+ - CNY
+ - COP
+ - CRC
+ - CUP
+ - CVE
+ - CZK
+ - DJF
+ - DKK
+ - DOP
+ - DZD
+ - EGP
+ - ERN
+ - ETB
+ - EUR
+ - FJD
+ - FKP
+ - FOK
+ - GBP
+ - GEL
+ - GGP
+ - GHS
+ - GIP
+ - GMD
+ - GNF
+ - GTQ
+ - GYD
+ - HKD
+ - HNL
+ - HRK
+ - HTG
+ - HUF
+ - IDR
+ - ILS
+ - IMP
+ - INR
+ - IQD
+ - IRR
+ - ISK
+ - JEP
+ - JMD
+ - JOD
+ - JPY
+ - KES
+ - KGS
+ - KHR
+ - KID
+ - KMF
+ - KRW
+ - KWD
+ - KYD
+ - KZT
+ - LAK
+ - LBP
+ - LKR
+ - LRD
+ - LSL
+ - LYD
+ - MAD
+ - MDL
+ - MGA
+ - MKD
+ - MMK
+ - MNT
+ - MOP
+ - MRU
+ - MUR
+ - MVR
+ - MWK
+ - MXN
+ - MYR
+ - MZN
+ - NAD
+ - NGN
+ - NIO
+ - NOK
+ - NPR
+ - NZD
+ - OMR
+ - PAB
+ - PEN
+ - PGK
+ - PHP
+ - PKR
+ - PLN
+ - PYG
+ - QAR
+ - RON
+ - RSD
+ - RUB
+ - RWF
+ - SAR
+ - SBD
+ - SCR
+ - SDG
+ - SEK
+ - SGD
+ - SHP
+ - SLE
+ - SLL
+ - SOS
+ - SRD
+ - SSP
+ - STN
+ - SYP
+ - SZL
+ - THB
+ - TJS
+ - TMT
+ - TND
+ - TOP
+ - TRY
+ - TTD
+ - TVD
+ - TWD
+ - TZS
+ - UAH
+ - UGX
+ - USD
+ - UYU
+ - UZS
+ - VES
+ - VND
+ - VUV
+ - WST
+ - XAF
+ - XCD
+ - XDR
+ - XOF
+ - XPF
+ - YER
+ - ZAR
+ - ZMW
+ - ZWL
+ nullable: true
+ description: The currency of the purchase order
+ exchange_rate:
+ type: string
+ example: '1.2'
+ nullable: true
+ description: The exchange rate applied to the purchase order
+ tracking_categories:
+ example: &ref_177
+ - 801f9ede-c698-4e66-a7fc-48d19eebaa4f
+ nullable: true
+ description: >-
+ The UUIDs of the tracking categories associated with the purchase order
+ type: array
+ items:
+ type: string
+ accounting_period_id:
+ type: string
+ example: 801f9ede-c698-4e66-a7fc-48d19eebaa4f
+ nullable: true
+ description: The UUID of the associated accounting period
+ line_items:
+ description: The line items associated with this purchase order
+ type: array
+ items:
+ $ref: '#/components/schemas/LineItem'
+ field_mappings:
+ type: object
+ example: &ref_178
+ custom_field_1: value1
+ custom_field_2: value2
+ nullable: true
+ description: >-
+ The custom field mappings of the object between the remote 3rd party & Panora
+ id:
+ type: string
+ example: 801f9ede-c698-4e66-a7fc-48d19eebaa4f
+ nullable: true
+ description: The UUID of the purchase order record
+ remote_id:
+ type: string
+ example: po_1234
+ nullable: true
+ description: The remote ID of the purchase order in the context of the 3rd Party
+ remote_created_at:
+ format: date-time
+ type: string
+ example: '2024-06-15T12:00:00Z'
+ nullable: true
+ description: The date when the purchase order was created in the remote system
+ remote_updated_at:
+ format: date-time
+ type: string
+ example: '2024-06-15T12:00:00Z'
+ nullable: true
+ description: >-
+ The date when the purchase order was last updated in the remote system
+ remote_data:
+ type: object
+ example:
+ raw_data:
+ additional_field: some value
+ nullable: true
+ description: >-
+ The remote data of the purchase order in the context of the 3rd Party
+ created_at:
+ format: date-time
+ type: string
+ example: '2024-06-15T12:00:00Z'
+ nullable: true
+ description: The created date of the purchase order record
+ modified_at:
+ format: date-time
+ type: string
+ example: '2024-06-15T12:00:00Z'
+ nullable: true
+ description: The last modified date of the purchase order record
+ UnifiedAccountingPurchaseorderInput:
+ type: object
+ properties:
+ status:
+ type: string
+ example: Pending
+ nullable: true
+ description: The status of the purchase order
+ issue_date:
+ format: date-time
+ type: string
+ example: '2024-06-15T12:00:00Z'
+ nullable: true
+ description: The issue date of the purchase order
+ purchase_order_number:
+ type: string
+ example: PO-001
+ nullable: true
+ description: The purchase order number
+ delivery_date:
+ format: date-time
+ type: string
+ example: '2024-07-15T12:00:00Z'
+ nullable: true
+ description: The delivery date for the purchase order
+ delivery_address:
+ type: string
+ example: 801f9ede-c698-4e66-a7fc-48d19eebaa4f
+ nullable: true
+ description: The UUID of the delivery address
+ customer:
+ type: string
+ example: 801f9ede-c698-4e66-a7fc-48d19eebaa4f
+ nullable: true
+ description: The UUID of the customer
+ vendor:
+ type: string
+ example: 801f9ede-c698-4e66-a7fc-48d19eebaa4f
+ nullable: true
+ description: The UUID of the vendor
+ memo:
+ type: string
+ example: Purchase order for Q3 inventory
+ nullable: true
+ description: A memo or note for the purchase order
+ company_id:
+ type: string
+ example: 801f9ede-c698-4e66-a7fc-48d19eebaa4f
+ nullable: true
+ description: The UUID of the company
+ total_amount:
+ type: number
+ example: 100000
+ nullable: true
+ description: The total amount of the purchase order in cents
+ currency:
+ type: string
+ example: USD
+ enum: *ref_176
+ nullable: true
+ description: The currency of the purchase order
+ exchange_rate:
+ type: string
+ example: '1.2'
+ nullable: true
+ description: The exchange rate applied to the purchase order
+ tracking_categories:
+ example: *ref_177
+ nullable: true
+ description: >-
+ The UUIDs of the tracking categories associated with the purchase order
+ type: array
+ items:
+ type: string
+ accounting_period_id:
+ type: string
+ example: 801f9ede-c698-4e66-a7fc-48d19eebaa4f
+ nullable: true
+ description: The UUID of the associated accounting period
+ line_items:
+ description: The line items associated with this purchase order
+ type: array
+ items:
+ $ref: '#/components/schemas/LineItem'
+ field_mappings:
+ type: object
+ example: *ref_178
+ nullable: true
+ description: >-
+ The custom field mappings of the object between the remote 3rd party & Panora
+ UnifiedAccountingTaxrateOutput:
+ type: object
+ properties:
+ description:
+ type: string
+ example: VAT 20%
+ nullable: true
+ description: The description of the tax rate
+ total_tax_ratge:
+ type: number
+ example: 2000
+ nullable: true
+ description: The total tax rate in basis points (e.g., 2000 for 20%)
+ effective_tax_rate:
+ type: number
+ example: 1900
+ nullable: true
+ description: The effective tax rate in basis points (e.g., 1900 for 19%)
+ company_id:
+ type: string
+ example: 801f9ede-c698-4e66-a7fc-48d19eebaa4f
+ nullable: true
+ description: The UUID of the associated company
+ field_mappings:
+ type: object
+ example:
+ custom_field_1: value1
+ custom_field_2: value2
+ nullable: true
+ description: >-
+ The custom field mappings of the object between the remote 3rd party & Panora
+ id:
+ type: string
+ example: 801f9ede-c698-4e66-a7fc-48d19eebaa4f
+ nullable: true
+ description: The UUID of the tax rate record
+ remote_id:
+ type: string
+ example: tax_rate_1234
+ nullable: true
+ description: The remote ID of the tax rate in the context of the 3rd Party
+ remote_data:
+ type: object
+ example:
+ raw_data:
+ additional_field: some value
+ nullable: true
+ description: The remote data of the tax rate in the context of the 3rd Party
+ created_at:
+ format: date-time
+ type: string
+ example: '2024-06-15T12:00:00Z'
+ nullable: true
+ description: The created date of the tax rate record
+ modified_at:
+ format: date-time
+ type: string
+ example: '2024-06-15T12:00:00Z'
+ nullable: true
+ description: The last modified date of the tax rate record
+ UnifiedAccountingTrackingcategoryOutput:
+ type: object
+ properties:
+ name:
+ type: string
+ example: Department
+ nullable: true
+ description: The name of the tracking category
+ status:
+ type: string
+ example: Active
+ nullable: true
+ description: The status of the tracking category
+ category_type:
+ type: string
+ example: Expense
+ nullable: true
+ description: The type of the tracking category
+ parent_category:
+ type: string
+ example: 801f9ede-c698-4e66-a7fc-48d19eebaa4f
+ nullable: true
+ description: The UUID of the parent category, if applicable
+ field_mappings:
+ type: object
+ example:
+ custom_field_1: value1
+ custom_field_2: value2
+ nullable: true
+ description: >-
+ The custom field mappings of the object between the remote 3rd party & Panora
+ id:
+ type: string
+ example: 801f9ede-c698-4e66-a7fc-48d19eebaa4f
+ nullable: true
+ description: The UUID of the tracking category record
+ remote_id:
+ type: string
+ example: tracking_category_1234
+ nullable: true
+ description: >-
+ The remote ID of the tracking category in the context of the 3rd Party
+ remote_data:
+ type: object
+ example:
+ raw_data:
+ additional_field: some value
+ nullable: true
+ description: >-
+ The remote data of the tracking category in the context of the 3rd Party
+ created_at:
+ format: date-time
+ type: string
+ example: '2024-06-15T12:00:00Z'
+ nullable: true
+ description: The created date of the tracking category record
+ modified_at:
+ format: date-time
+ type: string
+ example: '2024-06-15T12:00:00Z'
+ nullable: true
+ description: The last modified date of the tracking category record
+ UnifiedAccountingTransactionOutput:
+ type: object
+ properties:
+ transaction_type:
+ type: string
+ example: Sale
+ nullable: true
+ description: The type of the transaction
+ number:
+ type: string
+ example: '1001'
+ nullable: true
+ description: The transaction number
+ transaction_date:
+ format: date-time
+ type: string
+ example: '2024-06-15T12:00:00Z'
+ nullable: true
+ description: The date of the transaction
+ total_amount:
+ type: string
+ example: '1000'
+ nullable: true
+ description: The total amount of the transaction
+ exchange_rate:
+ type: string
+ example: '1.2'
+ nullable: true
+ description: The exchange rate applied to the transaction
+ currency:
+ type: string
+ example: USD
+ enum:
+ - AED
+ - AFN
+ - ALL
+ - AMD
+ - ANG
+ - AOA
+ - ARS
+ - AUD
+ - AWG
+ - AZN
+ - BAM
+ - BBD
+ - BDT
+ - BGN
+ - BHD
+ - BIF
+ - BMD
+ - BND
+ - BOB
+ - BRL
+ - BSD
+ - BTN
+ - BWP
+ - BYN
+ - BZD
+ - CAD
+ - CDF
+ - CHF
+ - CLP
+ - CNY
+ - COP
+ - CRC
+ - CUP
+ - CVE
+ - CZK
+ - DJF
+ - DKK
+ - DOP
+ - DZD
+ - EGP
+ - ERN
+ - ETB
+ - EUR
+ - FJD
+ - FKP
+ - FOK
+ - GBP
+ - GEL
+ - GGP
+ - GHS
+ - GIP
+ - GMD
+ - GNF
+ - GTQ
+ - GYD
+ - HKD
+ - HNL
+ - HRK
+ - HTG
+ - HUF
+ - IDR
+ - ILS
+ - IMP
+ - INR
+ - IQD
+ - IRR
+ - ISK
+ - JEP
+ - JMD
+ - JOD
+ - JPY
+ - KES
+ - KGS
+ - KHR
+ - KID
+ - KMF
+ - KRW
+ - KWD
+ - KYD
+ - KZT
+ - LAK
+ - LBP
+ - LKR
+ - LRD
+ - LSL
+ - LYD
+ - MAD
+ - MDL
+ - MGA
+ - MKD
+ - MMK
+ - MNT
+ - MOP
+ - MRU
+ - MUR
+ - MVR
+ - MWK
+ - MXN
+ - MYR
+ - MZN
+ - NAD
+ - NGN
+ - NIO
+ - NOK
+ - NPR
+ - NZD
+ - OMR
+ - PAB
+ - PEN
+ - PGK
+ - PHP
+ - PKR
+ - PLN
+ - PYG
+ - QAR
+ - RON
+ - RSD
+ - RUB
+ - RWF
+ - SAR
+ - SBD
+ - SCR
+ - SDG
+ - SEK
+ - SGD
+ - SHP
+ - SLE
+ - SLL
+ - SOS
+ - SRD
+ - SSP
+ - STN
+ - SYP
+ - SZL
+ - THB
+ - TJS
+ - TMT
+ - TND
+ - TOP
+ - TRY
+ - TTD
+ - TVD
+ - TWD
+ - TZS
+ - UAH
+ - UGX
+ - USD
+ - UYU
+ - UZS
+ - VES
+ - VND
+ - VUV
+ - WST
+ - XAF
+ - XCD
+ - XDR
+ - XOF
+ - XPF
+ - YER
+ - ZAR
+ - ZMW
+ - ZWL
+ nullable: true
+ description: The currency of the transaction
+ tracking_categories:
+ example:
+ - 801f9ede-c698-4e66-a7fc-48d19eebaa4f
+ nullable: true
+ description: The UUIDs of the tracking categories associated with the transaction
+ type: array
+ items:
+ type: string
+ account_id:
+ type: string
+ example: 801f9ede-c698-4e66-a7fc-48d19eebaa4f
+ nullable: true
+ description: The UUID of the associated account
+ contact_id:
+ type: string
+ example: 801f9ede-c698-4e66-a7fc-48d19eebaa4f
+ nullable: true
+ description: The UUID of the associated contact
+ company_info_id:
+ type: string
+ example: 801f9ede-c698-4e66-a7fc-48d19eebaa4f
+ nullable: true
+ description: The UUID of the associated company info
+ accounting_period_id:
+ type: string
+ example: 801f9ede-c698-4e66-a7fc-48d19eebaa4f
+ nullable: true
+ description: The UUID of the associated accounting period
+ line_items:
+ description: The line items associated with this transaction
+ type: array
+ items:
+ $ref: '#/components/schemas/LineItem'
+ field_mappings:
+ type: object
+ example:
+ custom_field_1: value1
+ custom_field_2: value2
+ nullable: true
+ description: >-
+ The custom field mappings of the object between the remote 3rd party & Panora
+ id:
+ type: string
+ example: 801f9ede-c698-4e66-a7fc-48d19eebaa4f
+ nullable: true
+ description: The UUID of the transaction record
+ remote_id:
+ type: string
+ example: remote_id_1234
+ nullable: false
+ description: The remote ID of the transaction
+ created_at:
+ format: date-time
+ type: string
+ example: '2024-06-15T12:00:00Z'
+ nullable: false
+ description: The created date of the transaction
+ remote_data:
+ type: object
+ example:
+ raw_data:
+ additional_field: some value
+ nullable: true
+ description: >-
+ The remote data of the tracking category in the context of the 3rd Party
+ modified_at:
+ format: date-time
+ type: string
+ example: '2024-06-15T12:00:00Z'
+ nullable: false
+ description: The last modified date of the transaction
+ remote_updated_at:
+ format: date-time
+ type: string
+ example: '2024-06-15T12:00:00Z'
+ nullable: true
+ description: The date when the transaction was last updated in the remote system
+ UnifiedAccountingVendorcreditOutput:
+ type: object
+ properties:
+ number:
+ type: string
+ example: VC-001
+ nullable: true
+ description: The number of the vendor credit
+ transaction_date:
+ format: date-time
+ type: string
+ example: '2024-06-15T12:00:00Z'
+ nullable: true
+ description: The date of the transaction
+ vendor:
+ type: string
+ example: 801f9ede-c698-4e66-a7fc-48d19eebaa4f
+ nullable: true
+ description: The UUID of the vendor associated with the credit
+ total_amount:
+ type: string
+ example: '1000'
+ nullable: true
+ description: The total amount of the vendor credit
+ currency:
+ type: string
+ example: USD
+ nullable: true
+ enum:
+ - AED
+ - AFN
+ - ALL
+ - AMD
+ - ANG
+ - AOA
+ - ARS
+ - AUD
+ - AWG
+ - AZN
+ - BAM
+ - BBD
+ - BDT
+ - BGN
+ - BHD
+ - BIF
+ - BMD
+ - BND
+ - BOB
+ - BRL
+ - BSD
+ - BTN
+ - BWP
+ - BYN
+ - BZD
+ - CAD
+ - CDF
+ - CHF
+ - CLP
+ - CNY
+ - COP
+ - CRC
+ - CUP
+ - CVE
+ - CZK
+ - DJF
+ - DKK
+ - DOP
+ - DZD
+ - EGP
+ - ERN
+ - ETB
+ - EUR
+ - FJD
+ - FKP
+ - FOK
+ - GBP
+ - GEL
+ - GGP
+ - GHS
+ - GIP
+ - GMD
+ - GNF
+ - GTQ
+ - GYD
+ - HKD
+ - HNL
+ - HRK
+ - HTG
+ - HUF
+ - IDR
+ - ILS
+ - IMP
+ - INR
+ - IQD
+ - IRR
+ - ISK
+ - JEP
+ - JMD
+ - JOD
+ - JPY
+ - KES
+ - KGS
+ - KHR
+ - KID
+ - KMF
+ - KRW
+ - KWD
+ - KYD
+ - KZT
+ - LAK
+ - LBP
+ - LKR
+ - LRD
+ - LSL
+ - LYD
+ - MAD
+ - MDL
+ - MGA
+ - MKD
+ - MMK
+ - MNT
+ - MOP
+ - MRU
+ - MUR
+ - MVR
+ - MWK
+ - MXN
+ - MYR
+ - MZN
+ - NAD
+ - NGN
+ - NIO
+ - NOK
+ - NPR
+ - NZD
+ - OMR
+ - PAB
+ - PEN
+ - PGK
+ - PHP
+ - PKR
+ - PLN
+ - PYG
+ - QAR
+ - RON
+ - RSD
+ - RUB
+ - RWF
+ - SAR
+ - SBD
+ - SCR
+ - SDG
+ - SEK
+ - SGD
+ - SHP
+ - SLE
+ - SLL
+ - SOS
+ - SRD
+ - SSP
+ - STN
+ - SYP
+ - SZL
+ - THB
+ - TJS
+ - TMT
+ - TND
+ - TOP
+ - TRY
+ - TTD
+ - TVD
+ - TWD
+ - TZS
+ - UAH
+ - UGX
+ - USD
+ - UYU
+ - UZS
+ - VES
+ - VND
+ - VUV
+ - WST
+ - XAF
+ - XCD
+ - XDR
+ - XOF
+ - XPF
+ - YER
+ - ZAR
+ - ZMW
+ - ZWL
+ description: The currency of the vendor credit
+ exchange_rate:
+ type: string
+ example: '1.2'
nullable: true
- access_role:
+ description: The exchange rate applied to the vendor credit
+ company_id:
type: string
- example: ADMIN
- enum:
- - SUPER_ADMIN
- - ADMIN
- - TEAM_MEMBER
- - LIMITED_TEAM_MEMBER
- - INTERVIEWER
- description: The access role of the user
+ example: 801f9ede-c698-4e66-a7fc-48d19eebaa4f
nullable: true
- remote_created_at:
- format: date-time
- type: string
- example: '2024-10-01T12:00:00Z'
- description: The remote creation date of the user
+ description: The UUID of the associated company
+ tracking_categories:
+ example:
+ - 801f9ede-c698-4e66-a7fc-48d19eebaa4f
nullable: true
- remote_modified_at:
- format: date-time
+ description: >-
+ The UUID of the tracking categories associated with the vendor credit
+ type: array
+ items:
+ type: string
+ accounting_period_id:
type: string
- example: '2024-10-01T12:00:00Z'
- description: The remote modification date of the user
+ example: 801f9ede-c698-4e66-a7fc-48d19eebaa4f
nullable: true
+ description: The UUID of the associated accounting period
+ line_items:
+ description: The line items associated with this vendor credit
+ type: array
+ items:
+ $ref: '#/components/schemas/LineItem'
field_mappings:
type: object
example:
- fav_dish: broccoli
- fav_color: red
+ custom_field_1: value1
+ custom_field_2: value2
+ nullable: true
description: >-
The custom field mappings of the object between the remote 3rd party & Panora
- nullable: true
- additionalProperties: true
id:
type: string
example: 801f9ede-c698-4e66-a7fc-48d19eebaa4f
- description: The UUID of the user
nullable: true
+ description: The UUID of the vendor credit record
remote_id:
type: string
- example: id_1
- description: The remote ID of the user in the context of the 3rd Party
- nullable: true
- remote_data:
- type: object
- example:
- fav_dish: broccoli
- fav_color: red
- description: The remote data of the user in the context of the 3rd Party
+ example: remote_id_1234
nullable: true
- additionalProperties: true
+ description: The remote ID of the vendor credit
created_at:
format: date-time
type: string
- example: '2024-10-01T12:00:00Z'
- description: The created date of the object
- nullable: true
+ example: '2024-06-15T12:00:00Z'
+ nullable: false
+ description: The created date of the vendor credit
modified_at:
format: date-time
type: string
- example: '2024-10-01T12:00:00Z'
- description: The modified date of the object
- nullable: true
- UnifiedAtsEeocsOutput:
- type: object
- properties:
- candidate_id:
- type: string
- example: 801f9ede-c698-4e66-a7fc-48d19eebaa4f
- nullable: true
- description: The UUID of the candidate
- submitted_at:
- type: string
- example: '2024-10-01T12:00:00Z'
+ example: '2024-06-15T12:00:00Z'
+ nullable: false
+ description: The last modified date of the vendor credit
+ remote_updated_at:
format: date-time
- nullable: true
- description: The submission date of the EEOC
- race:
- type: string
- enum:
- - 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
- example: AMERICAN_INDIAN_OR_ALASKAN_NATIVE
- nullable: true
- description: The race of the candidate
- gender:
- type: string
- example: MALE
- enum:
- - MALE
- - FEMALE
- - NON_BINARY
- - OTHER
- - DECLINE_TO_SELF_IDENTIFY
- nullable: true
- description: The gender of the candidate
- veteran_status:
- type: string
- example: I_AM_NOT_A_PROTECTED_VETERAN
- enum:
- - I_AM_NOT_A_PROTECTED_VETERAN
- - >-
- I_IDENTIFY_AS_ONE_OR_MORE_OF_THE_CLASSIFICATIONS_OF_A_PROTECTED_VETERAN
- - I_DONT_WISH_TO_ANSWER
- nullable: true
- description: The veteran status of the candidate
- disability_status:
type: string
- enum:
- - YES_I_HAVE_A_DISABILITY_OR_PREVIOUSLY_HAD_A_DISABILITY
- - NO_I_DONT_HAVE_A_DISABILITY
- - I_DONT_WISH_TO_ANSWER
- example: YES_I_HAVE_A_DISABILITY_OR_PREVIOUSLY_HAD_A_DISABILITY
- nullable: true
- description: The disability status of the candidate
- field_mappings:
- type: object
- example:
- fav_dish: broccoli
- fav_color: red
- additionalProperties: true
+ example: '2024-06-15T12:00:00Z'
nullable: true
description: >-
- The custom field mappings of the object between the remote 3rd party & Panora
- id:
- type: string
- example: 801f9ede-c698-4e66-a7fc-48d19eebaa4f
- nullable: true
- description: The UUID of the EEOC
- remote_id:
- type: string
- example: id_1
- nullable: true
- description: The remote ID of the EEOC in the context of the 3rd Party
+ The date when the vendor credit was last updated in the remote system
remote_data:
type: object
example:
- fav_dish: broccoli
- fav_color: red
- nullable: true
- additionalProperties: true
- description: The remote data of the EEOC in the context of the 3rd Party
- created_at:
- format: date-time
- type: string
- example: '2024-10-01T12:00:00Z'
+ raw_data:
+ additional_field: some value
nullable: true
- description: The created date of the object
- modified_at:
- format: date-time
- type: string
- example: '2024-10-01T12:00:00Z'
- nullable: true
- description: The modified date of the object
- UnifiedAccountingAccountOutput:
- type: object
- properties: {}
- UnifiedAccountingAccountInput:
- type: object
- properties: {}
- UnifiedAccountingAddressOutput:
- type: object
- properties: {}
- UnifiedAccountingAttachmentOutput:
- type: object
- properties: {}
- UnifiedAccountingAttachmentInput:
- type: object
- properties: {}
- UnifiedAccountingBalancesheetOutput:
- type: object
- properties: {}
- UnifiedAccountingCashflowstatementOutput:
- type: object
- properties: {}
- UnifiedAccountingCompanyinfoOutput:
- type: object
- properties: {}
- UnifiedAccountingContactOutput:
- type: object
- properties: {}
- UnifiedAccountingContactInput:
- type: object
- properties: {}
- UnifiedAccountingCreditnoteOutput:
- type: object
- properties: {}
- UnifiedAccountingExpenseOutput:
- type: object
- properties: {}
- UnifiedAccountingExpenseInput:
- type: object
- properties: {}
- UnifiedAccountingIncomestatementOutput:
- type: object
- properties: {}
- UnifiedAccountingInvoiceOutput:
- type: object
- properties: {}
- UnifiedAccountingInvoiceInput:
- type: object
- properties: {}
- UnifiedAccountingItemOutput:
- type: object
- properties: {}
- UnifiedAccountingJournalentryOutput:
- type: object
- properties: {}
- UnifiedAccountingJournalentryInput:
- type: object
- properties: {}
- UnifiedAccountingPaymentOutput:
- type: object
- properties: {}
- UnifiedAccountingPaymentInput:
- type: object
- properties: {}
- UnifiedAccountingPhonenumberOutput:
- type: object
- properties: {}
- UnifiedAccountingPurchaseorderOutput:
- type: object
- properties: {}
- UnifiedAccountingPurchaseorderInput:
- type: object
- properties: {}
- UnifiedAccountingTaxrateOutput:
- type: object
- properties: {}
- UnifiedAccountingTrackingcategoryOutput:
- type: object
- properties: {}
- UnifiedAccountingTransactionOutput:
- type: object
- properties: {}
- UnifiedAccountingVendorcreditOutput:
- type: object
- properties: {}
+ description: The remote data of the vendor credit in the context of the 3rd Party
UnifiedFilestorageDriveOutput:
type: object
properties:
@@ -29099,7 +36155,7 @@ components:
nullable: true
field_mappings:
type: object
- example: &ref_143
+ example: &ref_179
fav_dish: broccoli
fav_color: red
description: >-
@@ -29184,7 +36240,7 @@ components:
nullable: true
field_mappings:
type: object
- example: *ref_143
+ example: *ref_179
description: >-
The custom field mappings of the object between the remote 3rd party & Panora
nullable: true
@@ -29241,7 +36297,7 @@ components:
description: The UUID of the permission tied to the folder
field_mappings:
type: object
- example: &ref_144
+ example: &ref_180
fav_dish: broccoli
fav_color: red
additionalProperties: true
@@ -29331,7 +36387,7 @@ components:
description: The UUID of the permission tied to the folder
field_mappings:
type: object
- example: *ref_144
+ example: *ref_180
additionalProperties: true
nullable: true
description: >-
@@ -29492,13 +36548,13 @@ components:
type: string
example: ACTIVE
nullable: true
- enum: &ref_145
+ enum: &ref_181
- ARCHIVED
- ACTIVE
- DRAFT
description: The status of the product. Either ACTIVE, DRAFT OR ARCHIVED.
images_urls:
- example: &ref_146
+ example: &ref_182
- https://myproduct/image
nullable: true
description: The URLs of the product images
@@ -29516,7 +36572,7 @@ components:
nullable: true
description: The vendor of the product
variants:
- example: &ref_147
+ example: &ref_183
- title: teeshirt
price: 20
sku: '3'
@@ -29528,7 +36584,7 @@ components:
items:
$ref: '#/components/schemas/Variant'
tags:
- example: &ref_148
+ example: &ref_184
- tag_1
nullable: true
description: The tags associated with the product
@@ -29537,7 +36593,7 @@ components:
type: string
field_mappings:
type: object
- example: &ref_149
+ example: &ref_185
fav_dish: broccoli
fav_color: red
nullable: true
@@ -29587,10 +36643,10 @@ components:
type: string
example: ACTIVE
nullable: true
- enum: *ref_145
+ enum: *ref_181
description: The status of the product. Either ACTIVE, DRAFT OR ARCHIVED.
images_urls:
- example: *ref_146
+ example: *ref_182
nullable: true
description: The URLs of the product images
type: array
@@ -29607,13 +36663,13 @@ components:
nullable: true
description: The vendor of the product
variants:
- example: *ref_147
+ example: *ref_183
description: The variants of the product
type: array
items:
$ref: '#/components/schemas/Variant'
tags:
- example: *ref_148
+ example: *ref_184
nullable: true
description: The tags associated with the product
type: array
@@ -29621,20 +36677,17 @@ components:
type: string
field_mappings:
type: object
- example: *ref_149
+ example: *ref_185
nullable: true
description: >-
The custom field mappings of the object between the remote 3rd party & Panora
- LineItem:
- type: object
- properties: {}
UnifiedEcommerceOrderOutput:
type: object
properties:
order_status:
type: string
example: UNSHIPPED
- enum: &ref_150
+ enum: &ref_186
- PENDING
- UNSHIPPED
- SHIPPED
@@ -29649,7 +36702,7 @@ components:
payment_status:
type: string
example: SUCCESS
- enum: &ref_151
+ enum: &ref_187
- SUCCESS
- FAIL
nullable: true
@@ -29658,7 +36711,7 @@ components:
type: string
nullable: true
example: AUD
- enum: &ref_152
+ enum: &ref_188
- AED
- AFN
- ALL
@@ -29847,7 +36900,7 @@ components:
type: string
nullable: true
example: PENDING
- enum: &ref_153
+ enum: &ref_189
- PENDING
- FULFILLED
- CANCELED
@@ -29859,7 +36912,7 @@ components:
description: The UUID of the customer associated with the order
items:
nullable: true
- example: &ref_154
+ example: &ref_190
- remote_id: '12345'
product_id: prod_001
variant_id: var_001
@@ -29890,7 +36943,7 @@ components:
$ref: '#/components/schemas/LineItem'
field_mappings:
type: object
- example: &ref_155
+ example: &ref_191
fav_dish: broccoli
fav_color: red
nullable: true
@@ -29929,7 +36982,7 @@ components:
order_status:
type: string
example: UNSHIPPED
- enum: *ref_150
+ enum: *ref_186
nullable: true
description: The status of the order
order_number:
@@ -29940,14 +36993,14 @@ components:
payment_status:
type: string
example: SUCCESS
- enum: *ref_151
+ enum: *ref_187
nullable: true
description: The payment status of the order
currency:
type: string
nullable: true
example: AUD
- enum: *ref_152
+ enum: *ref_188
description: >-
The currency of the order. Authorized value must be of type CurrencyCode (ISO 4217)
total_price:
@@ -29974,7 +37027,7 @@ components:
type: string
nullable: true
example: PENDING
- enum: *ref_153
+ enum: *ref_189
description: The fulfillment status of the order
customer_id:
type: string
@@ -29983,14 +37036,14 @@ components:
description: The UUID of the customer associated with the order
items:
nullable: true
- example: *ref_154
+ example: *ref_190
description: The items in the order
type: array
items:
$ref: '#/components/schemas/LineItem'
field_mappings:
type: object
- example: *ref_155
+ example: *ref_191
nullable: true
description: >-
The custom field mappings of the object between the remote 3rd party & Panora
@@ -30164,7 +37217,7 @@ components:
field_mappings:
type: object
nullable: true
- example: &ref_156
+ example: &ref_192
fav_dish: broccoli
fav_color: red
description: >-
@@ -30235,7 +37288,7 @@ components:
field_mappings:
type: object
nullable: true
- example: *ref_156
+ example: *ref_192
description: >-
The custom field mappings of the attachment between the remote 3rd party & Panora
additionalProperties: true
From 2e62b82a3fe2149a5ec8a1baaaa17d0e9cf397a5 Mon Sep 17 00:00:00 2001
From: nael
Date: Fri, 16 Aug 2024 02:26:22 +0200
Subject: [PATCH 03/49] :sparkles: Deel + sage hris integrations
---
.../hris/hris.connection.module.ts | 2 +
.../hris/services/sage/sage.service.ts | 143 +++++++++++++++
.../utils/types/original/original.hris.ts | 31 +++-
packages/api/src/hris/@lib/@utils/index.ts | 15 ++
.../api/src/hris/company/company.module.ts | 4 +
.../src/hris/company/services/deel/index.ts | 72 ++++++++
.../src/hris/company/services/deel/mappers.ts | 70 ++++++++
.../src/hris/company/services/deel/types.ts | 7 +
.../api/src/hris/employee/employee.module.ts | 8 +
.../src/hris/employee/services/deel/index.ts | 60 +++++++
.../hris/employee/services/deel/mappers.ts | 170 ++++++++++++++++++
.../src/hris/employee/services/deel/types.ts | 100 +++++++++++
.../src/hris/employee/services/sage/index.ts | 58 ++++++
.../hris/employee/services/sage/mappers.ts | 115 ++++++++++++
.../src/hris/employee/services/sage/types.ts | 55 ++++++
.../src/hris/employment/employment.module.ts | 2 +
.../hris/employment/services/deel/mappers.ts | 136 ++++++++++++++
.../hris/employment/services/deel/types.ts | 50 ++++++
packages/api/src/hris/group/group.module.ts | 8 +
.../api/src/hris/group/services/deel/index.ts | 66 +++++++
.../src/hris/group/services/deel/mappers.ts | 61 +++++++
.../api/src/hris/group/services/deel/types.ts | 4 +
.../api/src/hris/group/services/sage/index.ts | 66 +++++++
.../src/hris/group/services/sage/mappers.ts | 61 +++++++
.../api/src/hris/group/services/sage/types.ts | 6 +
.../api/src/hris/location/location.module.ts | 2 +
.../hris/location/services/deel/mappers.ts | 70 ++++++++
.../src/hris/location/services/deel/types.ts | 8 +
.../src/hris/timeoff/services/sage/index.ts | 69 +++++++
.../src/hris/timeoff/services/sage/mappers.ts | 115 ++++++++++++
.../src/hris/timeoff/services/sage/types.ts | 30 ++++
.../api/src/hris/timeoff/timeoff.module.ts | 4 +
.../timeoffbalance/services/sage/index.ts | 72 ++++++++
.../timeoffbalance/services/sage/mappers.ts | 73 ++++++++
.../timeoffbalance/services/sage/types.ts | 5 +
.../timeoffbalance/timeoffbalance.module.ts | 4 +
packages/shared/src/connectors/metadata.ts | 44 +++--
37 files changed, 1846 insertions(+), 20 deletions(-)
create mode 100644 packages/api/src/@core/connections/hris/services/sage/sage.service.ts
create mode 100644 packages/api/src/hris/company/services/deel/index.ts
create mode 100644 packages/api/src/hris/company/services/deel/mappers.ts
create mode 100644 packages/api/src/hris/company/services/deel/types.ts
create mode 100644 packages/api/src/hris/employee/services/deel/index.ts
create mode 100644 packages/api/src/hris/employee/services/deel/mappers.ts
create mode 100644 packages/api/src/hris/employee/services/deel/types.ts
create mode 100644 packages/api/src/hris/employee/services/sage/index.ts
create mode 100644 packages/api/src/hris/employee/services/sage/mappers.ts
create mode 100644 packages/api/src/hris/employee/services/sage/types.ts
create mode 100644 packages/api/src/hris/employment/services/deel/mappers.ts
create mode 100644 packages/api/src/hris/employment/services/deel/types.ts
create mode 100644 packages/api/src/hris/group/services/deel/index.ts
create mode 100644 packages/api/src/hris/group/services/deel/mappers.ts
create mode 100644 packages/api/src/hris/group/services/deel/types.ts
create mode 100644 packages/api/src/hris/group/services/sage/index.ts
create mode 100644 packages/api/src/hris/group/services/sage/mappers.ts
create mode 100644 packages/api/src/hris/group/services/sage/types.ts
create mode 100644 packages/api/src/hris/location/services/deel/mappers.ts
create mode 100644 packages/api/src/hris/location/services/deel/types.ts
create mode 100644 packages/api/src/hris/timeoff/services/sage/index.ts
create mode 100644 packages/api/src/hris/timeoff/services/sage/mappers.ts
create mode 100644 packages/api/src/hris/timeoff/services/sage/types.ts
create mode 100644 packages/api/src/hris/timeoffbalance/services/sage/index.ts
create mode 100644 packages/api/src/hris/timeoffbalance/services/sage/mappers.ts
create mode 100644 packages/api/src/hris/timeoffbalance/services/sage/types.ts
diff --git a/packages/api/src/@core/connections/hris/hris.connection.module.ts b/packages/api/src/@core/connections/hris/hris.connection.module.ts
index 6c70292b3..da5e50d4a 100644
--- a/packages/api/src/@core/connections/hris/hris.connection.module.ts
+++ b/packages/api/src/@core/connections/hris/hris.connection.module.ts
@@ -13,6 +13,7 @@ import { NamelyConnectionService } from './services/namely/namely.service';
import { PayfitConnectionService } from './services/payfit/payfit.service';
import { ServiceRegistry } from './services/registry.service';
import { RipplingConnectionService } from './services/rippling/rippling.service';
+import { SageConnectionService } from './services/sage/sage.service';
@Module({
imports: [WebhookModule, BullQueueModule],
@@ -30,6 +31,7 @@ import { RipplingConnectionService } from './services/rippling/rippling.service'
FactorialConnectionService,
NamelyConnectionService,
BamboohrConnectionService,
+ SageConnectionService,
],
exports: [HrisConnectionsService],
})
diff --git a/packages/api/src/@core/connections/hris/services/sage/sage.service.ts b/packages/api/src/@core/connections/hris/services/sage/sage.service.ts
new file mode 100644
index 000000000..cbcdf1199
--- /dev/null
+++ b/packages/api/src/@core/connections/hris/services/sage/sage.service.ts
@@ -0,0 +1,143 @@
+import { EncryptionService } from '@@core/@core-services/encryption/encryption.service';
+import { LoggerService } from '@@core/@core-services/logger/logger.service';
+import { PrismaService } from '@@core/@core-services/prisma/prisma.service';
+import { RetryHandler } from '@@core/@core-services/request-retry/retry.handler';
+import { ConnectionsStrategiesService } from '@@core/connections-strategies/connections-strategies.service';
+import { ConnectionUtils } from '@@core/connections/@utils';
+import {
+ AbstractBaseConnectionService,
+ OAuthCallbackParams,
+ PassthroughInput,
+ RefreshParams,
+} from '@@core/connections/@utils/types';
+import { PassthroughResponse } from '@@core/passthrough/types';
+import { Injectable } from '@nestjs/common';
+import {
+ AuthStrategy,
+ CONNECTORS_METADATA,
+ DynamicApiUrl,
+ providerToType,
+} from '@panora/shared';
+import { v4 as uuidv4 } from 'uuid';
+import { ServiceRegistry } from '../registry.service';
+
+@Injectable()
+export class SageConnectionService extends AbstractBaseConnectionService {
+ private readonly type: string;
+
+ constructor(
+ protected prisma: PrismaService,
+ private logger: LoggerService,
+ protected cryptoService: EncryptionService,
+ private registry: ServiceRegistry,
+ private connectionUtils: ConnectionUtils,
+ private cService: ConnectionsStrategiesService,
+ private retryService: RetryHandler,
+ ) {
+ super(prisma, cryptoService);
+ this.logger.setContext(SageConnectionService.name);
+ this.registry.registerService('sage', this);
+ this.type = providerToType('sage', 'hris', AuthStrategy.oauth2);
+ }
+
+ async passthrough(
+ input: PassthroughInput,
+ connectionId: string,
+ ): Promise {
+ try {
+ const { headers } = input;
+ const config = await this.constructPassthrough(input, connectionId);
+
+ const connection = await this.prisma.connections.findUnique({
+ where: {
+ id_connection: connectionId,
+ },
+ });
+
+ config.headers = {
+ ...config.headers,
+ ...headers,
+ 'X-Auth-Token': this.cryptoService.decrypt(connection.access_token),
+ };
+
+ return await this.retryService.makeRequest(
+ {
+ method: config.method,
+ url: config.url,
+ data: config.data,
+ headers: config.headers,
+ },
+ 'hris.sage.passthrough',
+ config.linkedUserId,
+ );
+ } catch (error) {
+ throw error;
+ }
+ }
+
+ async handleCallback(opts: OAuthCallbackParams) {
+ try {
+ const { linkedUserId, projectId, body } = opts;
+ const { api_key, subdomain } = body;
+ const isNotUnique = await this.prisma.connections.findFirst({
+ where: {
+ id_linked_user: linkedUserId,
+ provider_slug: 'sage',
+ vertical: 'hris',
+ },
+ });
+
+ let db_res;
+ const connection_token = uuidv4();
+ const BASE_API_URL = (
+ CONNECTORS_METADATA['hris']['sage'].urls.apiUrl as DynamicApiUrl
+ )(subdomain);
+
+ if (isNotUnique) {
+ db_res = await this.prisma.connections.update({
+ where: {
+ id_connection: isNotUnique.id_connection,
+ },
+ data: {
+ access_token: this.cryptoService.encrypt(api_key),
+ account_url: BASE_API_URL,
+ status: 'valid',
+ created_at: new Date(),
+ },
+ });
+ } else {
+ db_res = await this.prisma.connections.create({
+ data: {
+ id_connection: uuidv4(),
+ connection_token: connection_token,
+ provider_slug: 'sage',
+ vertical: 'hris',
+ token_type: 'basic',
+ account_url: BASE_API_URL,
+ access_token: this.cryptoService.encrypt(api_key),
+ status: 'valid',
+ created_at: new Date(),
+ projects: {
+ connect: { id_project: projectId },
+ },
+ linked_users: {
+ connect: {
+ id_linked_user: await this.connectionUtils.getLinkedUserId(
+ projectId,
+ linkedUserId,
+ ),
+ },
+ },
+ },
+ });
+ }
+ return db_res;
+ } catch (error) {
+ throw error;
+ }
+ }
+
+ handleTokenRefresh?(opts: RefreshParams): Promise {
+ throw new Error('Method not implemented.');
+ }
+}
diff --git a/packages/api/src/@core/utils/types/original/original.hris.ts b/packages/api/src/@core/utils/types/original/original.hris.ts
index e85d40144..df980dafa 100644
--- a/packages/api/src/@core/utils/types/original/original.hris.ts
+++ b/packages/api/src/@core/utils/types/original/original.hris.ts
@@ -1,12 +1,21 @@
/* INPUT */
import { GustoBenefitOutput } from '@hris/benefit/services/gusto/types';
+import { DeelCompanyOutput } from '@hris/company/services/deel/types';
import { GustoCompanyOutput } from '@hris/company/services/gusto/types';
+import { DeelEmployeeOutput } from '@hris/employee/services/deel/types';
import { GustoEmployeeOutput } from '@hris/employee/services/gusto/types';
+import { SageEmployeeOutput } from '@hris/employee/services/sage/types';
import { GustoEmployerbenefitOutput } from '@hris/employerbenefit/services/gusto/types';
+import { DeelEmploymentOutput } from '@hris/employment/services/deel/types';
import { GustoEmploymentOutput } from '@hris/employment/services/gusto/types';
+import { DeelGroupOutput } from '@hris/group/services/deel/types';
import { GustoGroupOutput } from '@hris/group/services/gusto/types';
+import { SageGroupOutput } from '@hris/group/services/sage/types';
+import { DeelLocationOutput } from '@hris/location/services/deel/types';
import { GustoLocationOutput } from '@hris/location/services/gusto/types';
+import { SageTimeoffOutput } from '@hris/timeoff/services/sage/types';
+import { SageTimeoffbalanceOutput } from '@hris/timeoffbalance/services/sage/types';
/* bankinfo */
export type OriginalBankInfoInput = any;
@@ -79,13 +88,16 @@ export type OriginalBankInfoOutput = any;
export type OriginalBenefitOutput = GustoBenefitOutput;
/* company */
-export type OriginalCompanyOutput = GustoCompanyOutput;
+export type OriginalCompanyOutput = GustoCompanyOutput | DeelCompanyOutput;
/* dependent */
export type OriginalDependentOutput = any;
/* employee */
-export type OriginalEmployeeOutput = GustoEmployeeOutput;
+export type OriginalEmployeeOutput =
+ | GustoEmployeeOutput
+ | SageEmployeeOutput
+ | DeelEmployeeOutput;
/* employeepayrollrun */
export type OriginalEmployeePayrollRunOutput = any;
@@ -94,13 +106,18 @@ export type OriginalEmployeePayrollRunOutput = any;
export type OriginalEmployerBenefitOutput = GustoEmployerbenefitOutput;
/* employment */
-export type OriginalEmploymentOutput = GustoEmploymentOutput;
+export type OriginalEmploymentOutput =
+ | GustoEmploymentOutput
+ | DeelEmploymentOutput;
/* group */
-export type OriginalGroupOutput = GustoGroupOutput;
+export type OriginalGroupOutput =
+ | GustoGroupOutput
+ | DeelGroupOutput
+ | SageGroupOutput;
/* location */
-export type OriginalLocationOutput = GustoLocationOutput;
+export type OriginalLocationOutput = GustoLocationOutput | DeelLocationOutput;
/* paygroup */
export type OriginalPayGroupOutput = any;
@@ -109,10 +126,10 @@ export type OriginalPayGroupOutput = any;
export type OriginalPayrollRunOutput = any;
/* timeoff */
-export type OriginalTimeoffOutput = any;
+export type OriginalTimeoffOutput = SageTimeoffOutput;
/* timeoffbalance */
-export type OriginalTimeoffBalanceOutput = any;
+export type OriginalTimeoffBalanceOutput = SageTimeoffbalanceOutput;
/* timesheetentry */
export type OriginalTimesheetentryOutput = any;
diff --git a/packages/api/src/hris/@lib/@utils/index.ts b/packages/api/src/hris/@lib/@utils/index.ts
index 23b09c261..d4b9be7af 100644
--- a/packages/api/src/hris/@lib/@utils/index.ts
+++ b/packages/api/src/hris/@lib/@utils/index.ts
@@ -35,6 +35,21 @@ export class Utils {
}
}
+ async getGroupUuidFromRemoteId(id: string, connection_id: string) {
+ try {
+ const res = await this.prisma.hris_groups.findFirst({
+ where: {
+ remote_id: id,
+ id_connection: connection_id,
+ },
+ });
+ if (!res) return;
+ return res.id_hris_group;
+ } catch (error) {
+ throw error;
+ }
+ }
+
async getEmployerBenefitUuidFromRemoteId(id: string, connection_id: string) {
try {
const res = await this.prisma.hris_employer_benefits.findFirst({
diff --git a/packages/api/src/hris/company/company.module.ts b/packages/api/src/hris/company/company.module.ts
index eae8227f4..a1cfc0614 100644
--- a/packages/api/src/hris/company/company.module.ts
+++ b/packages/api/src/hris/company/company.module.ts
@@ -9,6 +9,8 @@ import { CoreUnification } from '@@core/@core-services/unification/core-unificat
import { GustoCompanyMapper } from './services/gusto/mappers';
import { GustoService } from './services/gusto';
import { Utils } from '@hris/@lib/@utils';
+import { DeelService } from './services/deel';
+import { DeelCompanyMapper } from './services/deel/mappers';
@Module({
controllers: [CompanyController],
providers: [
@@ -20,8 +22,10 @@ import { Utils } from '@hris/@lib/@utils';
ServiceRegistry,
IngestDataService,
GustoCompanyMapper,
+ DeelCompanyMapper,
/* PROVIDERS SERVICES */
GustoService,
+ DeelService,
],
exports: [SyncService],
})
diff --git a/packages/api/src/hris/company/services/deel/index.ts b/packages/api/src/hris/company/services/deel/index.ts
new file mode 100644
index 000000000..6eb47d4ea
--- /dev/null
+++ b/packages/api/src/hris/company/services/deel/index.ts
@@ -0,0 +1,72 @@
+import { EncryptionService } from '@@core/@core-services/encryption/encryption.service';
+import { EnvironmentService } from '@@core/@core-services/environment/environment.service';
+import { LoggerService } from '@@core/@core-services/logger/logger.service';
+import { PrismaService } from '@@core/@core-services/prisma/prisma.service';
+import { ApiResponse } from '@@core/utils/types';
+import { SyncParam } from '@@core/utils/types/interface';
+import { HrisObject } from '@hris/@lib/@types';
+import { ICompanyService } from '@hris/company/types';
+import { Injectable } from '@nestjs/common';
+import axios from 'axios';
+import { ServiceRegistry } from '../registry.service';
+import { DeelCompanyOutput } from './types';
+import { DesunifyReturnType } from '@@core/utils/types/desunify.input';
+import { OriginalCompanyOutput } from '@@core/utils/types/original/original.hris';
+
+@Injectable()
+export class DeelService implements ICompanyService {
+ constructor(
+ private prisma: PrismaService,
+ private logger: LoggerService,
+ private cryptoService: EncryptionService,
+ private env: EnvironmentService,
+ private registry: ServiceRegistry,
+ ) {
+ this.logger.setContext(
+ HrisObject.company.toUpperCase() + ':' + DeelService.name,
+ );
+ this.registry.registerService('deel', this);
+ }
+
+ addCompany(
+ companyData: DesunifyReturnType,
+ linkedUserId: string,
+ ): Promise> {
+ throw new Error('Method not implemented.');
+ }
+
+ async sync(data: SyncParam): Promise> {
+ try {
+ const { linkedUserId } = data;
+
+ const connection = await this.prisma.connections.findFirst({
+ where: {
+ id_linked_user: linkedUserId,
+ provider_slug: 'deel',
+ vertical: 'hris',
+ },
+ });
+
+ const resp = await axios.get(
+ `${connection.account_url}/rest/v2/legal-entities`,
+ {
+ headers: {
+ 'Content-Type': 'application/json',
+ Authorization: `Bearer ${this.cryptoService.decrypt(
+ connection.access_token,
+ )}`,
+ },
+ },
+ );
+ this.logger.log(`Synced deel companys !`);
+
+ return {
+ data: resp.data.data,
+ message: 'Deel companys retrieved',
+ statusCode: 200,
+ };
+ } catch (error) {
+ throw error;
+ }
+ }
+}
diff --git a/packages/api/src/hris/company/services/deel/mappers.ts b/packages/api/src/hris/company/services/deel/mappers.ts
new file mode 100644
index 000000000..5bdc9293c
--- /dev/null
+++ b/packages/api/src/hris/company/services/deel/mappers.ts
@@ -0,0 +1,70 @@
+import { MappersRegistry } from '@@core/@core-services/registries/mappers.registry';
+import { CoreUnification } from '@@core/@core-services/unification/core-unification.service';
+import { IngestDataService } from '@@core/@core-services/unification/ingest-data.service';
+import { Injectable } from '@nestjs/common';
+import { DeelCompanyOutput } from './types';
+import {
+ UnifiedHrisCompanyInput,
+ UnifiedHrisCompanyOutput,
+} from '@hris/company/types/model.unified';
+import { ICompanyMapper } from '@hris/company/types';
+import { Utils } from '@hris/@lib/@utils';
+
+@Injectable()
+export class DeelCompanyMapper implements ICompanyMapper {
+ constructor(
+ private mappersRegistry: MappersRegistry,
+ private utils: Utils,
+ private ingestService: IngestDataService,
+ private coreUnificationService: CoreUnification,
+ ) {
+ this.mappersRegistry.registerService('hris', 'company', 'deel', this);
+ }
+
+ async desunify(
+ source: UnifiedHrisCompanyInput,
+ customFieldMappings?: { slug: string; remote_id: string }[],
+ ): Promise {
+ // Implementation for desunify (if needed)
+ return;
+ }
+
+ async unify(
+ source: DeelCompanyOutput | DeelCompanyOutput[],
+ connectionId: string,
+ customFieldMappings?: { slug: string; remote_id: string }[],
+ ): Promise {
+ if (!Array.isArray(source)) {
+ return this.mapSingleCompanyToUnified(
+ source,
+ connectionId,
+ customFieldMappings,
+ );
+ }
+ return Promise.all(
+ source.map((company) =>
+ this.mapSingleCompanyToUnified(
+ company,
+ connectionId,
+ customFieldMappings,
+ ),
+ ),
+ );
+ }
+
+ private async mapSingleCompanyToUnified(
+ company: DeelCompanyOutput,
+ connectionId: string,
+ customFieldMappings?: { slug: string; remote_id: string }[],
+ ): Promise {
+ return {
+ remote_id: company.id || null,
+ legal_name: company.name || null,
+ display_name: company.name || null, // Using name for display_name as well
+ eins: [], // Deel doesn't provide EINs in this data structure
+ remote_data: company,
+ locations: [], // Deel doesn't provide locations in this data structure
+ field_mappings: {},
+ };
+ }
+}
diff --git a/packages/api/src/hris/company/services/deel/types.ts b/packages/api/src/hris/company/services/deel/types.ts
new file mode 100644
index 000000000..ec793698b
--- /dev/null
+++ b/packages/api/src/hris/company/services/deel/types.ts
@@ -0,0 +1,7 @@
+export interface DeelCompanyOutput {
+ id: string;
+ name: string;
+ country: string;
+ entity_type: 'individual' | string;
+ entity_subtype: string;
+}
diff --git a/packages/api/src/hris/employee/employee.module.ts b/packages/api/src/hris/employee/employee.module.ts
index ed03dd83f..e01e841db 100644
--- a/packages/api/src/hris/employee/employee.module.ts
+++ b/packages/api/src/hris/employee/employee.module.ts
@@ -9,6 +9,10 @@ import { CoreUnification } from '@@core/@core-services/unification/core-unificat
import { GustoEmployeeMapper } from './services/gusto/mappers';
import { GustoService } from './services/gusto';
import { Utils } from '@hris/@lib/@utils';
+import { SageEmployeeMapper } from './services/sage/mappers';
+import { SageService } from './services/sage';
+import { DeelService } from './services/deel';
+import { DeelEmployeeMapper } from './services/deel/mappers';
@Module({
controllers: [EmployeeController],
providers: [
@@ -20,8 +24,12 @@ import { Utils } from '@hris/@lib/@utils';
ServiceRegistry,
IngestDataService,
GustoEmployeeMapper,
+ SageEmployeeMapper,
+ DeelEmployeeMapper,
/* PROVIDERS SERVICES */
GustoService,
+ SageService,
+ DeelService,
],
exports: [SyncService],
})
diff --git a/packages/api/src/hris/employee/services/deel/index.ts b/packages/api/src/hris/employee/services/deel/index.ts
new file mode 100644
index 000000000..966c3ff66
--- /dev/null
+++ b/packages/api/src/hris/employee/services/deel/index.ts
@@ -0,0 +1,60 @@
+import { EncryptionService } from '@@core/@core-services/encryption/encryption.service';
+import { EnvironmentService } from '@@core/@core-services/environment/environment.service';
+import { LoggerService } from '@@core/@core-services/logger/logger.service';
+import { PrismaService } from '@@core/@core-services/prisma/prisma.service';
+import { ApiResponse } from '@@core/utils/types';
+import { SyncParam } from '@@core/utils/types/interface';
+import { HrisObject } from '@hris/@lib/@types';
+import { IEmployeeService } from '@hris/employee/types';
+import { Injectable } from '@nestjs/common';
+import axios from 'axios';
+import { ServiceRegistry } from '../registry.service';
+import { DeelEmployeeOutput } from './types';
+
+@Injectable()
+export class DeelService implements IEmployeeService {
+ constructor(
+ private prisma: PrismaService,
+ private logger: LoggerService,
+ private cryptoService: EncryptionService,
+ private env: EnvironmentService,
+ private registry: ServiceRegistry,
+ ) {
+ this.logger.setContext(
+ HrisObject.employee.toUpperCase() + ':' + DeelService.name,
+ );
+ this.registry.registerService('deel', this);
+ }
+
+ async sync(data: SyncParam): Promise> {
+ try {
+ const { linkedUserId } = data;
+
+ const connection = await this.prisma.connections.findFirst({
+ where: {
+ id_linked_user: linkedUserId,
+ provider_slug: 'deel',
+ vertical: 'hris',
+ },
+ });
+
+ const resp = await axios.get(`${connection.account_url}/rest/v2/people`, {
+ headers: {
+ 'Content-Type': 'application/json',
+ Authorization: `Bearer ${this.cryptoService.decrypt(
+ connection.access_token,
+ )}`,
+ },
+ });
+ this.logger.log(`Synced deel employees !`);
+
+ return {
+ data: resp.data.data,
+ message: 'Deel employees retrieved',
+ statusCode: 200,
+ };
+ } catch (error) {
+ throw error;
+ }
+ }
+}
diff --git a/packages/api/src/hris/employee/services/deel/mappers.ts b/packages/api/src/hris/employee/services/deel/mappers.ts
new file mode 100644
index 000000000..0912bdb4d
--- /dev/null
+++ b/packages/api/src/hris/employee/services/deel/mappers.ts
@@ -0,0 +1,170 @@
+import { Injectable } from '@nestjs/common';
+import { MappersRegistry } from '@@core/@core-services/registries/mappers.registry';
+import { CoreUnification } from '@@core/@core-services/unification/core-unification.service';
+import { IngestDataService } from '@@core/@core-services/unification/ingest-data.service';
+import { DeelEmployeeOutput } from './types';
+import {
+ UnifiedHrisEmployeeInput,
+ UnifiedHrisEmployeeOutput,
+} from '@hris/employee/types/model.unified';
+import { IEmployeeMapper } from '@hris/employee/types';
+import { Utils } from '@hris/@lib/@utils';
+import { HrisObject } from '@panora/shared';
+import { UnifiedHrisEmploymentOutput } from '@hris/employment/types/model.unified';
+import { DeelEmploymentOutput } from '@hris/employment/services/deel/types';
+import { DeelLocationOutput } from '@hris/location/services/deel/types';
+import { UnifiedHrisLocationOutput } from '@hris/location/types/model.unified';
+
+@Injectable()
+export class DeelEmployeeMapper implements IEmployeeMapper {
+ constructor(
+ private mappersRegistry: MappersRegistry,
+ private utils: Utils,
+ private ingestService: IngestDataService,
+ private coreUnificationService: CoreUnification,
+ ) {
+ this.mappersRegistry.registerService('hris', 'employee', 'deel', this);
+ }
+
+ async desunify(
+ source: UnifiedHrisEmployeeInput,
+ customFieldMappings?: { slug: string; remote_id: string }[],
+ ): Promise {
+ // Implementation for desunify (if needed)
+ return;
+ }
+
+ async unify(
+ source: DeelEmployeeOutput | DeelEmployeeOutput[],
+ connectionId: string,
+ customFieldMappings?: { slug: string; remote_id: string }[],
+ ): Promise {
+ if (!Array.isArray(source)) {
+ return this.mapSingleEmployeeToUnified(
+ source,
+ connectionId,
+ customFieldMappings,
+ );
+ }
+ return Promise.all(
+ source.map((employee) =>
+ this.mapSingleEmployeeToUnified(
+ employee,
+ connectionId,
+ customFieldMappings,
+ ),
+ ),
+ );
+ }
+
+ private async mapSingleEmployeeToUnified(
+ employee: DeelEmployeeOutput,
+ connectionId: string,
+ customFieldMappings?: { slug: string; remote_id: string }[],
+ ): Promise {
+ const opts: any = {};
+
+ if (employee.client_legal_entity) {
+ const company_id = await this.utils.getCompanyUuidFromRemoteId(
+ employee.client_legal_entity.id, // Assuming client_legal_entity has an id field
+ connectionId,
+ );
+ if (company_id) {
+ opts.company_id = company_id;
+ }
+ }
+
+ if (employee.direct_manager) {
+ const manager_id = await this.utils.getEmployeeUuidFromRemoteId(
+ employee.direct_manager.id,
+ connectionId,
+ );
+ if (manager_id) {
+ opts.manager_id = manager_id;
+ }
+ }
+
+ if (employee.employments) {
+ const employments = await this.ingestService.ingestData<
+ UnifiedHrisEmploymentOutput,
+ DeelEmploymentOutput
+ >(
+ employee.employments,
+ 'deel',
+ connectionId,
+ 'hris',
+ HrisObject.employment,
+ [],
+ );
+ if (employments) {
+ opts.employments = employments.map((emp) => emp.id_hris_employment);
+ }
+ }
+
+ if (employee.addresses) {
+ const addresses = await this.ingestService.ingestData<
+ UnifiedHrisLocationOutput,
+ DeelLocationOutput
+ >(
+ employee.addresses.map((add) => {
+ return {
+ ...add,
+ type: 'HOME',
+ };
+ }),
+ 'deel',
+ connectionId,
+ 'hris',
+ HrisObject.location,
+ [],
+ );
+ if (addresses) {
+ opts.locations = addresses.map((add) => add.id_hris_location);
+ }
+ }
+
+ const primaryEmployment = employee.employments.find((emp) => !emp.is_ended);
+
+ return {
+ remote_id: employee.id,
+ remote_data: employee,
+ first_name: employee.first_name,
+ last_name: employee.last_name,
+ preferred_name: null, // Deel doesn't provide this information
+ display_full_name: employee.full_name,
+ work_email:
+ employee.emails.find((email) => email.type === 'work')?.value || null,
+ personal_email:
+ employee.emails.find((email) => email.type === 'personal')?.value ||
+ null,
+ mobile_phone_number: null, // Deel doesn't provide this information in the given structure
+ start_date: primaryEmployment
+ ? new Date(primaryEmployment.start_date)
+ : null,
+ termination_date: employee.completion_date
+ ? new Date(employee.completion_date)
+ : null,
+ employment_status: this.mapEmploymentStatus(employee.hiring_status),
+ date_of_birth: employee.birth_date ? new Date(employee.birth_date) : null,
+ avatar_url: null, // Deel doesn't provide this information in the given structure
+ gender: null, // Deel doesn't provide this information in the given structure
+ ethnicity: null, // Deel doesn't provide this information in the given structure
+ marital_status: null, // Deel doesn't provide this information in the given structure
+ job_title: primaryEmployment ? primaryEmployment.job_title : null,
+ ...opts,
+ };
+ }
+
+ private mapEmploymentStatus(
+ status: string,
+ ): 'ACTIVE' | 'PENDING' | 'INACTIVE' {
+ switch (status.toUpperCase()) {
+ case 'ACTIVE':
+ return 'ACTIVE';
+ case 'PENDING':
+ return 'PENDING';
+ default:
+ return 'INACTIVE';
+ }
+ }
+}
diff --git a/packages/api/src/hris/employee/services/deel/types.ts b/packages/api/src/hris/employee/services/deel/types.ts
new file mode 100644
index 000000000..65eb03f3d
--- /dev/null
+++ b/packages/api/src/hris/employee/services/deel/types.ts
@@ -0,0 +1,100 @@
+export type DeelEmployeeOutput = Partial<{
+ id: string;
+ created_at: string; // Date-time in string format
+ first_name: string;
+ last_name: string;
+ full_name: string;
+ addresses: DeelAddress[];
+ emails: DeelEmail[];
+ birth_date: string;
+ start_date: string; // Date in string format
+ nationalities: string[];
+ client_legal_entity: DeelClientLegalEntity;
+ state: string;
+ seniority: string;
+ completion_date: string | null;
+ direct_manager: DeelDirectManager | null;
+ direct_reports: DeelDirectManager[] | null;
+ direct_reports_count: number;
+ employments: DeelEmployment[];
+ hiring_status: string;
+ new_hiring_status: string;
+ hiring_type: string;
+ job_title: string;
+ country: string;
+ timezone: string;
+ department: DeelDepartment;
+ work_location: string;
+ updated_at: string | null; // Date-time in string format
+}>;
+
+export interface DeelAddress {
+ streetAddress: string;
+ locality: string;
+ region: string;
+ postalCode: string;
+ country: string;
+}
+
+export interface DeelEmail {
+ type: string;
+ value: string;
+}
+
+export interface DeelClientLegalEntity {
+ id: string;
+ name: string;
+}
+
+export interface DeelDirectManager {
+ id: string;
+ last_name: string;
+ first_name: string;
+ work_email: string;
+}
+
+export interface DeelTeam {
+ id: string;
+ name: string;
+}
+
+export interface DeelPayment {
+ rate: number;
+ scale: string;
+ currency: string;
+ contract_name: string;
+}
+export interface DeelDepartment {
+ id: string;
+ name: string;
+ parent: string;
+}
+
+export interface DeelEmployment {
+ id: string;
+ name: string;
+ team: DeelTeam;
+ email: string;
+ state: string;
+ country: string;
+ payment: DeelPayment;
+ is_ended: boolean;
+ timezone: string;
+ job_title: string;
+ seniority: string;
+ start_date: string; // Date in string format
+ work_email: string;
+ hiring_type: string;
+ hiring_status: string;
+ completion_date: string;
+ contract_status: string;
+ voluntarily_left: string;
+ contract_coverage: string[];
+ new_hiring_status: string;
+ client_legal_entity: DeelClientLegalEntity;
+ has_eor_termination: string;
+ contract_is_archived: boolean;
+ contract_has_contractor: boolean;
+ is_user_contract_deleted: boolean;
+ hris_direct_employee_invitation: string;
+}
diff --git a/packages/api/src/hris/employee/services/sage/index.ts b/packages/api/src/hris/employee/services/sage/index.ts
new file mode 100644
index 000000000..be8e2937c
--- /dev/null
+++ b/packages/api/src/hris/employee/services/sage/index.ts
@@ -0,0 +1,58 @@
+import { EncryptionService } from '@@core/@core-services/encryption/encryption.service';
+import { EnvironmentService } from '@@core/@core-services/environment/environment.service';
+import { LoggerService } from '@@core/@core-services/logger/logger.service';
+import { PrismaService } from '@@core/@core-services/prisma/prisma.service';
+import { ApiResponse } from '@@core/utils/types';
+import { SyncParam } from '@@core/utils/types/interface';
+import { HrisObject } from '@hris/@lib/@types';
+import { IEmployeeService } from '@hris/employee/types';
+import { Injectable } from '@nestjs/common';
+import axios from 'axios';
+import { ServiceRegistry } from '../registry.service';
+import { SageEmployeeOutput } from './types';
+
+@Injectable()
+export class SageService implements IEmployeeService {
+ constructor(
+ private prisma: PrismaService,
+ private logger: LoggerService,
+ private cryptoService: EncryptionService,
+ private env: EnvironmentService,
+ private registry: ServiceRegistry,
+ ) {
+ this.logger.setContext(
+ HrisObject.employee.toUpperCase() + ':' + SageService.name,
+ );
+ this.registry.registerService('sage', this);
+ }
+
+ async sync(data: SyncParam): Promise> {
+ try {
+ const { linkedUserId } = data;
+
+ const connection = await this.prisma.connections.findFirst({
+ where: {
+ id_linked_user: linkedUserId,
+ provider_slug: 'sage',
+ vertical: 'hris',
+ },
+ });
+
+ const resp = await axios.get(`${connection.account_url}/api/employees`, {
+ headers: {
+ 'Content-Type': 'application/json',
+ 'X-Auth-Token': this.cryptoService.decrypt(connection.access_token),
+ },
+ });
+ this.logger.log(`Synced sage employees !`);
+
+ return {
+ data: resp.data.data,
+ message: 'Sage employees retrieved',
+ statusCode: 200,
+ };
+ } catch (error) {
+ throw error;
+ }
+ }
+}
diff --git a/packages/api/src/hris/employee/services/sage/mappers.ts b/packages/api/src/hris/employee/services/sage/mappers.ts
new file mode 100644
index 000000000..3c0064346
--- /dev/null
+++ b/packages/api/src/hris/employee/services/sage/mappers.ts
@@ -0,0 +1,115 @@
+import { MappersRegistry } from '@@core/@core-services/registries/mappers.registry';
+import { CoreUnification } from '@@core/@core-services/unification/core-unification.service';
+import { IngestDataService } from '@@core/@core-services/unification/ingest-data.service';
+import { Utils } from '@hris/@lib/@utils';
+import { IEmployeeMapper } from '@hris/employee/types';
+import {
+ EmploymentStatus,
+ Gender,
+ MartialStatus,
+ UnifiedHrisEmployeeInput,
+ UnifiedHrisEmployeeOutput,
+} from '@hris/employee/types/model.unified';
+import { Injectable } from '@nestjs/common';
+import { SageEmployeeOutput } from './types';
+
+@Injectable()
+export class SageEmployeeMapper implements IEmployeeMapper {
+ constructor(
+ private mappersRegistry: MappersRegistry,
+ private utils: Utils,
+ private ingestService: IngestDataService,
+ private coreUnificationService: CoreUnification,
+ ) {
+ this.mappersRegistry.registerService('hris', 'employee', 'sage', this);
+ }
+
+ async desunify(
+ source: UnifiedHrisEmployeeInput,
+ customFieldMappings?: { slug: string; remote_id: string }[],
+ ): Promise {
+ // Implementation for desunify (if needed)
+ return;
+ }
+
+ async unify(
+ source: SageEmployeeOutput | SageEmployeeOutput[],
+ connectionId: string,
+ customFieldMappings?: { slug: string; remote_id: string }[],
+ ): Promise {
+ if (!Array.isArray(source)) {
+ return this.mapSingleEmployeeToUnified(
+ source,
+ connectionId,
+ customFieldMappings,
+ );
+ }
+ return Promise.all(
+ source.map((employee) =>
+ this.mapSingleEmployeeToUnified(
+ employee,
+ connectionId,
+ customFieldMappings,
+ ),
+ ),
+ );
+ }
+
+ private async mapSingleEmployeeToUnified(
+ employee: SageEmployeeOutput,
+ connectionId: string,
+ customFieldMappings?: { slug: string; remote_id: string }[],
+ ): Promise {
+ return {
+ remote_id: employee.id.toString(),
+ remote_data: employee,
+ first_name: employee.first_name,
+ last_name: employee.last_name,
+ display_full_name: `${employee.first_name} ${employee.last_name}`,
+ work_email: employee.email,
+ mobile_phone_number: employee.mobile_phone,
+ employments: [], // We would need to process employment history to populate this
+ groups: [employee.team],
+ start_date: new Date(employee.employment_start_date),
+ employment_status: this.mapEmploymentStatus(employee.employment_status),
+ date_of_birth: new Date(employee.date_of_birth),
+ gender: this.mapGender(employee.gender),
+ marital_status: this.mapMaritalStatus(employee.marital_status),
+ avatar_url: employee.picture_url,
+ ssn: employee.personal_identification_number,
+ employee_number: employee.employee_number,
+ };
+ }
+
+ private mapGender(sageGender: string): Gender {
+ switch (sageGender.toLowerCase()) {
+ case 'male':
+ return 'MALE';
+ case 'female':
+ return 'FEMALE';
+ default:
+ return 'OTHER';
+ }
+ }
+
+ private mapMaritalStatus(sageMaritalStatus: string): MartialStatus {
+ switch (sageMaritalStatus.toLowerCase()) {
+ case 'married':
+ return 'MARRIED_FILING_JOINTLY';
+ case 'single':
+ return 'SINGLE';
+ default:
+ return 'SINGLE'; // Default to single if unknown
+ }
+ }
+
+ private mapEmploymentStatus(sageEmploymentStatus: string): EmploymentStatus {
+ switch (sageEmploymentStatus.toLowerCase()) {
+ case 'full-time':
+ case 'part-time':
+ return 'ACTIVE';
+ default:
+ return 'INACTIVE';
+ }
+ }
+}
diff --git a/packages/api/src/hris/employee/services/sage/types.ts b/packages/api/src/hris/employee/services/sage/types.ts
new file mode 100644
index 000000000..c4f986e70
--- /dev/null
+++ b/packages/api/src/hris/employee/services/sage/types.ts
@@ -0,0 +1,55 @@
+export type SageEmployeeOutput = Partial<{
+ id: number;
+ email: string;
+ first_name: string;
+ last_name: string;
+ picture_url: string;
+ employment_start_date: string;
+ date_of_birth: string;
+ team: string;
+ team_id: number;
+ position: string;
+ position_id: number;
+ reports_to_employee_id: number;
+ work_phone: string;
+ home_phone: string;
+ mobile_phone: string;
+ gender: string;
+ street_first: string;
+ street_second: string;
+ city: string;
+ post_code: number;
+ country: string;
+ employee_number: string;
+ employment_status: string;
+ nationality: string;
+ marital_status: string;
+ personal_identification_number: string;
+ tax_number: string;
+ irregular_contract_worker: boolean;
+ team_history: SageTeamHistory[];
+ employment_status_history: SageEmploymentStatusHistory[];
+ position_history: SagePositionHistory[];
+}>;
+
+export interface SageTeamHistory {
+ team_id: number;
+ start_date: string;
+ end_date: string;
+ team_name: string;
+}
+
+export interface SageEmploymentStatusHistory {
+ employment_status_id: number;
+ start_date: string;
+ end_date: string;
+ employment_statu_name: string; // Note: This seems to be a typo in the original data
+}
+
+export interface SagePositionHistory {
+ position_id: number;
+ start_date: string;
+ end_date: string;
+ position_name: string;
+ position_code: string;
+}
diff --git a/packages/api/src/hris/employment/employment.module.ts b/packages/api/src/hris/employment/employment.module.ts
index e5d64d523..2ef02de82 100644
--- a/packages/api/src/hris/employment/employment.module.ts
+++ b/packages/api/src/hris/employment/employment.module.ts
@@ -8,6 +8,7 @@ import { WebhookService } from '@@core/@core-services/webhooks/panora-webhooks/w
import { CoreUnification } from '@@core/@core-services/unification/core-unification.service';
import { GustoEmploymentMapper } from './services/gusto/mappers';
import { Utils } from '@hris/@lib/@utils';
+import { DeelEmploymentMapper } from './services/deel/mappers';
@Module({
controllers: [EmploymentController],
providers: [
@@ -19,6 +20,7 @@ import { Utils } from '@hris/@lib/@utils';
IngestDataService,
Utils,
GustoEmploymentMapper,
+ DeelEmploymentMapper,
/* PROVIDERS SERVICES */
],
exports: [SyncService],
diff --git a/packages/api/src/hris/employment/services/deel/mappers.ts b/packages/api/src/hris/employment/services/deel/mappers.ts
new file mode 100644
index 000000000..bb892abf0
--- /dev/null
+++ b/packages/api/src/hris/employment/services/deel/mappers.ts
@@ -0,0 +1,136 @@
+import { Injectable } from '@nestjs/common';
+import { MappersRegistry } from '@@core/@core-services/registries/mappers.registry';
+import { CoreUnification } from '@@core/@core-services/unification/core-unification.service';
+import { IngestDataService } from '@@core/@core-services/unification/ingest-data.service';
+import { Utils } from '@hris/@lib/@utils';
+import { IEmploymentMapper } from '@hris/employment/types';
+import {
+ FlsaStatus,
+ UnifiedHrisEmploymentInput,
+ UnifiedHrisEmploymentOutput,
+ EmploymentType,
+ PayFrequency,
+ PayPeriod,
+} from '@hris/employment/types/model.unified';
+import { DeelEmploymentOutput } from './types';
+import { CurrencyCode } from '@@core/utils/types';
+
+@Injectable()
+export class DeelEmploymentMapper implements IEmploymentMapper {
+ constructor(
+ private mappersRegistry: MappersRegistry,
+ private utils: Utils,
+ private ingestService: IngestDataService,
+ private coreUnificationService: CoreUnification,
+ ) {
+ this.mappersRegistry.registerService('hris', 'employment', 'deel', this);
+ }
+
+ async desunify(
+ source: UnifiedHrisEmploymentInput,
+ customFieldMappings?: { slug: string; remote_id: string }[],
+ ): Promise {
+ // Implementation for desunify (if needed)
+ return;
+ }
+
+ async unify(
+ source: DeelEmploymentOutput | DeelEmploymentOutput[],
+ connectionId: string,
+ customFieldMappings?: { slug: string; remote_id: string }[],
+ ): Promise {
+ if (!Array.isArray(source)) {
+ return this.mapSingleEmploymentToUnified(
+ source,
+ connectionId,
+ customFieldMappings,
+ );
+ }
+ return Promise.all(
+ source.map((employment) =>
+ this.mapSingleEmploymentToUnified(
+ employment,
+ connectionId,
+ customFieldMappings,
+ ),
+ ),
+ );
+ }
+
+ private async mapSingleEmploymentToUnified(
+ employment: DeelEmploymentOutput,
+ connectionId: string,
+ customFieldMappings?: { slug: string; remote_id: string }[],
+ ): Promise {
+ return {
+ remote_id: employment.id,
+ remote_data: employment,
+ job_title: employment.job_title,
+ pay_rate: employment.payment?.rate,
+ pay_period: this.mapPayPeriod(employment.payment?.scale),
+ pay_frequency: this.mapPayFrequency(employment.payment?.scale),
+ pay_currency: employment.payment?.currency as CurrencyCode,
+ flsa_status: this.mapFlsaStatus(employment.hiring_type),
+ effective_date: employment.start_date
+ ? new Date(employment.start_date)
+ : null,
+ employment_type: this.mapEmploymentType(employment.hiring_type),
+ };
+ }
+
+ private mapPayPeriod(scale?: string): PayPeriod | undefined {
+ switch (scale?.toLowerCase()) {
+ case 'yearly':
+ return 'YEAR';
+ case 'monthly':
+ return 'MONTH';
+ case 'weekly':
+ return 'WEEK';
+ case 'daily':
+ return 'DAY';
+ case 'hourly':
+ return 'HOUR';
+ default:
+ return undefined;
+ }
+ }
+
+ private mapPayFrequency(scale?: string): PayFrequency | undefined {
+ switch (scale?.toLowerCase()) {
+ case 'yearly':
+ return 'ANNUALLY';
+ case 'monthly':
+ return 'MONTHLY';
+ case 'weekly':
+ return 'WEEKLY';
+ case 'daily':
+ return 'WEEKLY'; // Assuming daily payment is done weekly
+ case 'hourly':
+ return 'WEEKLY'; // Assuming hourly payment is done weekly
+ default:
+ return undefined;
+ }
+ }
+
+ private mapFlsaStatus(hiringType?: string): FlsaStatus | undefined {
+ switch (hiringType?.toLowerCase()) {
+ case 'employee':
+ return 'EXEMPT'; // Assuming employees are exempt
+ case 'contractor':
+ return 'NONEXEMPT'; // Assuming contractors are nonexempt
+ default:
+ return undefined;
+ }
+ }
+
+ private mapEmploymentType(hiringType?: string): EmploymentType | undefined {
+ switch (hiringType?.toLowerCase()) {
+ case 'employee':
+ return 'FULL_TIME'; // Assuming employees are full-time
+ case 'contractor':
+ return 'CONTRACTOR';
+ default:
+ return undefined;
+ }
+ }
+}
diff --git a/packages/api/src/hris/employment/services/deel/types.ts b/packages/api/src/hris/employment/services/deel/types.ts
new file mode 100644
index 000000000..8b4ad5ae9
--- /dev/null
+++ b/packages/api/src/hris/employment/services/deel/types.ts
@@ -0,0 +1,50 @@
+export type DeelEmploymentOutput = Partial<{
+ id: string;
+ name: string;
+ team: DeelTeam;
+ email: string;
+ state: string;
+ country: string;
+ payment: DeelPayment;
+ is_ended: boolean;
+ timezone: string;
+ job_title: string;
+ seniority: string;
+ start_date: string; // Date in string format
+ work_email: string;
+ hiring_type: string;
+ hiring_status: string;
+ completion_date: string;
+ contract_status: string;
+ voluntarily_left: string;
+ contract_coverage: string[];
+ new_hiring_status: string;
+ client_legal_entity: DeelClientLegalEntity;
+ has_eor_termination: string;
+ contract_is_archived: boolean;
+ contract_has_contractor: boolean;
+ is_user_contract_deleted: boolean;
+ hris_direct_employee_invitation: string;
+}>;
+
+export interface DeelTeam {
+ id: string;
+ name: string;
+}
+
+export interface DeelPayment {
+ rate: number;
+ scale: string;
+ currency: string;
+ contract_name: string;
+}
+export interface DeelDepartment {
+ id: string;
+ name: string;
+ parent: string;
+}
+
+export interface DeelClientLegalEntity {
+ id: string;
+ name: string;
+}
diff --git a/packages/api/src/hris/group/group.module.ts b/packages/api/src/hris/group/group.module.ts
index 9e1bdaa36..78f6a35ee 100644
--- a/packages/api/src/hris/group/group.module.ts
+++ b/packages/api/src/hris/group/group.module.ts
@@ -9,6 +9,10 @@ import { CoreUnification } from '@@core/@core-services/unification/core-unificat
import { GustoGroupMapper } from './services/gusto/mappers';
import { GustoService } from './services/gusto';
import { Utils } from '@hris/@lib/@utils';
+import { SageService } from './services/sage';
+import { SageGroupMapper } from './services/sage/mappers';
+import { DeelService } from './services/deel';
+import { DeelGroupMapper } from './services/deel/mappers';
@Module({
controllers: [GroupController],
providers: [
@@ -20,8 +24,12 @@ import { Utils } from '@hris/@lib/@utils';
IngestDataService,
GustoGroupMapper,
Utils,
+ SageGroupMapper,
+ DeelGroupMapper,
/* PROVIDERS SERVICES */
GustoService,
+ SageService,
+ DeelService,
],
exports: [SyncService],
})
diff --git a/packages/api/src/hris/group/services/deel/index.ts b/packages/api/src/hris/group/services/deel/index.ts
new file mode 100644
index 000000000..f593070b1
--- /dev/null
+++ b/packages/api/src/hris/group/services/deel/index.ts
@@ -0,0 +1,66 @@
+import { EncryptionService } from '@@core/@core-services/encryption/encryption.service';
+import { EnvironmentService } from '@@core/@core-services/environment/environment.service';
+import { LoggerService } from '@@core/@core-services/logger/logger.service';
+import { PrismaService } from '@@core/@core-services/prisma/prisma.service';
+import { ApiResponse } from '@@core/utils/types';
+import { SyncParam } from '@@core/utils/types/interface';
+import { HrisObject } from '@hris/@lib/@types';
+import { IGroupService } from '@hris/group/types';
+import { Injectable } from '@nestjs/common';
+import axios from 'axios';
+import { ServiceRegistry } from '../registry.service';
+import { DeelGroupOutput } from './types';
+import { DesunifyReturnType } from '@@core/utils/types/desunify.input';
+import { OriginalGroupOutput } from '@@core/utils/types/original/original.hris';
+
+@Injectable()
+export class DeelService implements IGroupService {
+ constructor(
+ private prisma: PrismaService,
+ private logger: LoggerService,
+ private cryptoService: EncryptionService,
+ private env: EnvironmentService,
+ private registry: ServiceRegistry,
+ ) {
+ this.logger.setContext(
+ HrisObject.group.toUpperCase() + ':' + DeelService.name,
+ );
+ this.registry.registerService('deel', this);
+ }
+ addGroup(
+ groupData: DesunifyReturnType,
+ linkedUserId: string,
+ ): Promise> {
+ throw new Error('Method not implemented.');
+ }
+
+ async sync(data: SyncParam): Promise> {
+ try {
+ const { linkedUserId } = data;
+
+ const connection = await this.prisma.connections.findFirst({
+ where: {
+ id_linked_user: linkedUserId,
+ provider_slug: 'deel',
+ vertical: 'hris',
+ },
+ });
+
+ const resp = await axios.get(`${connection.account_url}/rest/v2/teams`, {
+ headers: {
+ 'Content-Type': 'application/json',
+ 'X-Auth-Token': this.cryptoService.decrypt(connection.access_token),
+ },
+ });
+ this.logger.log(`Synced deel groups !`);
+
+ return {
+ data: resp.data.data,
+ message: 'Deel groups retrieved',
+ statusCode: 200,
+ };
+ } catch (error) {
+ throw error;
+ }
+ }
+}
diff --git a/packages/api/src/hris/group/services/deel/mappers.ts b/packages/api/src/hris/group/services/deel/mappers.ts
new file mode 100644
index 000000000..356c44695
--- /dev/null
+++ b/packages/api/src/hris/group/services/deel/mappers.ts
@@ -0,0 +1,61 @@
+import { MappersRegistry } from '@@core/@core-services/registries/mappers.registry';
+import { CoreUnification } from '@@core/@core-services/unification/core-unification.service';
+import { IngestDataService } from '@@core/@core-services/unification/ingest-data.service';
+import { Utils } from '@hris/@lib/@utils';
+import { IGroupMapper } from '@hris/group/types';
+import {
+ UnifiedHrisGroupInput,
+ UnifiedHrisGroupOutput,
+} from '@hris/group/types/model.unified';
+import { Injectable } from '@nestjs/common';
+import { DeelGroupOutput } from './types';
+
+@Injectable()
+export class DeelGroupMapper implements IGroupMapper {
+ constructor(
+ private mappersRegistry: MappersRegistry,
+ private utils: Utils,
+ private ingestService: IngestDataService,
+ private coreUnificationService: CoreUnification,
+ ) {
+ this.mappersRegistry.registerService('hris', 'group', 'deel', this);
+ }
+
+ async desunify(
+ source: UnifiedHrisGroupInput,
+ customFieldMappings?: { slug: string; remote_id: string }[],
+ ): Promise {
+ return;
+ }
+
+ async unify(
+ source: DeelGroupOutput | DeelGroupOutput[],
+ connectionId: string,
+ customFieldMappings?: { slug: string; remote_id: string }[],
+ ): Promise {
+ if (!Array.isArray(source)) {
+ return this.mapSingleGroupToUnified(
+ source,
+ connectionId,
+ customFieldMappings,
+ );
+ }
+ return Promise.all(
+ source.map((group) =>
+ this.mapSingleGroupToUnified(group, connectionId, customFieldMappings),
+ ),
+ );
+ }
+
+ private async mapSingleGroupToUnified(
+ group: DeelGroupOutput,
+ connectionId: string,
+ customFieldMappings?: { slug: string; remote_id: string }[],
+ ): Promise {
+ return {
+ remote_id: group.id,
+ remote_data: group,
+ name: group.name,
+ };
+ }
+}
diff --git a/packages/api/src/hris/group/services/deel/types.ts b/packages/api/src/hris/group/services/deel/types.ts
new file mode 100644
index 000000000..8964f34e3
--- /dev/null
+++ b/packages/api/src/hris/group/services/deel/types.ts
@@ -0,0 +1,4 @@
+export type DeelGroupOutput = {
+ id: string;
+ name: string;
+};
diff --git a/packages/api/src/hris/group/services/sage/index.ts b/packages/api/src/hris/group/services/sage/index.ts
new file mode 100644
index 000000000..08dff20ec
--- /dev/null
+++ b/packages/api/src/hris/group/services/sage/index.ts
@@ -0,0 +1,66 @@
+import { EncryptionService } from '@@core/@core-services/encryption/encryption.service';
+import { EnvironmentService } from '@@core/@core-services/environment/environment.service';
+import { LoggerService } from '@@core/@core-services/logger/logger.service';
+import { PrismaService } from '@@core/@core-services/prisma/prisma.service';
+import { ApiResponse } from '@@core/utils/types';
+import { SyncParam } from '@@core/utils/types/interface';
+import { HrisObject } from '@hris/@lib/@types';
+import { IGroupService } from '@hris/group/types';
+import { Injectable } from '@nestjs/common';
+import axios from 'axios';
+import { ServiceRegistry } from '../registry.service';
+import { SageGroupOutput } from './types';
+import { DesunifyReturnType } from '@@core/utils/types/desunify.input';
+import { OriginalGroupOutput } from '@@core/utils/types/original/original.hris';
+
+@Injectable()
+export class SageService implements IGroupService {
+ constructor(
+ private prisma: PrismaService,
+ private logger: LoggerService,
+ private cryptoService: EncryptionService,
+ private env: EnvironmentService,
+ private registry: ServiceRegistry,
+ ) {
+ this.logger.setContext(
+ HrisObject.group.toUpperCase() + ':' + SageService.name,
+ );
+ this.registry.registerService('sage', this);
+ }
+ addGroup(
+ groupData: DesunifyReturnType,
+ linkedUserId: string,
+ ): Promise> {
+ throw new Error('Method not implemented.');
+ }
+
+ async sync(data: SyncParam): Promise> {
+ try {
+ const { linkedUserId } = data;
+
+ const connection = await this.prisma.connections.findFirst({
+ where: {
+ id_linked_user: linkedUserId,
+ provider_slug: 'sage',
+ vertical: 'hris',
+ },
+ });
+
+ const resp = await axios.get(`${connection.account_url}/api/teams`, {
+ headers: {
+ 'Content-Type': 'application/json',
+ 'X-Auth-Token': this.cryptoService.decrypt(connection.access_token),
+ },
+ });
+ this.logger.log(`Synced sage groups !`);
+
+ return {
+ data: resp.data.data,
+ message: 'Sage groups retrieved',
+ statusCode: 200,
+ };
+ } catch (error) {
+ throw error;
+ }
+ }
+}
diff --git a/packages/api/src/hris/group/services/sage/mappers.ts b/packages/api/src/hris/group/services/sage/mappers.ts
new file mode 100644
index 000000000..c40072b9f
--- /dev/null
+++ b/packages/api/src/hris/group/services/sage/mappers.ts
@@ -0,0 +1,61 @@
+import { MappersRegistry } from '@@core/@core-services/registries/mappers.registry';
+import { CoreUnification } from '@@core/@core-services/unification/core-unification.service';
+import { IngestDataService } from '@@core/@core-services/unification/ingest-data.service';
+import { Utils } from '@hris/@lib/@utils';
+import { IGroupMapper } from '@hris/group/types';
+import {
+ UnifiedHrisGroupInput,
+ UnifiedHrisGroupOutput,
+} from '@hris/group/types/model.unified';
+import { Injectable } from '@nestjs/common';
+import { SageGroupOutput } from './types';
+
+@Injectable()
+export class SageGroupMapper implements IGroupMapper {
+ constructor(
+ private mappersRegistry: MappersRegistry,
+ private utils: Utils,
+ private ingestService: IngestDataService,
+ private coreUnificationService: CoreUnification,
+ ) {
+ this.mappersRegistry.registerService('hris', 'group', 'sage', this);
+ }
+
+ async desunify(
+ source: UnifiedHrisGroupInput,
+ customFieldMappings?: { slug: string; remote_id: string }[],
+ ): Promise {
+ return;
+ }
+
+ async unify(
+ source: SageGroupOutput | SageGroupOutput[],
+ connectionId: string,
+ customFieldMappings?: { slug: string; remote_id: string }[],
+ ): Promise {
+ if (!Array.isArray(source)) {
+ return this.mapSingleGroupToUnified(
+ source,
+ connectionId,
+ customFieldMappings,
+ );
+ }
+ return Promise.all(
+ source.map((group) =>
+ this.mapSingleGroupToUnified(group, connectionId, customFieldMappings),
+ ),
+ );
+ }
+
+ private async mapSingleGroupToUnified(
+ group: SageGroupOutput,
+ connectionId: string,
+ customFieldMappings?: { slug: string; remote_id: string }[],
+ ): Promise {
+ return {
+ remote_id: String(group.id),
+ remote_data: group,
+ name: group.name,
+ };
+ }
+}
diff --git a/packages/api/src/hris/group/services/sage/types.ts b/packages/api/src/hris/group/services/sage/types.ts
new file mode 100644
index 000000000..dcd2d590b
--- /dev/null
+++ b/packages/api/src/hris/group/services/sage/types.ts
@@ -0,0 +1,6 @@
+export type SageGroupOutput = {
+ id: number;
+ name: string;
+ manager_ids: string[];
+ employee_ids: string[];
+};
diff --git a/packages/api/src/hris/location/location.module.ts b/packages/api/src/hris/location/location.module.ts
index 443570585..c2f147465 100644
--- a/packages/api/src/hris/location/location.module.ts
+++ b/packages/api/src/hris/location/location.module.ts
@@ -9,6 +9,7 @@ import { CoreUnification } from '@@core/@core-services/unification/core-unificat
import { Utils } from '@hris/@lib/@utils';
import { GustoLocationMapper } from './services/gusto/mappers';
import { GustoService } from './services/gusto';
+import { DeelLocationMapper } from './services/deel/mappers';
@Module({
controllers: [LocationController],
providers: [
@@ -20,6 +21,7 @@ import { GustoService } from './services/gusto';
ServiceRegistry,
IngestDataService,
GustoLocationMapper,
+ DeelLocationMapper,
/* PROVIDERS SERVICES */
GustoService,
],
diff --git a/packages/api/src/hris/location/services/deel/mappers.ts b/packages/api/src/hris/location/services/deel/mappers.ts
new file mode 100644
index 000000000..cecf44401
--- /dev/null
+++ b/packages/api/src/hris/location/services/deel/mappers.ts
@@ -0,0 +1,70 @@
+import { MappersRegistry } from '@@core/@core-services/registries/mappers.registry';
+import { CoreUnification } from '@@core/@core-services/unification/core-unification.service';
+import { IngestDataService } from '@@core/@core-services/unification/ingest-data.service';
+import { Injectable } from '@nestjs/common';
+import { DeelLocationOutput } from './types';
+import {
+ UnifiedHrisLocationInput,
+ UnifiedHrisLocationOutput,
+} from '@hris/location/types/model.unified';
+import { ILocationMapper } from '@hris/location/types';
+import { Utils } from '@hris/@lib/@utils';
+
+@Injectable()
+export class DeelLocationMapper implements ILocationMapper {
+ constructor(
+ private mappersRegistry: MappersRegistry,
+ private utils: Utils,
+ private ingestService: IngestDataService,
+ private coreUnificationService: CoreUnification,
+ ) {
+ this.mappersRegistry.registerService('hris', 'location', 'deel', this);
+ }
+
+ async desunify(
+ source: UnifiedHrisLocationInput,
+ customFieldMappings?: { slug: string; remote_id: string }[],
+ ): Promise {
+ return;
+ }
+
+ async unify(
+ source: DeelLocationOutput | DeelLocationOutput[],
+ connectionId: string,
+ customFieldMappings?: { slug: string; remote_id: string }[],
+ ): Promise {
+ if (!Array.isArray(source)) {
+ return this.mapSingleLocationToUnified(
+ source,
+ connectionId,
+ customFieldMappings,
+ );
+ }
+ return Promise.all(
+ source.map((location) =>
+ this.mapSingleLocationToUnified(
+ location,
+ connectionId,
+ customFieldMappings,
+ ),
+ ),
+ );
+ }
+
+ private async mapSingleLocationToUnified(
+ location: DeelLocationOutput,
+ connectionId: string,
+ customFieldMappings?: { slug: string; remote_id: string }[],
+ ): Promise {
+ return {
+ remote_id: null,
+ remote_data: location,
+ street_1: location.streetAddress,
+ city: location.locality,
+ state: location.region,
+ zip_code: location.postalCode,
+ country: location.country,
+ location_type: location.type,
+ };
+ }
+}
diff --git a/packages/api/src/hris/location/services/deel/types.ts b/packages/api/src/hris/location/services/deel/types.ts
new file mode 100644
index 000000000..98db26aa7
--- /dev/null
+++ b/packages/api/src/hris/location/services/deel/types.ts
@@ -0,0 +1,8 @@
+export type DeelLocationOutput = Partial<{
+ streetAddress: string;
+ locality: string;
+ region: string;
+ postalCode: string;
+ country: string;
+ type: 'WORK' | 'HOME';
+}>;
diff --git a/packages/api/src/hris/timeoff/services/sage/index.ts b/packages/api/src/hris/timeoff/services/sage/index.ts
new file mode 100644
index 000000000..c83e2d187
--- /dev/null
+++ b/packages/api/src/hris/timeoff/services/sage/index.ts
@@ -0,0 +1,69 @@
+import { EncryptionService } from '@@core/@core-services/encryption/encryption.service';
+import { EnvironmentService } from '@@core/@core-services/environment/environment.service';
+import { LoggerService } from '@@core/@core-services/logger/logger.service';
+import { PrismaService } from '@@core/@core-services/prisma/prisma.service';
+import { ApiResponse } from '@@core/utils/types';
+import { SyncParam } from '@@core/utils/types/interface';
+import { HrisObject } from '@hris/@lib/@types';
+import { ITimeoffService } from '@hris/timeoff/types';
+import { Injectable } from '@nestjs/common';
+import axios from 'axios';
+import { ServiceRegistry } from '../registry.service';
+import { SageTimeoffOutput } from './types';
+import { DesunifyReturnType } from '@@core/utils/types/desunify.input';
+import { OriginalTimeoffOutput } from '@@core/utils/types/original/original.hris';
+
+@Injectable()
+export class SageService implements ITimeoffService {
+ constructor(
+ private prisma: PrismaService,
+ private logger: LoggerService,
+ private cryptoService: EncryptionService,
+ private env: EnvironmentService,
+ private registry: ServiceRegistry,
+ ) {
+ this.logger.setContext(
+ HrisObject.timeoff.toUpperCase() + ':' + SageService.name,
+ );
+ this.registry.registerService('sage', this);
+ }
+ addTimeoff(
+ timeoffData: DesunifyReturnType,
+ linkedUserId: string,
+ ): Promise> {
+ throw new Error('Method not implemented.');
+ }
+
+ async sync(data: SyncParam): Promise> {
+ try {
+ const { linkedUserId } = data;
+
+ const connection = await this.prisma.connections.findFirst({
+ where: {
+ id_linked_user: linkedUserId,
+ provider_slug: 'sage',
+ vertical: 'hris',
+ },
+ });
+
+ const resp = await axios.get(
+ `${connection.account_url}/api/leave-management/requests`,
+ {
+ headers: {
+ 'Content-Type': 'application/json',
+ 'X-Auth-Token': this.cryptoService.decrypt(connection.access_token),
+ },
+ },
+ );
+ this.logger.log(`Synced sage timeoffs !`);
+
+ return {
+ data: resp.data.data,
+ message: 'Sage timeoffs retrieved',
+ statusCode: 200,
+ };
+ } catch (error) {
+ throw error;
+ }
+ }
+}
diff --git a/packages/api/src/hris/timeoff/services/sage/mappers.ts b/packages/api/src/hris/timeoff/services/sage/mappers.ts
new file mode 100644
index 000000000..d8eeff03d
--- /dev/null
+++ b/packages/api/src/hris/timeoff/services/sage/mappers.ts
@@ -0,0 +1,115 @@
+import { Injectable } from '@nestjs/common';
+import { MappersRegistry } from '@@core/@core-services/registries/mappers.registry';
+import { CoreUnification } from '@@core/@core-services/unification/core-unification.service';
+import { IngestDataService } from '@@core/@core-services/unification/ingest-data.service';
+import { Utils } from '@hris/@lib/@utils';
+import { ITimeoffMapper } from '@hris/timeoff/types';
+import {
+ UnifiedHrisTimeoffInput,
+ UnifiedHrisTimeoffOutput,
+ Status,
+ RequestType,
+} from '@hris/timeoff/types/model.unified';
+import { SageTimeoffOutput } from './types';
+
+@Injectable()
+export class SageTimeoffMapper implements ITimeoffMapper {
+ constructor(
+ private mappersRegistry: MappersRegistry,
+ private utils: Utils,
+ private ingestService: IngestDataService,
+ private coreUnificationService: CoreUnification,
+ ) {
+ this.mappersRegistry.registerService('hris', 'timeoff', 'sage', this);
+ }
+
+ async desunify(
+ source: UnifiedHrisTimeoffInput,
+ customFieldMappings?: { slug: string; remote_id: string }[],
+ ): Promise {
+ // Implementation for desunify (if needed)
+ return;
+ }
+
+ async unify(
+ source: SageTimeoffOutput | SageTimeoffOutput[],
+ connectionId: string,
+ customFieldMappings?: { slug: string; remote_id: string }[],
+ ): Promise {
+ if (!Array.isArray(source)) {
+ return this.mapSingleTimeoffToUnified(
+ source,
+ connectionId,
+ customFieldMappings,
+ );
+ }
+ return Promise.all(
+ source.map((timeoff) =>
+ this.mapSingleTimeoffToUnified(
+ timeoff,
+ connectionId,
+ customFieldMappings,
+ ),
+ ),
+ );
+ }
+
+ private async mapSingleTimeoffToUnified(
+ timeoff: SageTimeoffOutput,
+ connectionId: string,
+ customFieldMappings?: { slug: string; remote_id: string }[],
+ ): Promise {
+ const employee = await this.utils.getEmployeeUuidFromRemoteId(
+ timeoff.employee_id.toString(),
+ connectionId,
+ );
+
+ return {
+ remote_id: timeoff.id.toString(),
+ remote_data: timeoff,
+ employee: employee,
+ status: this.mapStatus(timeoff.status_code),
+ employee_note: timeoff.details,
+ units: 'HOURS',
+ amount: timeoff.hours,
+ request_type: this.inferRequestType(timeoff.details),
+ start_time: new Date(timeoff.start_date),
+ end_time: new Date(timeoff.end_date),
+ };
+ }
+
+ private mapStatus(statusCode: string): Status {
+ switch (statusCode.toLowerCase()) {
+ case 'approved':
+ return 'APPROVED';
+ case 'declined':
+ return 'DECLINED';
+ case 'cancelled':
+ return 'CANCELLED';
+ case 'deleted':
+ return 'DELETED';
+ default:
+ return 'REQUESTED';
+ }
+ }
+
+ private inferRequestType(details: string): RequestType {
+ const lowerDetails = details.toLowerCase();
+ if (lowerDetails.includes('vacation') || lowerDetails.includes('holiday')) {
+ return 'VACATION';
+ } else if (
+ lowerDetails.includes('sick') ||
+ lowerDetails.includes('illness')
+ ) {
+ return 'SICK';
+ } else if (lowerDetails.includes('jury')) {
+ return 'JURY_DUTY';
+ } else if (lowerDetails.includes('bereavement')) {
+ return 'BEREAVEMENT';
+ } else if (lowerDetails.includes('volunteer')) {
+ return 'VOLUNTEER';
+ } else {
+ return 'PERSONAL';
+ }
+ }
+}
diff --git a/packages/api/src/hris/timeoff/services/sage/types.ts b/packages/api/src/hris/timeoff/services/sage/types.ts
new file mode 100644
index 000000000..f7b59bd94
--- /dev/null
+++ b/packages/api/src/hris/timeoff/services/sage/types.ts
@@ -0,0 +1,30 @@
+export interface SageTimeoffReplacement {
+ id: number;
+ full_name: string;
+}
+
+export interface SageTimeoffField {
+ title: string;
+ answer: string;
+}
+
+export type SageTimeoffOutput = Partial<{
+ id: number;
+ status: string;
+ status_code: string;
+ policy_id: number;
+ employee_id: number;
+ replacement: SageTimeoffReplacement;
+ details: string;
+ is_multi_date: boolean;
+ is_single_day: boolean;
+ is_part_of_day: boolean;
+ first_part_of_day: boolean;
+ second_part_of_day: boolean;
+ start_date: string;
+ end_date: string;
+ request_date: string;
+ approval_date: string | null;
+ hours: number;
+ fields: SageTimeoffField[];
+}>;
diff --git a/packages/api/src/hris/timeoff/timeoff.module.ts b/packages/api/src/hris/timeoff/timeoff.module.ts
index 86d017aa9..0f66654af 100644
--- a/packages/api/src/hris/timeoff/timeoff.module.ts
+++ b/packages/api/src/hris/timeoff/timeoff.module.ts
@@ -7,6 +7,8 @@ import { IngestDataService } from '@@core/@core-services/unification/ingest-data
import { WebhookService } from '@@core/@core-services/webhooks/panora-webhooks/webhook.service';
import { CoreUnification } from '@@core/@core-services/unification/core-unification.service';
import { Utils } from '@hris/@lib/@utils';
+import { SageTimeoffMapper } from './services/sage/mappers';
+import { SageService } from './services/sage';
@Module({
controllers: [TimeoffController],
providers: [
@@ -17,7 +19,9 @@ import { Utils } from '@hris/@lib/@utils';
WebhookService,
ServiceRegistry,
IngestDataService,
+ SageTimeoffMapper,
/* PROVIDERS SERVICES */
+ SageService,
],
exports: [SyncService],
})
diff --git a/packages/api/src/hris/timeoffbalance/services/sage/index.ts b/packages/api/src/hris/timeoffbalance/services/sage/index.ts
new file mode 100644
index 000000000..61f928029
--- /dev/null
+++ b/packages/api/src/hris/timeoffbalance/services/sage/index.ts
@@ -0,0 +1,72 @@
+import { EncryptionService } from '@@core/@core-services/encryption/encryption.service';
+import { EnvironmentService } from '@@core/@core-services/environment/environment.service';
+import { LoggerService } from '@@core/@core-services/logger/logger.service';
+import { PrismaService } from '@@core/@core-services/prisma/prisma.service';
+import { ApiResponse } from '@@core/utils/types';
+import { SyncParam } from '@@core/utils/types/interface';
+import { HrisObject } from '@hris/@lib/@types';
+import { ITimeoffBalanceService } from '@hris/timeoffbalance/types';
+import { Injectable } from '@nestjs/common';
+import axios from 'axios';
+import { ServiceRegistry } from '../registry.service';
+import { SageTimeoffbalanceOutput } from './types';
+
+@Injectable()
+export class SageService implements ITimeoffBalanceService {
+ constructor(
+ private prisma: PrismaService,
+ private logger: LoggerService,
+ private cryptoService: EncryptionService,
+ private env: EnvironmentService,
+ private registry: ServiceRegistry,
+ ) {
+ this.logger.setContext(
+ HrisObject.timeoffbalance.toUpperCase() + ':' + SageService.name,
+ );
+ this.registry.registerService('sage', this);
+ }
+
+ async sync(
+ data: SyncParam,
+ ): Promise> {
+ try {
+ const { linkedUserId, id_employee } = data;
+
+ const connection = await this.prisma.connections.findFirst({
+ where: {
+ id_linked_user: linkedUserId,
+ provider_slug: 'sage',
+ vertical: 'hris',
+ },
+ });
+
+ const employee = await this.prisma.hris_employees.findUnique({
+ where: {
+ id_hris_employee: id_employee as string,
+ },
+ select: {
+ remote_id: true,
+ },
+ });
+
+ const resp = await axios.get(
+ `${connection.account_url}/api/employees/${employee.remote_id}/leave-management/balances`,
+ {
+ headers: {
+ 'Content-Type': 'application/json',
+ 'X-Auth-Token': this.cryptoService.decrypt(connection.access_token),
+ },
+ },
+ );
+ this.logger.log(`Synced sage timeoffbalances !`);
+
+ return {
+ data: resp.data.data,
+ message: 'Sage timeoffbalances retrieved',
+ statusCode: 200,
+ };
+ } catch (error) {
+ throw error;
+ }
+ }
+}
diff --git a/packages/api/src/hris/timeoffbalance/services/sage/mappers.ts b/packages/api/src/hris/timeoffbalance/services/sage/mappers.ts
new file mode 100644
index 000000000..448a08afd
--- /dev/null
+++ b/packages/api/src/hris/timeoffbalance/services/sage/mappers.ts
@@ -0,0 +1,73 @@
+import { MappersRegistry } from '@@core/@core-services/registries/mappers.registry';
+import { CoreUnification } from '@@core/@core-services/unification/core-unification.service';
+import { IngestDataService } from '@@core/@core-services/unification/ingest-data.service';
+import { Utils } from '@hris/@lib/@utils';
+import { ITimeoffBalanceMapper } from '@hris/timeoffbalance/types';
+import {
+ UnifiedHrisTimeoffbalanceInput,
+ UnifiedHrisTimeoffbalanceOutput,
+} from '@hris/timeoffbalance/types/model.unified';
+import { Injectable } from '@nestjs/common';
+import { SageTimeoffbalanceOutput } from './types';
+
+@Injectable()
+export class SageTimeoffbalanceMapper implements ITimeoffBalanceMapper {
+ constructor(
+ private mappersRegistry: MappersRegistry,
+ private utils: Utils,
+ private ingestService: IngestDataService,
+ private coreUnificationService: CoreUnification,
+ ) {
+ this.mappersRegistry.registerService(
+ 'hris',
+ 'timeoffbalance',
+ 'sage',
+ this,
+ );
+ }
+
+ async desunify(
+ source: UnifiedHrisTimeoffbalanceInput,
+ customFieldMappings?: { slug: string; remote_id: string }[],
+ ): Promise {
+ return;
+ }
+
+ async unify(
+ source: SageTimeoffbalanceOutput | SageTimeoffbalanceOutput[],
+ connectionId: string,
+ customFieldMappings?: { slug: string; remote_id: string }[],
+ ): Promise<
+ UnifiedHrisTimeoffbalanceOutput | UnifiedHrisTimeoffbalanceOutput[]
+ > {
+ if (!Array.isArray(source)) {
+ return this.mapSingleTimeoffbalanceToUnified(
+ source,
+ connectionId,
+ customFieldMappings,
+ );
+ }
+ return Promise.all(
+ source.map((timeoffbalance) =>
+ this.mapSingleTimeoffbalanceToUnified(
+ timeoffbalance,
+ connectionId,
+ customFieldMappings,
+ ),
+ ),
+ );
+ }
+
+ private async mapSingleTimeoffbalanceToUnified(
+ timeoffbalance: SageTimeoffbalanceOutput,
+ connectionId: string,
+ customFieldMappings?: { slug: string; remote_id: string }[],
+ ): Promise {
+ return {
+ remote_id: null,
+ remote_data: timeoffbalance,
+ balance: timeoffbalance.available,
+ used: timeoffbalance.used,
+ };
+ }
+}
diff --git a/packages/api/src/hris/timeoffbalance/services/sage/types.ts b/packages/api/src/hris/timeoffbalance/services/sage/types.ts
new file mode 100644
index 000000000..b22f8a766
--- /dev/null
+++ b/packages/api/src/hris/timeoffbalance/services/sage/types.ts
@@ -0,0 +1,5 @@
+export type SageTimeoffbalanceOutput = Partial<{
+ policy_id: number;
+ used: number;
+ available: number;
+}>;
diff --git a/packages/api/src/hris/timeoffbalance/timeoffbalance.module.ts b/packages/api/src/hris/timeoffbalance/timeoffbalance.module.ts
index 106e1bdec..12f5213b3 100644
--- a/packages/api/src/hris/timeoffbalance/timeoffbalance.module.ts
+++ b/packages/api/src/hris/timeoffbalance/timeoffbalance.module.ts
@@ -7,6 +7,8 @@ import { IngestDataService } from '@@core/@core-services/unification/ingest-data
import { WebhookService } from '@@core/@core-services/webhooks/panora-webhooks/webhook.service';
import { CoreUnification } from '@@core/@core-services/unification/core-unification.service';
import { Utils } from '@hris/@lib/@utils';
+import { SageTimeoffbalanceMapper } from './services/sage/mappers';
+import { SageService } from './services/sage';
@Module({
controllers: [TimeoffBalanceController],
providers: [
@@ -17,7 +19,9 @@ import { Utils } from '@hris/@lib/@utils';
WebhookService,
ServiceRegistry,
IngestDataService,
+ SageTimeoffbalanceMapper,
/* PROVIDERS SERVICES */
+ SageService,
],
exports: [SyncService],
})
diff --git a/packages/shared/src/connectors/metadata.ts b/packages/shared/src/connectors/metadata.ts
index 9f0368312..ef65b5d6c 100644
--- a/packages/shared/src/connectors/metadata.ts
+++ b/packages/shared/src/connectors/metadata.ts
@@ -1110,6 +1110,20 @@ export const CONNECTORS_METADATA: ProvidersConfig = {
strategy: AuthStrategy.oauth2
}
},
+ 'apollo': {
+ urls: {
+ docsUrl: 'https://apolloio.github.io/apollo-api-docs/?shell#introduction',
+ apiUrl: 'https://api.apollo.io'
+ },
+ logoPath: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSM4trwPJLoj7tPkFYZG6TyMVzgCX1fn2zUyA&s',
+ description: 'Sync & Create contacts, deals, companies, notes, engagements, stages, tasks and users',
+ active: false,
+ primaryColor: '#ffcf40',
+ authStrategy: {
+ strategy: AuthStrategy.api_key,
+ properties: ["api_key"]
+ }
+ },
'hubspot_marketing_hub': {
scopes: '',
urls: {
@@ -1251,7 +1265,7 @@ export const CONNECTORS_METADATA: ProvidersConfig = {
scopes: 'openid+email',
urls: {
docsUrl: 'https://documentation.bamboohr.com/docs/getting-started',
- apiUrl: (companySubdomain) => `https://api.bamboohr.com/api/gateway.php/${companySubdomain}`,
+ apiUrl: (subdomain) => `https://api.bamboohr.com/api/gateway.php/${subdomain}`,
},
logoPath: 'https://play-lh.googleusercontent.com/c4BW9wr_QAiIeVBYHhP7rs06w99xJzxgLvmL5I1mkucC3_ATMyL1t7Doz0_LQ0X-qS0',
description: 'Sync & Create contacts, deals, companies, notes, engagements, stages, tasks and users',
@@ -1259,7 +1273,7 @@ export const CONNECTORS_METADATA: ProvidersConfig = {
primaryColor: '#599D16',
authStrategy: {
strategy: AuthStrategy.basic,
- properties: ['username', 'company_subdomain']
+ properties: ['username', 'subdomain']
},
},
'breezy': {
@@ -1685,7 +1699,7 @@ export const CONNECTORS_METADATA: ProvidersConfig = {
strategy: AuthStrategy.api_key
}
},
- 'sage_hr': {
+ 'sage': {
scopes: '',
urls: {
docsUrl: '',
@@ -2449,11 +2463,13 @@ export const CONNECTORS_METADATA: ProvidersConfig = {
docsUrl: '',
apiUrl: ''
},
- logoPath: 'https://play-lh.googleusercontent.com/EMobDJKabP1eY_63QHgPS_-TK3eRfxXaeOnERbcRaWAw573iaV74pXS9xOv997dRZtM',
+ logoPath: 'https://assets.wheelhouse.com/media/_solution_logo_04042023_58844144.png',
description: 'Sync & Create contacts, deals, companies, notes, engagements, stages, tasks and users',
- active: false,
+ active: true,
+ primaryColor: '#F8A22D',
authStrategy: {
- strategy: AuthStrategy.api_key
+ strategy: AuthStrategy.api_key,
+ properties: ["api_key"]
}
},
'payfit': {
@@ -2549,18 +2565,20 @@ export const CONNECTORS_METADATA: ProvidersConfig = {
strategy: AuthStrategy.api_key
}
},
- 'sage_hr': {
+ 'sage': {
scopes: '',
urls: {
- docsUrl: '',
- apiUrl: ''
+ docsUrl: 'https://sagehr.docs.apiary.io/#reference',
+ apiUrl: (subdomain) => `https://${subdomain}.sage.hr`
},
- logoPath: 'https://play-lh.googleusercontent.com/EMobDJKabP1eY_63QHgPS_-TK3eRfxXaeOnERbcRaWAw573iaV74pXS9xOv997dRZtM',
+ logoPath: 'https://appexchange.salesforce.com/partners/servlet/servlet.FileDownload?file=00P4V00000xPZsjUAG',
description: 'Sync & Create contacts, deals, companies, notes, engagements, stages, tasks and users',
- active: false,
+ active: true,
+ primaryColor: '#00d639',
authStrategy: {
- strategy: AuthStrategy.api_key
- }
+ strategy: AuthStrategy.api_key,
+ properties: ["api_key", "subdomain"]
+ },
},
'sap_successfactors': {
scopes: '',
From ba8471a3954eecfde6b1143557be76f13c3a1ea8 Mon Sep 17 00:00:00 2001
From: Manoj Kumar <95513071+Iamsidar07@users.noreply.github.com>
Date: Fri, 16 Aug 2024 07:31:12 +0530
Subject: [PATCH 04/49] Change whixch to which
---
docs/open-source/contributors/build.mdx | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/docs/open-source/contributors/build.mdx b/docs/open-source/contributors/build.mdx
index 279be5f54..273d34136 100644
--- a/docs/open-source/contributors/build.mdx
+++ b/docs/open-source/contributors/build.mdx
@@ -34,7 +34,7 @@ You can find all categories inside [`packages/shared/src/categories.ts`](https:/
Actually an integration is built in 2 parts :
- the **authentication part** (oauth, api key, basic etc) which is built by the Panora team
-- the **service integration** where the mapping with our unified model is created whixch is what you'll build in the next steps
+- the **service integration** where the mapping with our unified model is created which is what you'll build in the next steps
# Step 2: Build your provider service
@@ -186,4 +186,4 @@ For the sake of this guide, let's map the common object `contact` under `crm` ca
The script will automatically scan the `/crm/contact/services` folder and detect any new service folder so all dependencies and imports are updated across the codebase.
-
\ No newline at end of file
+
From 5052c8ed70aef4864072c7f545da59665cee0767 Mon Sep 17 00:00:00 2001
From: Manoj Kumar <95513071+Iamsidar07@users.noreply.github.com>
Date: Fri, 16 Aug 2024 07:44:27 +0530
Subject: [PATCH 05/49] discord link was expired change to
https://discord.com/invite/PH5k7gGubt
---
docs/support/get_help.mdx | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/docs/support/get_help.mdx b/docs/support/get_help.mdx
index a87780feb..f130c991c 100644
--- a/docs/support/get_help.mdx
+++ b/docs/support/get_help.mdx
@@ -4,4 +4,4 @@ icon: circle-info
---
Our team can help you - click [here](https://app.cal.com/rflih/30) to book some time to chat with an integrations expert.
-You can also ask the community: just go on our [discord](https://discord.gg/2SCC2jxN)
+You can also ask the community: just go on our [discord](https://discord.com/invite/PH5k7gGubt)
From aef952658d25ec8b15538a1abd3b7d00200cc330 Mon Sep 17 00:00:00 2001
From: nael
Date: Fri, 16 Aug 2024 04:40:34 +0200
Subject: [PATCH 06/49] :sparkles: Added connections for all cybersec
integrations
---
.../@core/connections/connections.module.ts | 3 +
.../cybersecurity.connection.module.ts | 38 ++++
.../crowdstrike/crowdstrike.service.ts | 195 +++++++++++++++++
.../cybersecurity.connection.service.ts | 129 ++++++++++++
.../microsoftdefender.service.ts | 199 ++++++++++++++++++
.../services/qualys/qualys.service.ts | 156 ++++++++++++++
.../rapid7insightvm/rapid7.service.ts | 145 +++++++++++++
.../services/registry.service.ts | 25 +++
.../services/semgrep/semgrep.service.ts | 143 +++++++++++++
.../sentinelone/sentinelone.service.ts | 149 +++++++++++++
.../services/snyk/snyk.service.ts | 191 +++++++++++++++++
.../services/tenable/tenable.service.ts | 147 +++++++++++++
packages/shared/src/categories.ts | 3 +-
packages/shared/src/connectors/metadata.ts | 119 +++++++++++
14 files changed, 1641 insertions(+), 1 deletion(-)
create mode 100644 packages/api/src/@core/connections/cybersecurity/cybersecurity.connection.module.ts
create mode 100644 packages/api/src/@core/connections/cybersecurity/services/crowdstrike/crowdstrike.service.ts
create mode 100644 packages/api/src/@core/connections/cybersecurity/services/cybersecurity.connection.service.ts
create mode 100644 packages/api/src/@core/connections/cybersecurity/services/microsoftdefender/microsoftdefender.service.ts
create mode 100644 packages/api/src/@core/connections/cybersecurity/services/qualys/qualys.service.ts
create mode 100644 packages/api/src/@core/connections/cybersecurity/services/rapid7insightvm/rapid7.service.ts
create mode 100644 packages/api/src/@core/connections/cybersecurity/services/registry.service.ts
create mode 100644 packages/api/src/@core/connections/cybersecurity/services/semgrep/semgrep.service.ts
create mode 100644 packages/api/src/@core/connections/cybersecurity/services/sentinelone/sentinelone.service.ts
create mode 100644 packages/api/src/@core/connections/cybersecurity/services/snyk/snyk.service.ts
create mode 100644 packages/api/src/@core/connections/cybersecurity/services/tenable/tenable.service.ts
diff --git a/packages/api/src/@core/connections/connections.module.ts b/packages/api/src/@core/connections/connections.module.ts
index 80c2a0d71..188d25c6c 100644
--- a/packages/api/src/@core/connections/connections.module.ts
+++ b/packages/api/src/@core/connections/connections.module.ts
@@ -12,6 +12,7 @@ import { ProductivityConnectionsModule } from './productivity/productivity.conne
import { MarketingAutomationConnectionsModule } from './marketingautomation/marketingautomation.connection.module';
import { TicketingConnectionModule } from './ticketing/ticketing.connection.module';
import { EcommerceConnectionModule } from './ecommerce/ecommerce.connection.module';
+import { CybersecurityConnectionsModule } from './cybersecurity/cybersecurity.connection.module';
@Module({
controllers: [ConnectionsController],
@@ -25,6 +26,7 @@ import { EcommerceConnectionModule } from './ecommerce/ecommerce.connection.modu
FilestorageConnectionModule,
HrisConnectionModule,
EcommerceConnectionModule,
+ CybersecurityConnectionsModule,
SyncModule,
],
providers: [ValidateUserService, OAuthTokenRefreshService],
@@ -40,6 +42,7 @@ import { EcommerceConnectionModule } from './ecommerce/ecommerce.connection.modu
EcommerceConnectionModule,
HrisConnectionModule,
ProductivityConnectionsModule,
+ CybersecurityConnectionsModule,
],
})
export class ConnectionsModule {}
diff --git a/packages/api/src/@core/connections/cybersecurity/cybersecurity.connection.module.ts b/packages/api/src/@core/connections/cybersecurity/cybersecurity.connection.module.ts
new file mode 100644
index 000000000..65508349f
--- /dev/null
+++ b/packages/api/src/@core/connections/cybersecurity/cybersecurity.connection.module.ts
@@ -0,0 +1,38 @@
+import { EnvironmentService } from '@@core/@core-services/environment/environment.service';
+import { BullQueueModule } from '@@core/@core-services/queues/queue.module';
+import { WebhookModule } from '@@core/@core-services/webhooks/panora-webhooks/webhook.module';
+import { WebhookService } from '@@core/@core-services/webhooks/panora-webhooks/webhook.service';
+import { ConnectionsStrategiesService } from '@@core/connections-strategies/connections-strategies.service';
+import { Module } from '@nestjs/common';
+import { CybersecurityConnectionsService } from './services/cybersecurity.connection.service';
+import { ServiceRegistry } from './services/registry.service';
+import { TenableConnectionService } from './services/tenable/tenable.service';
+import { QualysConnectionService } from './services/qualys/qualys.service';
+import { SemgrepConnectionService } from './services/semgrep/semgrep.service';
+import { SentineloneConnectionService } from './services/sentinelone/sentinelone.service';
+import { Rapid7ConnectionService } from './services/rapid7insightvm/rapid7.service';
+import { SnykConnectionService } from './services/snyk/snyk.service';
+import { CrowdstrikeConnectionService } from './services/crowdstrike/crowdstrike.service';
+import { MicrosoftdefenderConnectionService } from './services/microsoftdefender/microsoftdefender.service';
+
+@Module({
+ imports: [WebhookModule, BullQueueModule],
+ providers: [
+ CybersecurityConnectionsService,
+ WebhookService,
+ EnvironmentService,
+ ServiceRegistry,
+ ConnectionsStrategiesService,
+ //PROVIDERS SERVICES
+ SemgrepConnectionService,
+ TenableConnectionService,
+ QualysConnectionService,
+ SentineloneConnectionService,
+ Rapid7ConnectionService,
+ SnykConnectionService,
+ CrowdstrikeConnectionService,
+ MicrosoftdefenderConnectionService,
+ ],
+ exports: [CybersecurityConnectionsService],
+})
+export class CybersecurityConnectionsModule {}
diff --git a/packages/api/src/@core/connections/cybersecurity/services/crowdstrike/crowdstrike.service.ts b/packages/api/src/@core/connections/cybersecurity/services/crowdstrike/crowdstrike.service.ts
new file mode 100644
index 000000000..4fcff71f9
--- /dev/null
+++ b/packages/api/src/@core/connections/cybersecurity/services/crowdstrike/crowdstrike.service.ts
@@ -0,0 +1,195 @@
+import { EncryptionService } from '@@core/@core-services/encryption/encryption.service';
+import { LoggerService } from '@@core/@core-services/logger/logger.service';
+import { PrismaService } from '@@core/@core-services/prisma/prisma.service';
+import { RetryHandler } from '@@core/@core-services/request-retry/retry.handler';
+import { ConnectionsStrategiesService } from '@@core/connections-strategies/connections-strategies.service';
+import { ConnectionUtils } from '@@core/connections/@utils';
+import {
+ AbstractBaseConnectionService,
+ OAuthCallbackParams,
+ PassthroughInput,
+ RefreshParams,
+} from '@@core/connections/@utils/types';
+import { PassthroughResponse } from '@@core/passthrough/types';
+import { Injectable } from '@nestjs/common';
+import {
+ AuthStrategy,
+ CONNECTORS_METADATA,
+ OAuth2AuthData,
+ providerToType,
+} from '@panora/shared';
+import { v4 as uuidv4 } from 'uuid';
+import { ServiceRegistry } from '../registry.service';
+import { EnvironmentService } from '@@core/@core-services/environment/environment.service';
+import axios from 'axios';
+
+export interface CrowdstrikeOAuthResponse {
+ access_token: string;
+ token_type: string;
+ scope: string;
+}
+
+@Injectable()
+export class CrowdstrikeConnectionService extends AbstractBaseConnectionService {
+ private readonly type: string;
+
+ constructor(
+ protected prisma: PrismaService,
+ private logger: LoggerService,
+ protected cryptoService: EncryptionService,
+ private env: EnvironmentService,
+ private registry: ServiceRegistry,
+ private connectionUtils: ConnectionUtils,
+ private cService: ConnectionsStrategiesService,
+ private retryService: RetryHandler,
+ ) {
+ super(prisma, cryptoService);
+ this.logger.setContext(CrowdstrikeConnectionService.name);
+ this.registry.registerService('crowdstrike', this);
+ this.type = providerToType(
+ 'crowdstrike',
+ 'cybersecurity',
+ AuthStrategy.oauth2,
+ );
+ }
+
+ async passthrough(
+ input: PassthroughInput,
+ connectionId: string,
+ ): Promise {
+ try {
+ const { headers } = input;
+ const config = await this.constructPassthrough(input, connectionId);
+
+ const connection = await this.prisma.connections.findUnique({
+ where: {
+ id_connection: connectionId,
+ },
+ });
+
+ const access_token = JSON.parse(
+ this.cryptoService.decrypt(connection.access_token),
+ );
+ config.headers = {
+ ...config.headers,
+ ...headers,
+ Authorization: `Bearer ${access_token}`,
+ };
+
+ return await this.retryService.makeRequest(
+ {
+ method: config.method,
+ url: config.url,
+ data: config.data,
+ headers: config.headers,
+ },
+ 'cybersecurity.crowdstrike.passthrough',
+ config.linkedUserId,
+ );
+ } catch (error) {
+ throw error;
+ }
+ }
+
+ async handleCallback(opts: OAuthCallbackParams) {
+ try {
+ const { linkedUserId, projectId, code } = opts;
+ const isNotUnique = await this.prisma.connections.findFirst({
+ where: {
+ id_linked_user: linkedUserId,
+ provider_slug: 'crowdstrike',
+ vertical: 'cybersecurity',
+ },
+ });
+ //reconstruct the redirect URI that was passed in the frontend it must be the same
+ const REDIRECT_URI = `${
+ this.env.getDistributionMode() == 'selfhost'
+ ? this.env.getTunnelIngress()
+ : this.env.getPanoraBaseUrl()
+ }/connections/oauth/callback`;
+
+ const CREDENTIALS = (await this.cService.getCredentials(
+ projectId,
+ this.type,
+ )) as OAuth2AuthData;
+
+ const formData = new URLSearchParams({
+ redirect_uri: REDIRECT_URI,
+ client_id: CREDENTIALS.CLIENT_ID,
+ client_secret: CREDENTIALS.CLIENT_SECRET,
+ code: code,
+ grant_type: 'authorization_code',
+ });
+ const res = await axios.post(
+ 'https://api.crowdstrike.com/oauth/access_token',
+ formData.toString(),
+ {
+ headers: {
+ 'Content-Type': 'application/x-www-form-urlencoded;charset=utf-8',
+ },
+ },
+ );
+ const data: CrowdstrikeOAuthResponse = res.data;
+ // save tokens for this customer inside our db
+ let db_res;
+ const connection_token = uuidv4();
+ const BASE_API_URL = CONNECTORS_METADATA['cybersecurity']['crowdstrike']
+ .urls.apiUrl as string;
+ // get the site id for the token
+ const site = await axios.get('https://api.crowdstrike.com/v2/sites', {
+ headers: {
+ 'Content-Type': 'application/x-www-form-urlencoded;charset=utf-8',
+ Authorization: `Bearer ${data.access_token}`,
+ },
+ });
+ const site_id = site.data.sites[0].id;
+ if (isNotUnique) {
+ // Update existing connection
+ db_res = await this.prisma.connections.update({
+ where: {
+ id_connection: isNotUnique.id_connection,
+ },
+ data: {
+ access_token: this.cryptoService.encrypt(data.access_token),
+ status: 'valid',
+ created_at: new Date(),
+ },
+ });
+ } else {
+ // Create new connection
+ db_res = await this.prisma.connections.create({
+ data: {
+ id_connection: uuidv4(),
+ connection_token: connection_token,
+ provider_slug: 'crowdstrike',
+ vertical: 'cybersecurity',
+ token_type: 'oauth2',
+ account_url: `${BASE_API_URL}/sites/${site_id}`,
+ access_token: this.cryptoService.encrypt(data.access_token),
+ status: 'valid',
+ created_at: new Date(),
+ projects: {
+ connect: { id_project: projectId },
+ },
+ linked_users: {
+ connect: {
+ id_linked_user: await this.connectionUtils.getLinkedUserId(
+ projectId,
+ linkedUserId,
+ ),
+ },
+ },
+ },
+ });
+ }
+ this.logger.log('Successfully added tokens inside DB ' + db_res);
+ return db_res;
+ } catch (error) {
+ throw error;
+ }
+ }
+
+ async handleTokenRefresh(opts: RefreshParams) {
+ return;
+ }
+}
diff --git a/packages/api/src/@core/connections/cybersecurity/services/cybersecurity.connection.service.ts b/packages/api/src/@core/connections/cybersecurity/services/cybersecurity.connection.service.ts
new file mode 100644
index 000000000..586f81b2e
--- /dev/null
+++ b/packages/api/src/@core/connections/cybersecurity/services/cybersecurity.connection.service.ts
@@ -0,0 +1,129 @@
+import { LoggerService } from '@@core/@core-services/logger/logger.service';
+import { PrismaService } from '@@core/@core-services/prisma/prisma.service';
+import { WebhookService } from '@@core/@core-services/webhooks/panora-webhooks/webhook.service';
+import {
+ CallbackParams,
+ IConnectionCategory,
+ PassthroughInput,
+ RefreshParams,
+} from '@@core/connections/@utils/types';
+import { Injectable } from '@nestjs/common';
+import { connections as Connection } from '@prisma/client';
+import { v4 as uuidv4 } from 'uuid';
+import { ServiceRegistry } from './registry.service';
+import { CategoryConnectionRegistry } from '@@core/@core-services/registries/connections-categories.registry';
+import { PassthroughResponse } from '@@core/passthrough/types';
+
+@Injectable()
+export class CybersecurityConnectionsService implements IConnectionCategory {
+ constructor(
+ private serviceRegistry: ServiceRegistry,
+ private connectionCategoryRegistry: CategoryConnectionRegistry,
+ private webhook: WebhookService,
+ private logger: LoggerService,
+ private prisma: PrismaService,
+ ) {
+ this.logger.setContext(CybersecurityConnectionsService.name);
+ this.connectionCategoryRegistry.registerService('cybersecurity', this);
+ }
+ //STEP 1:[FRONTEND STEP]
+ //create a frontend SDK snippet in which an authorization embedded link is set up so when users click
+ // on it to grant access => they grant US the access and then when confirmed
+ /*const authUrl =
+ 'https://app.hubspot.com/oauth/authorize' +
+ `?client_id=${encodeURIComponent(CLIENT_ID)}` +
+ `&scope=${encodeURIComponent(SCOPES)}` +
+ `&redirect_uri=${encodeURIComponent(REDIRECT_URI)}`;*/ //oauth/callback
+
+ // oauth server calls this redirect callback
+ // WE WOULD HAVE CREATED A DEV ACCOUNT IN THE 5 CRMs (Panora dev account)
+ // we catch the tmp token and swap it against oauth2 server for access/refresh tokens
+ // to perform actions on his behalf
+ // this call pass 1. integrationID 2. CustomerId 3. Panora Api Key
+ async handleCallBack(
+ providerName: string,
+ callbackOpts: CallbackParams,
+ type_strategy: 'oauth2' | 'apikey' | 'basic',
+ ) {
+ try {
+ const serviceName = providerName.toLowerCase();
+
+ const service = this.serviceRegistry.getService(serviceName);
+
+ if (!service) {
+ throw new ReferenceError(`Unknown provider, found ${providerName}`);
+ }
+ const data: Connection = await service.handleCallback(callbackOpts);
+ const event = await this.prisma.events.create({
+ data: {
+ id_connection: data.id_connection,
+ id_project: data.id_project,
+ id_event: uuidv4(),
+ status: 'success',
+ type: 'connection.created',
+ method: 'GET',
+ url: `/${type_strategy}/callback`,
+ provider: providerName.toLowerCase(),
+ direction: '0',
+ timestamp: new Date(),
+ id_linked_user: callbackOpts.linkedUserId,
+ },
+ });
+ //directly send the webhook
+ await this.webhook.dispatchWebhook(
+ data,
+ 'connection.created',
+ callbackOpts.projectId,
+ event.id_event,
+ );
+ } catch (error) {
+ throw error;
+ }
+ }
+
+ async handleTokensRefresh(
+ connectionId: string,
+ providerName: string,
+ refresh_token: string,
+ id_project: string,
+ account_url?: string,
+ ) {
+ try {
+ const serviceName = providerName.toLowerCase();
+ const service = this.serviceRegistry.getService(serviceName);
+ if (!service) {
+ throw new ReferenceError(`Unknown provider, found ${providerName}`);
+ }
+ const refreshOpts: RefreshParams = {
+ connectionId: connectionId,
+ refreshToken: refresh_token,
+ account_url: account_url,
+ projectId: id_project,
+ };
+ await service.handleTokenRefresh(refreshOpts);
+ } catch (error) {
+ throw error;
+ }
+ }
+
+ async passthrough(
+ input: PassthroughInput,
+ connectionId: string,
+ ): Promise {
+ try {
+ const connection = await this.prisma.connections.findUnique({
+ where: {
+ id_connection: connectionId,
+ },
+ });
+ const serviceName = connection.provider_slug.toLowerCase();
+ const service = this.serviceRegistry.getService(serviceName);
+ if (!service) {
+ throw new ReferenceError(`Unknown provider, found ${serviceName}`);
+ }
+ return await service.passthrough(input, connectionId);
+ } catch (error) {
+ throw error;
+ }
+ }
+}
diff --git a/packages/api/src/@core/connections/cybersecurity/services/microsoftdefender/microsoftdefender.service.ts b/packages/api/src/@core/connections/cybersecurity/services/microsoftdefender/microsoftdefender.service.ts
new file mode 100644
index 000000000..c874a92ba
--- /dev/null
+++ b/packages/api/src/@core/connections/cybersecurity/services/microsoftdefender/microsoftdefender.service.ts
@@ -0,0 +1,199 @@
+import { EncryptionService } from '@@core/@core-services/encryption/encryption.service';
+import { LoggerService } from '@@core/@core-services/logger/logger.service';
+import { PrismaService } from '@@core/@core-services/prisma/prisma.service';
+import { RetryHandler } from '@@core/@core-services/request-retry/retry.handler';
+import { ConnectionsStrategiesService } from '@@core/connections-strategies/connections-strategies.service';
+import { ConnectionUtils } from '@@core/connections/@utils';
+import {
+ AbstractBaseConnectionService,
+ OAuthCallbackParams,
+ PassthroughInput,
+ RefreshParams,
+} from '@@core/connections/@utils/types';
+import { PassthroughResponse } from '@@core/passthrough/types';
+import { Injectable } from '@nestjs/common';
+import {
+ AuthStrategy,
+ CONNECTORS_METADATA,
+ OAuth2AuthData,
+ providerToType,
+} from '@panora/shared';
+import { v4 as uuidv4 } from 'uuid';
+import { ServiceRegistry } from '../registry.service';
+import { EnvironmentService } from '@@core/@core-services/environment/environment.service';
+import axios from 'axios';
+
+export interface MicrosoftdefenderOAuthResponse {
+ access_token: string;
+ token_type: string;
+ scope: string;
+}
+
+@Injectable()
+export class MicrosoftdefenderConnectionService extends AbstractBaseConnectionService {
+ private readonly type: string;
+
+ constructor(
+ protected prisma: PrismaService,
+ private logger: LoggerService,
+ protected cryptoService: EncryptionService,
+ private env: EnvironmentService,
+ private registry: ServiceRegistry,
+ private connectionUtils: ConnectionUtils,
+ private cService: ConnectionsStrategiesService,
+ private retryService: RetryHandler,
+ ) {
+ super(prisma, cryptoService);
+ this.logger.setContext(MicrosoftdefenderConnectionService.name);
+ this.registry.registerService('microsoftdefender', this);
+ this.type = providerToType(
+ 'microsoftdefender',
+ 'cybersecurity',
+ AuthStrategy.oauth2,
+ );
+ }
+
+ async passthrough(
+ input: PassthroughInput,
+ connectionId: string,
+ ): Promise {
+ try {
+ const { headers } = input;
+ const config = await this.constructPassthrough(input, connectionId);
+
+ const connection = await this.prisma.connections.findUnique({
+ where: {
+ id_connection: connectionId,
+ },
+ });
+
+ const access_token = JSON.parse(
+ this.cryptoService.decrypt(connection.access_token),
+ );
+ config.headers = {
+ ...config.headers,
+ ...headers,
+ Authorization: `Bearer ${access_token}`,
+ };
+
+ return await this.retryService.makeRequest(
+ {
+ method: config.method,
+ url: config.url,
+ data: config.data,
+ headers: config.headers,
+ },
+ 'cybersecurity.microsoftdefender.passthrough',
+ config.linkedUserId,
+ );
+ } catch (error) {
+ throw error;
+ }
+ }
+
+ async handleCallback(opts: OAuthCallbackParams) {
+ try {
+ const { linkedUserId, projectId, code } = opts;
+ const isNotUnique = await this.prisma.connections.findFirst({
+ where: {
+ id_linked_user: linkedUserId,
+ provider_slug: 'microsoftdefender',
+ vertical: 'cybersecurity',
+ },
+ });
+ //reconstruct the redirect URI that was passed in the frontend it must be the same
+ const REDIRECT_URI = `${
+ this.env.getDistributionMode() == 'selfhost'
+ ? this.env.getTunnelIngress()
+ : this.env.getPanoraBaseUrl()
+ }/connections/oauth/callback`;
+
+ const CREDENTIALS = (await this.cService.getCredentials(
+ projectId,
+ this.type,
+ )) as OAuth2AuthData;
+
+ const formData = new URLSearchParams({
+ redirect_uri: REDIRECT_URI,
+ client_id: CREDENTIALS.CLIENT_ID,
+ client_secret: CREDENTIALS.CLIENT_SECRET,
+ code: code,
+ grant_type: 'authorization_code',
+ });
+ const res = await axios.post(
+ 'https://api.microsoftdefender.com/oauth/access_token',
+ formData.toString(),
+ {
+ headers: {
+ 'Content-Type': 'application/x-www-form-urlencoded;charset=utf-8',
+ },
+ },
+ );
+ const data: MicrosoftdefenderOAuthResponse = res.data;
+ // save tokens for this customer inside our db
+ let db_res;
+ const connection_token = uuidv4();
+ const BASE_API_URL = CONNECTORS_METADATA['cybersecurity'][
+ 'microsoftdefender'
+ ].urls.apiUrl as string;
+ // get the site id for the token
+ const site = await axios.get(
+ 'https://api.microsoftdefender.com/v2/sites',
+ {
+ headers: {
+ 'Content-Type': 'application/x-www-form-urlencoded;charset=utf-8',
+ Authorization: `Bearer ${data.access_token}`,
+ },
+ },
+ );
+ const site_id = site.data.sites[0].id;
+ if (isNotUnique) {
+ // Update existing connection
+ db_res = await this.prisma.connections.update({
+ where: {
+ id_connection: isNotUnique.id_connection,
+ },
+ data: {
+ access_token: this.cryptoService.encrypt(data.access_token),
+ status: 'valid',
+ created_at: new Date(),
+ },
+ });
+ } else {
+ // Create new connection
+ db_res = await this.prisma.connections.create({
+ data: {
+ id_connection: uuidv4(),
+ connection_token: connection_token,
+ provider_slug: 'microsoftdefender',
+ vertical: 'cybersecurity',
+ token_type: 'oauth2',
+ account_url: `${BASE_API_URL}/sites/${site_id}`,
+ access_token: this.cryptoService.encrypt(data.access_token),
+ status: 'valid',
+ created_at: new Date(),
+ projects: {
+ connect: { id_project: projectId },
+ },
+ linked_users: {
+ connect: {
+ id_linked_user: await this.connectionUtils.getLinkedUserId(
+ projectId,
+ linkedUserId,
+ ),
+ },
+ },
+ },
+ });
+ }
+ this.logger.log('Successfully added tokens inside DB ' + db_res);
+ return db_res;
+ } catch (error) {
+ throw error;
+ }
+ }
+
+ async handleTokenRefresh(opts: RefreshParams) {
+ return;
+ }
+}
diff --git a/packages/api/src/@core/connections/cybersecurity/services/qualys/qualys.service.ts b/packages/api/src/@core/connections/cybersecurity/services/qualys/qualys.service.ts
new file mode 100644
index 000000000..7840147b9
--- /dev/null
+++ b/packages/api/src/@core/connections/cybersecurity/services/qualys/qualys.service.ts
@@ -0,0 +1,156 @@
+import { EncryptionService } from '@@core/@core-services/encryption/encryption.service';
+import { LoggerService } from '@@core/@core-services/logger/logger.service';
+import { PrismaService } from '@@core/@core-services/prisma/prisma.service';
+import { RetryHandler } from '@@core/@core-services/request-retry/retry.handler';
+import { ConnectionsStrategiesService } from '@@core/connections-strategies/connections-strategies.service';
+import { ConnectionUtils } from '@@core/connections/@utils';
+import {
+ AbstractBaseConnectionService,
+ OAuthCallbackParams,
+ PassthroughInput,
+ RefreshParams,
+} from '@@core/connections/@utils/types';
+import { PassthroughResponse } from '@@core/passthrough/types';
+import { Injectable } from '@nestjs/common';
+import {
+ AuthStrategy,
+ CONNECTORS_METADATA,
+ DynamicApiUrl,
+ providerToType,
+} from '@panora/shared';
+import { v4 as uuidv4 } from 'uuid';
+import { ServiceRegistry } from '../registry.service';
+
+@Injectable()
+export class QualysConnectionService extends AbstractBaseConnectionService {
+ private readonly type: string;
+
+ constructor(
+ protected prisma: PrismaService,
+ private logger: LoggerService,
+ protected cryptoService: EncryptionService,
+ private registry: ServiceRegistry,
+ private connectionUtils: ConnectionUtils,
+ private cService: ConnectionsStrategiesService,
+ private retryService: RetryHandler,
+ ) {
+ super(prisma, cryptoService);
+ this.logger.setContext(QualysConnectionService.name);
+ this.registry.registerService('qualys', this);
+ this.type = providerToType('qualys', 'cybersecurity', AuthStrategy.oauth2);
+ }
+
+ async passthrough(
+ input: PassthroughInput,
+ connectionId: string,
+ ): Promise {
+ try {
+ const { headers } = input;
+ const config = await this.constructPassthrough(input, connectionId);
+
+ const connection = await this.prisma.connections.findUnique({
+ where: {
+ id_connection: connectionId,
+ },
+ });
+ const decryptedData = JSON.parse(
+ this.cryptoService.decrypt(connection.access_token),
+ );
+
+ const { username, password } = decryptedData;
+
+ config.headers = {
+ ...config.headers,
+ ...headers,
+ 'X-Requested-With': 'Curl Sample',
+ Authorization: `Basic ${Buffer.from(`${username}:${password}`).toString(
+ 'base64',
+ )}`,
+ };
+
+ return await this.retryService.makeRequest(
+ {
+ method: config.method,
+ url: config.url,
+ data: config.data,
+ headers: config.headers,
+ },
+ 'cybersecurity.qualys.passthrough',
+ config.linkedUserId,
+ );
+ } catch (error) {
+ throw error;
+ }
+ }
+
+ async handleCallback(opts: OAuthCallbackParams) {
+ try {
+ const { linkedUserId, projectId, body } = opts;
+ const { username, password, api_url } = body;
+ const isNotUnique = await this.prisma.connections.findFirst({
+ where: {
+ id_linked_user: linkedUserId,
+ provider_slug: 'qualys',
+ vertical: 'cybersecurity',
+ },
+ });
+
+ let db_res;
+ const connection_token = uuidv4();
+ const BASE_API_URL = (
+ CONNECTORS_METADATA['cybersecurity']['qualys'].urls
+ .apiUrl as DynamicApiUrl
+ )(api_url);
+
+ if (isNotUnique) {
+ db_res = await this.prisma.connections.update({
+ where: {
+ id_connection: isNotUnique.id_connection,
+ },
+ data: {
+ access_token: this.cryptoService.encrypt(
+ JSON.stringify({ username, password }),
+ ),
+ account_url: BASE_API_URL,
+ status: 'valid',
+ created_at: new Date(),
+ },
+ });
+ } else {
+ db_res = await this.prisma.connections.create({
+ data: {
+ id_connection: uuidv4(),
+ connection_token: connection_token,
+ provider_slug: 'qualys',
+ vertical: 'cybersecurity',
+ token_type: 'basic',
+ account_url: BASE_API_URL,
+ access_token: this.cryptoService.encrypt(
+ JSON.stringify({ username, password }),
+ ),
+ status: 'valid',
+ created_at: new Date(),
+ projects: {
+ connect: { id_project: projectId },
+ },
+ linked_users: {
+ connect: {
+ id_linked_user: await this.connectionUtils.getLinkedUserId(
+ projectId,
+ linkedUserId,
+ ),
+ },
+ },
+ },
+ });
+ }
+ return db_res;
+ } catch (error) {
+ throw error;
+ }
+ }
+
+ handleTokenRefresh?(opts: RefreshParams): Promise {
+ throw new Error('Method not implemented.');
+ }
+}
diff --git a/packages/api/src/@core/connections/cybersecurity/services/rapid7insightvm/rapid7.service.ts b/packages/api/src/@core/connections/cybersecurity/services/rapid7insightvm/rapid7.service.ts
new file mode 100644
index 000000000..12e5cd767
--- /dev/null
+++ b/packages/api/src/@core/connections/cybersecurity/services/rapid7insightvm/rapid7.service.ts
@@ -0,0 +1,145 @@
+import { EncryptionService } from '@@core/@core-services/encryption/encryption.service';
+import { LoggerService } from '@@core/@core-services/logger/logger.service';
+import { PrismaService } from '@@core/@core-services/prisma/prisma.service';
+import { RetryHandler } from '@@core/@core-services/request-retry/retry.handler';
+import { ConnectionsStrategiesService } from '@@core/connections-strategies/connections-strategies.service';
+import { ConnectionUtils } from '@@core/connections/@utils';
+import {
+ AbstractBaseConnectionService,
+ OAuthCallbackParams,
+ PassthroughInput,
+ RefreshParams,
+} from '@@core/connections/@utils/types';
+import { PassthroughResponse } from '@@core/passthrough/types';
+import { Injectable } from '@nestjs/common';
+import {
+ AuthStrategy,
+ CONNECTORS_METADATA,
+ DynamicApiUrl,
+ providerToType,
+} from '@panora/shared';
+import { v4 as uuidv4 } from 'uuid';
+import { ServiceRegistry } from '../registry.service';
+
+@Injectable()
+export class Rapid7ConnectionService extends AbstractBaseConnectionService {
+ private readonly type: string;
+
+ constructor(
+ protected prisma: PrismaService,
+ private logger: LoggerService,
+ protected cryptoService: EncryptionService,
+ private registry: ServiceRegistry,
+ private connectionUtils: ConnectionUtils,
+ private cService: ConnectionsStrategiesService,
+ private retryService: RetryHandler,
+ ) {
+ super(prisma, cryptoService);
+ this.logger.setContext(Rapid7ConnectionService.name);
+ this.registry.registerService('rapid7', this);
+ this.type = providerToType('rapid7', 'cybersecurity', AuthStrategy.oauth2);
+ }
+
+ async passthrough(
+ input: PassthroughInput,
+ connectionId: string,
+ ): Promise {
+ try {
+ const { headers } = input;
+ const config = await this.constructPassthrough(input, connectionId);
+
+ const connection = await this.prisma.connections.findUnique({
+ where: {
+ id_connection: connectionId,
+ },
+ });
+ config.headers = {
+ ...config.headers,
+ ...headers,
+ Authorization: `Basic ${Buffer.from(
+ `:${connection.access_token}`,
+ ).toString('base64')}`,
+ };
+
+ return await this.retryService.makeRequest(
+ {
+ method: config.method,
+ url: config.url,
+ data: config.data,
+ headers: config.headers,
+ },
+ 'cybersecurity.rapid7.passthrough',
+ config.linkedUserId,
+ );
+ } catch (error) {
+ throw error;
+ }
+ }
+
+ async handleCallback(opts: OAuthCallbackParams) {
+ try {
+ const { linkedUserId, projectId, body } = opts;
+ const { api_key, region } = body;
+ const isNotUnique = await this.prisma.connections.findFirst({
+ where: {
+ id_linked_user: linkedUserId,
+ provider_slug: 'rapid7',
+ vertical: 'cybersecurity',
+ },
+ });
+
+ let db_res;
+ const connection_token = uuidv4();
+ const BASE_API_URL = (
+ CONNECTORS_METADATA['cybersecurity']['rapid7'].urls
+ .apiUrl as DynamicApiUrl
+ )(region);
+
+ if (isNotUnique) {
+ db_res = await this.prisma.connections.update({
+ where: {
+ id_connection: isNotUnique.id_connection,
+ },
+ data: {
+ access_token: this.cryptoService.encrypt(api_key),
+ account_url: BASE_API_URL,
+ status: 'valid',
+ created_at: new Date(),
+ },
+ });
+ } else {
+ db_res = await this.prisma.connections.create({
+ data: {
+ id_connection: uuidv4(),
+ connection_token: connection_token,
+ provider_slug: 'rapid7',
+ vertical: 'cybersecurity',
+ token_type: 'basic',
+ account_url: BASE_API_URL,
+ access_token: this.cryptoService.encrypt(api_key),
+ status: 'valid',
+ created_at: new Date(),
+ projects: {
+ connect: { id_project: projectId },
+ },
+ linked_users: {
+ connect: {
+ id_linked_user: await this.connectionUtils.getLinkedUserId(
+ projectId,
+ linkedUserId,
+ ),
+ },
+ },
+ },
+ });
+ }
+ return db_res;
+ } catch (error) {
+ throw error;
+ }
+ }
+
+ handleTokenRefresh?(opts: RefreshParams): Promise {
+ throw new Error('Method not implemented.');
+ }
+}
diff --git a/packages/api/src/@core/connections/cybersecurity/services/registry.service.ts b/packages/api/src/@core/connections/cybersecurity/services/registry.service.ts
new file mode 100644
index 000000000..2e9e3b100
--- /dev/null
+++ b/packages/api/src/@core/connections/cybersecurity/services/registry.service.ts
@@ -0,0 +1,25 @@
+import { IConnectionService } from '@@core/connections/@utils/types';
+import { Injectable } from '@nestjs/common';
+
+@Injectable()
+export class ServiceRegistry {
+ private serviceMap: Map;
+
+ constructor() {
+ this.serviceMap = new Map();
+ }
+
+ registerService(serviceKey: string, service: IConnectionService) {
+ this.serviceMap.set(serviceKey, service);
+ }
+
+ getService(integrationId: string): IConnectionService {
+ const service = this.serviceMap.get(integrationId);
+ if (!service) {
+ throw new ReferenceError(
+ `Service not found for integration ID: ${integrationId}`,
+ );
+ }
+ return service;
+ }
+}
diff --git a/packages/api/src/@core/connections/cybersecurity/services/semgrep/semgrep.service.ts b/packages/api/src/@core/connections/cybersecurity/services/semgrep/semgrep.service.ts
new file mode 100644
index 000000000..7bd36d5d0
--- /dev/null
+++ b/packages/api/src/@core/connections/cybersecurity/services/semgrep/semgrep.service.ts
@@ -0,0 +1,143 @@
+import { EncryptionService } from '@@core/@core-services/encryption/encryption.service';
+import { LoggerService } from '@@core/@core-services/logger/logger.service';
+import { PrismaService } from '@@core/@core-services/prisma/prisma.service';
+import { RetryHandler } from '@@core/@core-services/request-retry/retry.handler';
+import { ConnectionsStrategiesService } from '@@core/connections-strategies/connections-strategies.service';
+import { ConnectionUtils } from '@@core/connections/@utils';
+import {
+ AbstractBaseConnectionService,
+ OAuthCallbackParams,
+ PassthroughInput,
+ RefreshParams,
+} from '@@core/connections/@utils/types';
+import { PassthroughResponse } from '@@core/passthrough/types';
+import { Injectable } from '@nestjs/common';
+import {
+ AuthStrategy,
+ CONNECTORS_METADATA,
+ DynamicApiUrl,
+ providerToType,
+} from '@panora/shared';
+import { v4 as uuidv4 } from 'uuid';
+import { ServiceRegistry } from '../registry.service';
+
+@Injectable()
+export class SemgrepConnectionService extends AbstractBaseConnectionService {
+ private readonly type: string;
+
+ constructor(
+ protected prisma: PrismaService,
+ private logger: LoggerService,
+ protected cryptoService: EncryptionService,
+ private registry: ServiceRegistry,
+ private connectionUtils: ConnectionUtils,
+ private cService: ConnectionsStrategiesService,
+ private retryService: RetryHandler,
+ ) {
+ super(prisma, cryptoService);
+ this.logger.setContext(SemgrepConnectionService.name);
+ this.registry.registerService('semgrep', this);
+ this.type = providerToType('semgrep', 'cybersecurity', AuthStrategy.oauth2);
+ }
+
+ async passthrough(
+ input: PassthroughInput,
+ connectionId: string,
+ ): Promise {
+ try {
+ const { headers } = input;
+ const config = await this.constructPassthrough(input, connectionId);
+
+ const connection = await this.prisma.connections.findUnique({
+ where: {
+ id_connection: connectionId,
+ },
+ });
+ config.headers = {
+ ...config.headers,
+ ...headers,
+ Authorization: `Bearer ${this.cryptoService.decrypt(
+ connection.access_token,
+ )}`,
+ };
+
+ return await this.retryService.makeRequest(
+ {
+ method: config.method,
+ url: config.url,
+ data: config.data,
+ headers: config.headers,
+ },
+ 'cybersecurity.semgrep.passthrough',
+ config.linkedUserId,
+ );
+ } catch (error) {
+ throw error;
+ }
+ }
+
+ async handleCallback(opts: OAuthCallbackParams) {
+ try {
+ const { linkedUserId, projectId, body } = opts;
+ const { api_key } = body;
+ const isNotUnique = await this.prisma.connections.findFirst({
+ where: {
+ id_linked_user: linkedUserId,
+ provider_slug: 'semgrep',
+ vertical: 'cybersecurity',
+ },
+ });
+
+ let db_res;
+ const connection_token = uuidv4();
+ const BASE_API_URL = CONNECTORS_METADATA['cybersecurity']['semgrep'].urls
+ .apiUrl as string;
+
+ if (isNotUnique) {
+ db_res = await this.prisma.connections.update({
+ where: {
+ id_connection: isNotUnique.id_connection,
+ },
+ data: {
+ access_token: this.cryptoService.encrypt(api_key),
+ account_url: BASE_API_URL,
+ status: 'valid',
+ created_at: new Date(),
+ },
+ });
+ } else {
+ db_res = await this.prisma.connections.create({
+ data: {
+ id_connection: uuidv4(),
+ connection_token: connection_token,
+ provider_slug: 'semgrep',
+ vertical: 'cybersecurity',
+ token_type: 'basic',
+ account_url: BASE_API_URL,
+ access_token: this.cryptoService.encrypt(api_key),
+ status: 'valid',
+ created_at: new Date(),
+ projects: {
+ connect: { id_project: projectId },
+ },
+ linked_users: {
+ connect: {
+ id_linked_user: await this.connectionUtils.getLinkedUserId(
+ projectId,
+ linkedUserId,
+ ),
+ },
+ },
+ },
+ });
+ }
+ return db_res;
+ } catch (error) {
+ throw error;
+ }
+ }
+
+ handleTokenRefresh?(opts: RefreshParams): Promise {
+ throw new Error('Method not implemented.');
+ }
+}
diff --git a/packages/api/src/@core/connections/cybersecurity/services/sentinelone/sentinelone.service.ts b/packages/api/src/@core/connections/cybersecurity/services/sentinelone/sentinelone.service.ts
new file mode 100644
index 000000000..7d6f02fb5
--- /dev/null
+++ b/packages/api/src/@core/connections/cybersecurity/services/sentinelone/sentinelone.service.ts
@@ -0,0 +1,149 @@
+import { EncryptionService } from '@@core/@core-services/encryption/encryption.service';
+import { LoggerService } from '@@core/@core-services/logger/logger.service';
+import { PrismaService } from '@@core/@core-services/prisma/prisma.service';
+import { RetryHandler } from '@@core/@core-services/request-retry/retry.handler';
+import { ConnectionsStrategiesService } from '@@core/connections-strategies/connections-strategies.service';
+import { ConnectionUtils } from '@@core/connections/@utils';
+import {
+ AbstractBaseConnectionService,
+ OAuthCallbackParams,
+ PassthroughInput,
+ RefreshParams,
+} from '@@core/connections/@utils/types';
+import { PassthroughResponse } from '@@core/passthrough/types';
+import { Injectable } from '@nestjs/common';
+import {
+ AuthStrategy,
+ CONNECTORS_METADATA,
+ DynamicApiUrl,
+ providerToType,
+} from '@panora/shared';
+import { v4 as uuidv4 } from 'uuid';
+import { ServiceRegistry } from '../registry.service';
+
+@Injectable()
+export class SentineloneConnectionService extends AbstractBaseConnectionService {
+ private readonly type: string;
+
+ constructor(
+ protected prisma: PrismaService,
+ private logger: LoggerService,
+ protected cryptoService: EncryptionService,
+ private registry: ServiceRegistry,
+ private connectionUtils: ConnectionUtils,
+ private cService: ConnectionsStrategiesService,
+ private retryService: RetryHandler,
+ ) {
+ super(prisma, cryptoService);
+ this.logger.setContext(SentineloneConnectionService.name);
+ this.registry.registerService('sentinelone', this);
+ this.type = providerToType(
+ 'sentinelone',
+ 'cybersecurity',
+ AuthStrategy.oauth2,
+ );
+ }
+
+ async passthrough(
+ input: PassthroughInput,
+ connectionId: string,
+ ): Promise {
+ try {
+ const { headers } = input;
+ const config = await this.constructPassthrough(input, connectionId);
+
+ const connection = await this.prisma.connections.findUnique({
+ where: {
+ id_connection: connectionId,
+ },
+ });
+ config.headers = {
+ ...config.headers,
+ ...headers,
+ Authorization: `APIToken ${this.cryptoService.decrypt(
+ connection.access_token,
+ )}`,
+ };
+
+ return await this.retryService.makeRequest(
+ {
+ method: config.method,
+ url: config.url,
+ data: config.data,
+ headers: config.headers,
+ },
+ 'cybersecurity.sentinelone.passthrough',
+ config.linkedUserId,
+ );
+ } catch (error) {
+ throw error;
+ }
+ }
+
+ async handleCallback(opts: OAuthCallbackParams) {
+ try {
+ const { linkedUserId, projectId, body } = opts;
+ const { api_key, host } = body;
+ const isNotUnique = await this.prisma.connections.findFirst({
+ where: {
+ id_linked_user: linkedUserId,
+ provider_slug: 'sentinelone',
+ vertical: 'cybersecurity',
+ },
+ });
+
+ let db_res;
+ const connection_token = uuidv4();
+ const BASE_API_URL = (
+ CONNECTORS_METADATA['cybersecurity']['sentinelone'].urls
+ .apiUrl as DynamicApiUrl
+ )(host);
+
+ if (isNotUnique) {
+ db_res = await this.prisma.connections.update({
+ where: {
+ id_connection: isNotUnique.id_connection,
+ },
+ data: {
+ access_token: this.cryptoService.encrypt(api_key),
+ account_url: BASE_API_URL,
+ status: 'valid',
+ created_at: new Date(),
+ },
+ });
+ } else {
+ db_res = await this.prisma.connections.create({
+ data: {
+ id_connection: uuidv4(),
+ connection_token: connection_token,
+ provider_slug: 'sentinelone',
+ vertical: 'cybersecurity',
+ token_type: 'basic',
+ account_url: BASE_API_URL,
+ access_token: this.cryptoService.encrypt(api_key),
+ status: 'valid',
+ created_at: new Date(),
+ projects: {
+ connect: { id_project: projectId },
+ },
+ linked_users: {
+ connect: {
+ id_linked_user: await this.connectionUtils.getLinkedUserId(
+ projectId,
+ linkedUserId,
+ ),
+ },
+ },
+ },
+ });
+ }
+ return db_res;
+ } catch (error) {
+ throw error;
+ }
+ }
+
+ handleTokenRefresh?(opts: RefreshParams): Promise {
+ throw new Error('Method not implemented.');
+ }
+}
diff --git a/packages/api/src/@core/connections/cybersecurity/services/snyk/snyk.service.ts b/packages/api/src/@core/connections/cybersecurity/services/snyk/snyk.service.ts
new file mode 100644
index 000000000..ff77211ce
--- /dev/null
+++ b/packages/api/src/@core/connections/cybersecurity/services/snyk/snyk.service.ts
@@ -0,0 +1,191 @@
+import { EncryptionService } from '@@core/@core-services/encryption/encryption.service';
+import { LoggerService } from '@@core/@core-services/logger/logger.service';
+import { PrismaService } from '@@core/@core-services/prisma/prisma.service';
+import { RetryHandler } from '@@core/@core-services/request-retry/retry.handler';
+import { ConnectionsStrategiesService } from '@@core/connections-strategies/connections-strategies.service';
+import { ConnectionUtils } from '@@core/connections/@utils';
+import {
+ AbstractBaseConnectionService,
+ OAuthCallbackParams,
+ PassthroughInput,
+ RefreshParams,
+} from '@@core/connections/@utils/types';
+import { PassthroughResponse } from '@@core/passthrough/types';
+import { Injectable } from '@nestjs/common';
+import {
+ AuthStrategy,
+ CONNECTORS_METADATA,
+ OAuth2AuthData,
+ providerToType,
+} from '@panora/shared';
+import { v4 as uuidv4 } from 'uuid';
+import { ServiceRegistry } from '../registry.service';
+import { EnvironmentService } from '@@core/@core-services/environment/environment.service';
+import axios from 'axios';
+
+export interface SnykOAuthResponse {
+ access_token: string;
+ token_type: string;
+ scope: string;
+}
+
+@Injectable()
+export class SnykConnectionService extends AbstractBaseConnectionService {
+ private readonly type: string;
+
+ constructor(
+ protected prisma: PrismaService,
+ private logger: LoggerService,
+ protected cryptoService: EncryptionService,
+ private env: EnvironmentService,
+ private registry: ServiceRegistry,
+ private connectionUtils: ConnectionUtils,
+ private cService: ConnectionsStrategiesService,
+ private retryService: RetryHandler,
+ ) {
+ super(prisma, cryptoService);
+ this.logger.setContext(SnykConnectionService.name);
+ this.registry.registerService('snyk', this);
+ this.type = providerToType('snyk', 'cybersecurity', AuthStrategy.oauth2);
+ }
+
+ async passthrough(
+ input: PassthroughInput,
+ connectionId: string,
+ ): Promise {
+ try {
+ const { headers } = input;
+ const config = await this.constructPassthrough(input, connectionId);
+
+ const connection = await this.prisma.connections.findUnique({
+ where: {
+ id_connection: connectionId,
+ },
+ });
+
+ const access_token = JSON.parse(
+ this.cryptoService.decrypt(connection.access_token),
+ );
+ config.headers = {
+ ...config.headers,
+ ...headers,
+ Authorization: `Bearer ${access_token}`,
+ };
+
+ return await this.retryService.makeRequest(
+ {
+ method: config.method,
+ url: config.url,
+ data: config.data,
+ headers: config.headers,
+ },
+ 'cybersecurity.snyk.passthrough',
+ config.linkedUserId,
+ );
+ } catch (error) {
+ throw error;
+ }
+ }
+
+ async handleCallback(opts: OAuthCallbackParams) {
+ try {
+ const { linkedUserId, projectId, code } = opts;
+ const isNotUnique = await this.prisma.connections.findFirst({
+ where: {
+ id_linked_user: linkedUserId,
+ provider_slug: 'snyk',
+ vertical: 'cybersecurity',
+ },
+ });
+ //reconstruct the redirect URI that was passed in the frontend it must be the same
+ const REDIRECT_URI = `${
+ this.env.getDistributionMode() == 'selfhost'
+ ? this.env.getTunnelIngress()
+ : this.env.getPanoraBaseUrl()
+ }/connections/oauth/callback`;
+
+ const CREDENTIALS = (await this.cService.getCredentials(
+ projectId,
+ this.type,
+ )) as OAuth2AuthData;
+
+ const formData = new URLSearchParams({
+ redirect_uri: REDIRECT_URI,
+ client_id: CREDENTIALS.CLIENT_ID,
+ client_secret: CREDENTIALS.CLIENT_SECRET,
+ code: code,
+ grant_type: 'authorization_code',
+ });
+ const res = await axios.post(
+ 'https://api.snyk.com/oauth/access_token',
+ formData.toString(),
+ {
+ headers: {
+ 'Content-Type': 'application/x-www-form-urlencoded;charset=utf-8',
+ },
+ },
+ );
+ const data: SnykOAuthResponse = res.data;
+ // save tokens for this customer inside our db
+ let db_res;
+ const connection_token = uuidv4();
+ const BASE_API_URL = CONNECTORS_METADATA['cybersecurity']['snyk'].urls
+ .apiUrl as string;
+ // get the site id for the token
+ const site = await axios.get('https://api.snyk.com/v2/sites', {
+ headers: {
+ 'Content-Type': 'application/x-www-form-urlencoded;charset=utf-8',
+ Authorization: `Bearer ${data.access_token}`,
+ },
+ });
+ const site_id = site.data.sites[0].id;
+ if (isNotUnique) {
+ // Update existing connection
+ db_res = await this.prisma.connections.update({
+ where: {
+ id_connection: isNotUnique.id_connection,
+ },
+ data: {
+ access_token: this.cryptoService.encrypt(data.access_token),
+ status: 'valid',
+ created_at: new Date(),
+ },
+ });
+ } else {
+ // Create new connection
+ db_res = await this.prisma.connections.create({
+ data: {
+ id_connection: uuidv4(),
+ connection_token: connection_token,
+ provider_slug: 'snyk',
+ vertical: 'cybersecurity',
+ token_type: 'oauth2',
+ account_url: `${BASE_API_URL}/sites/${site_id}`,
+ access_token: this.cryptoService.encrypt(data.access_token),
+ status: 'valid',
+ created_at: new Date(),
+ projects: {
+ connect: { id_project: projectId },
+ },
+ linked_users: {
+ connect: {
+ id_linked_user: await this.connectionUtils.getLinkedUserId(
+ projectId,
+ linkedUserId,
+ ),
+ },
+ },
+ },
+ });
+ }
+ this.logger.log('Successfully added tokens inside DB ' + db_res);
+ return db_res;
+ } catch (error) {
+ throw error;
+ }
+ }
+
+ async handleTokenRefresh(opts: RefreshParams) {
+ return;
+ }
+}
diff --git a/packages/api/src/@core/connections/cybersecurity/services/tenable/tenable.service.ts b/packages/api/src/@core/connections/cybersecurity/services/tenable/tenable.service.ts
new file mode 100644
index 000000000..7c125d3d8
--- /dev/null
+++ b/packages/api/src/@core/connections/cybersecurity/services/tenable/tenable.service.ts
@@ -0,0 +1,147 @@
+import { EncryptionService } from '@@core/@core-services/encryption/encryption.service';
+import { LoggerService } from '@@core/@core-services/logger/logger.service';
+import { PrismaService } from '@@core/@core-services/prisma/prisma.service';
+import { RetryHandler } from '@@core/@core-services/request-retry/retry.handler';
+import { ConnectionsStrategiesService } from '@@core/connections-strategies/connections-strategies.service';
+import { ConnectionUtils } from '@@core/connections/@utils';
+import {
+ AbstractBaseConnectionService,
+ OAuthCallbackParams,
+ PassthroughInput,
+ RefreshParams,
+} from '@@core/connections/@utils/types';
+import { PassthroughResponse } from '@@core/passthrough/types';
+import { Injectable } from '@nestjs/common';
+import {
+ AuthStrategy,
+ CONNECTORS_METADATA,
+ DynamicApiUrl,
+ providerToType,
+} from '@panora/shared';
+import { v4 as uuidv4 } from 'uuid';
+import { ServiceRegistry } from '../registry.service';
+
+@Injectable()
+export class TenableConnectionService extends AbstractBaseConnectionService {
+ private readonly type: string;
+
+ constructor(
+ protected prisma: PrismaService,
+ private logger: LoggerService,
+ protected cryptoService: EncryptionService,
+ private registry: ServiceRegistry,
+ private connectionUtils: ConnectionUtils,
+ private cService: ConnectionsStrategiesService,
+ private retryService: RetryHandler,
+ ) {
+ super(prisma, cryptoService);
+ this.logger.setContext(TenableConnectionService.name);
+ this.registry.registerService('tenable', this);
+ this.type = providerToType('tenable', 'cybersecurity', AuthStrategy.oauth2);
+ }
+
+ async passthrough(
+ input: PassthroughInput,
+ connectionId: string,
+ ): Promise {
+ try {
+ const { headers } = input;
+ const config = await this.constructPassthrough(input, connectionId);
+
+ const connection = await this.prisma.connections.findUnique({
+ where: {
+ id_connection: connectionId,
+ },
+ });
+ const decryptedData = JSON.parse(
+ this.cryptoService.decrypt(connection.access_token),
+ );
+
+ const { access_key, secret_key } = decryptedData; // todo
+
+ config.headers = {
+ ...config.headers,
+ ...headers,
+ 'X-ApiKeys': `${secret_key}`,
+ };
+
+ return await this.retryService.makeRequest(
+ {
+ method: config.method,
+ url: config.url,
+ data: config.data,
+ headers: config.headers,
+ },
+ 'cybersecurity.tenable.passthrough',
+ config.linkedUserId,
+ );
+ } catch (error) {
+ throw error;
+ }
+ }
+
+ async handleCallback(opts: OAuthCallbackParams) {
+ try {
+ const { linkedUserId, projectId, body } = opts;
+ const { access_key, secret_key } = body;
+ const isNotUnique = await this.prisma.connections.findFirst({
+ where: {
+ id_linked_user: linkedUserId,
+ provider_slug: 'tenable',
+ vertical: 'cybersecurity',
+ },
+ });
+
+ let db_res;
+ const connection_token = uuidv4();
+ const BASE_API_URL = CONNECTORS_METADATA['cybersecurity']['tenable'].urls
+ .apiUrl as string;
+
+ if (isNotUnique) {
+ db_res = await this.prisma.connections.update({
+ where: {
+ id_connection: isNotUnique.id_connection,
+ },
+ data: {
+ access_token: this.cryptoService.encrypt(secret_key),
+ account_url: BASE_API_URL,
+ status: 'valid',
+ created_at: new Date(),
+ },
+ });
+ } else {
+ db_res = await this.prisma.connections.create({
+ data: {
+ id_connection: uuidv4(),
+ connection_token: connection_token,
+ provider_slug: 'tenable',
+ vertical: 'cybersecurity',
+ token_type: 'basic',
+ account_url: BASE_API_URL,
+ access_token: this.cryptoService.encrypt(secret_key),
+ status: 'valid',
+ created_at: new Date(),
+ projects: {
+ connect: { id_project: projectId },
+ },
+ linked_users: {
+ connect: {
+ id_linked_user: await this.connectionUtils.getLinkedUserId(
+ projectId,
+ linkedUserId,
+ ),
+ },
+ },
+ },
+ });
+ }
+ return db_res;
+ } catch (error) {
+ throw error;
+ }
+ }
+
+ handleTokenRefresh?(opts: RefreshParams): Promise {
+ throw new Error('Method not implemented.');
+ }
+}
diff --git a/packages/shared/src/categories.ts b/packages/shared/src/categories.ts
index 5cb99075e..00369f15b 100644
--- a/packages/shared/src/categories.ts
+++ b/packages/shared/src/categories.ts
@@ -7,7 +7,8 @@ export enum ConnectorCategory {
MarketingAutomation = 'marketingautomation',
FileStorage = 'filestorage',
Productivity = 'productivity',
- Ecommerce = 'ecommerce'
+ Ecommerce = 'ecommerce',
+ Cybersecurity = 'cybersecurity'
}
export const categoriesVerticals: ConnectorCategory[] = Object.values(ConnectorCategory);
diff --git a/packages/shared/src/connectors/metadata.ts b/packages/shared/src/connectors/metadata.ts
index ef65b5d6c..687f99313 100644
--- a/packages/shared/src/connectors/metadata.ts
+++ b/packages/shared/src/connectors/metadata.ts
@@ -2967,5 +2967,124 @@ export const CONNECTORS_METADATA: ProvidersConfig = {
properties: ['username', 'password', 'store_url']
}
},
+ },
+ 'cybersecurity': {
+ 'semgrep': {
+ urls: {
+ docsUrl: 'https://semgrep.dev/api/v1/docs/#section/Introduction',
+ apiUrl: 'https://semgrep.dev/api',
+ },
+ logoPath: 'https://yt3.googleusercontent.com/NWVXYvuzHDgJJsbda7eyyz21Ba2qnq5WmuGrt9ax1rs6PP-mlDl5LCJ4ZO0Z2ZbiCq4ZoxqiGg=s900-c-k-c0x00ffffff-no-rj',
+ description: 'Sync & Create orders, fulfillments, fulfillment orders, customers and products',
+ active: false,
+ primaryColor: '#10C096',
+ authStrategy: {
+ strategy: AuthStrategy.api_key,
+ properties: ['api_key']
+ }
+ },
+ 'snyk': {
+ scopes: '',
+ urls: {
+ docsUrl: 'https://docs.snyk.io/snyk-api/',
+ apiUrl: 'https://api.snyk.io',
+ authBaseUrl: 'https://app.snyk.io/oauth2/authorize'
+ },
+ logoPath: 'https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Forganization%2Fprofile_image%2F1215%2Ffe4be452-1e68-444a-bf77-db21bf3a7bdc.png',
+ description: 'Sync & Create orders, fulfillments, fulfillment orders, customers and products',
+ active: false,
+ authStrategy: {
+ strategy: AuthStrategy.oauth2
+ },
+ options: {
+ local_redirect_uri_in_https: true
+ }
+ },
+ 'tenable': {
+ urls: {
+ docsUrl: 'https://developer.tenable.com/reference/navigate',
+ apiUrl: 'https://cloud.tenable.com',
+ },
+ logoPath: 'https://pbs.twimg.com/profile_images/1410604377757216768/ocEKYniC_400x400.jpg',
+ description: 'Sync & Create orders, fulfillments, fulfillment orders, customers and products',
+ active: false,
+ primaryColor: '#0D1E40',
+ authStrategy: {
+ strategy: AuthStrategy.basic,
+ properties: ['access_key', 'secret_key']
+ }
+ },
+ 'qualys': {
+ urls: {
+ docsUrl: 'https://docs.qualys.com/en/vm/api/scans/index.htm#t=get_started%2Fauthentication.htm',
+ apiUrl: (baseApi) => `https://${baseApi}/api`
+ },
+ logoPath: 'https://companieslogo.com/img/orig/QLYS-68c2032c.png?t=1720244493',
+ description: 'Sync & Create orders, fulfillments, fulfillment orders, customers and products',
+ active: false,
+ primaryColor: '#ED2E28',
+ authStrategy: {
+ strategy: AuthStrategy.basic,
+ properties: ['username', 'password', 'api_url']
+ }
+ },
+ 'rapid7insightvm': {
+ urls: {
+ docsUrl: 'https://help.rapid7.com/insightvm/en-us/api/index.html',
+ apiUrl: (region) => `https://${region}.api.insight.rapid7.com`,
+ },
+ logoPath: 'https://images.saasworthy.com/insightvm_9113_logo_1635748346_lc0gr.png',
+ description: 'Sync & Create orders, fulfillments, fulfillment orders, customers and products',
+ active: false,
+ primaryColor: '#E95722',
+ authStrategy: {
+ strategy: AuthStrategy.api_key,
+ properties: ['region', 'api_key']
+ }
+ },
+ 'crowdstrike': {
+ scopes: '',
+ urls: {
+ docsUrl: 'https://developer.crowdstrike.com/',
+ apiUrl: (dotHost) => `https://api${dotHost}.crowdstrike.com`,
+ authBaseUrl: ''
+ },
+ logoPath: 'https://pbs.twimg.com/profile_images/1451022302578049024/6L-zG5oq_400x400.jpg',
+ description: 'Sync & Create orders, fulfillments, fulfillment orders, customers and products',
+ active: false,
+ primaryColor: '#FC0001',
+ authStrategy: {
+ strategy: AuthStrategy.oauth2,
+ }
+ },
+ 'sentinelone': {
+ urls: {
+ docsUrl: 'https://www.postman.com/api-evangelist/sentinelone/overview',
+ apiUrl: (host) => `https://${host}.sentinelone.net`,
+ },
+ logoPath: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTZHLye2za7fjLiggqC1upKhhM3T-laySJSLQ&s',
+ description: 'Sync & Create orders, fulfillments, fulfillment orders, customers and products',
+ active: false,
+ primaryColor: '#522E74',
+ authStrategy: {
+ strategy: AuthStrategy.api_key,
+ properties: ['host', 'api_key']
+ }
+ },
+ 'microsoftdefender': {
+ scopes: '',
+ urls: {
+ docsUrl: 'https://learn.microsoft.com/en-us/defender-endpoint/api/apis-intro',
+ apiUrl: '',
+ authBaseUrl: ''
+ },
+ logoPath: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSuR4GZElDP7UNKhXS9jDGpElBTdchjg8hSsA&s',
+ description: 'Sync & Create orders, fulfillments, fulfillment orders, customers and products',
+ active: false,
+ primaryColor: '#0078D8',
+ authStrategy: {
+ strategy: AuthStrategy.oauth2,
+ }
+ },
}
};
From 0ffb1be959a4ff8ed8050a3a60f14d783a7e6b3c Mon Sep 17 00:00:00 2001
From: nael
Date: Fri, 16 Aug 2024 04:51:27 +0200
Subject: [PATCH 07/49] :bug: Added fix
---
packages/api/scripts/init.sql | 3 +++
packages/api/scripts/seed.sql | 8 ++++----
packages/shared/src/connectors/metadata.ts | 3 +--
3 files changed, 8 insertions(+), 6 deletions(-)
diff --git a/packages/api/scripts/init.sql b/packages/api/scripts/init.sql
index ead5ee43c..f3bbbc437 100644
--- a/packages/api/scripts/init.sql
+++ b/packages/api/scripts/init.sql
@@ -541,6 +541,9 @@ CREATE TABLE connector_sets
crm_close boolean NULL,
fs_box boolean NULL,
tcg_github boolean NULL,
+ hris_gusto boolean NULL,
+ hris_deel boolean NULL,
+ hris_sage boolean NULL,
ecom_woocommerce boolean NULL,
ecom_shopify boolean NULL,
ecom_amazon boolean NULL,
diff --git a/packages/api/scripts/seed.sql b/packages/api/scripts/seed.sql
index 0bee28a94..7b29520da 100644
--- a/packages/api/scripts/seed.sql
+++ b/packages/api/scripts/seed.sql
@@ -1,10 +1,10 @@
INSERT INTO users (id_user, identification_strategy, email, password_hash, first_name, last_name) VALUES
('0ce39030-2901-4c56-8db0-5e326182ec6b', 'b2c','local@panora.dev', '$2b$10$Y7Q8TWGyGuc5ecdIASbBsuXMo3q/Rs3/cnY.mLZP4tUgfGUOCUBlG', 'local', 'Panora');
-INSERT INTO connector_sets (id_connector_set, crm_hubspot, crm_zoho, crm_pipedrive, crm_attio, crm_zendesk, crm_close, tcg_zendesk, tcg_gorgias, tcg_front, tcg_jira, tcg_gitlab, fs_box, tcg_github) VALUES
- ('1709da40-17f7-4d3a-93a0-96dc5da6ddd7', TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE),
- ('852dfff8-ab63-4530-ae49-e4b2924407f8', TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE),
- ('aed0f856-f802-4a79-8640-66d441581a99', TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE);
+INSERT INTO connector_sets (id_connector_set, crm_hubspot, crm_zoho, crm_pipedrive, crm_attio, crm_zendesk, crm_close, tcg_zendesk, tcg_gorgias, tcg_front, tcg_jira, tcg_gitlab, fs_box, tcg_github, hris_deel, hris_sage) VALUES
+ ('1709da40-17f7-4d3a-93a0-96dc5da6ddd7', TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE),
+ ('852dfff8-ab63-4530-ae49-e4b2924407f8', TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE),
+ ('aed0f856-f802-4a79-8640-66d441581a99', TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE);
INSERT INTO projects (id_project, name, sync_mode, id_user, id_connector_set) VALUES
('1e468c15-aa57-4448-aa2b-7fed640d1e3d', 'Project 1', 'pull', '0ce39030-2901-4c56-8db0-5e326182ec6b', '1709da40-17f7-4d3a-93a0-96dc5da6ddd7'),
diff --git a/packages/shared/src/connectors/metadata.ts b/packages/shared/src/connectors/metadata.ts
index 687f99313..a0540c9f3 100644
--- a/packages/shared/src/connectors/metadata.ts
+++ b/packages/shared/src/connectors/metadata.ts
@@ -2026,7 +2026,7 @@ export const CONNECTORS_METADATA: ProvidersConfig = {
},
logoPath: 'https://asset.brandfetch.io/id4NSNrRnG/idXzwlo3iL.jpeg',
description: 'Sync & Create contacts, deals, companies, notes, engagements, stages, tasks and users',
- active: false,
+ active: true,
authStrategy: {
strategy: AuthStrategy.oauth2
},
@@ -2566,7 +2566,6 @@ export const CONNECTORS_METADATA: ProvidersConfig = {
}
},
'sage': {
- scopes: '',
urls: {
docsUrl: 'https://sagehr.docs.apiary.io/#reference',
apiUrl: (subdomain) => `https://${subdomain}.sage.hr`
From e3a079bf9e7f6fd4bc37df12da77642fe1ddd985 Mon Sep 17 00:00:00 2001
From: nael
Date: Fri, 16 Aug 2024 04:53:26 +0200
Subject: [PATCH 08/49] :pencil2: Fix
---
packages/api/scripts/init.sql | 1 +
packages/api/scripts/seed.sql | 8 ++++----
packages/shared/src/connectors/metadata.ts | 6 +++---
3 files changed, 8 insertions(+), 7 deletions(-)
diff --git a/packages/api/scripts/init.sql b/packages/api/scripts/init.sql
index f3bbbc437..71a8c80ec 100644
--- a/packages/api/scripts/init.sql
+++ b/packages/api/scripts/init.sql
@@ -548,6 +548,7 @@ CREATE TABLE connector_sets
ecom_shopify boolean NULL,
ecom_amazon boolean NULL,
ecom_squarespace boolean NULL,
+ ats_ashby boolean NULL,
CONSTRAINT PK_project_connector PRIMARY KEY ( id_connector_set )
);
diff --git a/packages/api/scripts/seed.sql b/packages/api/scripts/seed.sql
index 7b29520da..05c4d1bde 100644
--- a/packages/api/scripts/seed.sql
+++ b/packages/api/scripts/seed.sql
@@ -1,10 +1,10 @@
INSERT INTO users (id_user, identification_strategy, email, password_hash, first_name, last_name) VALUES
('0ce39030-2901-4c56-8db0-5e326182ec6b', 'b2c','local@panora.dev', '$2b$10$Y7Q8TWGyGuc5ecdIASbBsuXMo3q/Rs3/cnY.mLZP4tUgfGUOCUBlG', 'local', 'Panora');
-INSERT INTO connector_sets (id_connector_set, crm_hubspot, crm_zoho, crm_pipedrive, crm_attio, crm_zendesk, crm_close, tcg_zendesk, tcg_gorgias, tcg_front, tcg_jira, tcg_gitlab, fs_box, tcg_github, hris_deel, hris_sage) VALUES
- ('1709da40-17f7-4d3a-93a0-96dc5da6ddd7', TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE),
- ('852dfff8-ab63-4530-ae49-e4b2924407f8', TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE),
- ('aed0f856-f802-4a79-8640-66d441581a99', TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE);
+INSERT INTO connector_sets (id_connector_set, crm_hubspot, crm_zoho, crm_pipedrive, crm_attio, crm_zendesk, crm_close, tcg_zendesk, tcg_gorgias, tcg_front, tcg_jira, tcg_gitlab, fs_box, tcg_github, hris_deel, hris_sage, ats_ashby) VALUES
+ ('1709da40-17f7-4d3a-93a0-96dc5da6ddd7', TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE),
+ ('852dfff8-ab63-4530-ae49-e4b2924407f8', TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE),
+ ('aed0f856-f802-4a79-8640-66d441581a99', TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE);
INSERT INTO projects (id_project, name, sync_mode, id_user, id_connector_set) VALUES
('1e468c15-aa57-4448-aa2b-7fed640d1e3d', 'Project 1', 'pull', '0ce39030-2901-4c56-8db0-5e326182ec6b', '1709da40-17f7-4d3a-93a0-96dc5da6ddd7'),
diff --git a/packages/shared/src/connectors/metadata.ts b/packages/shared/src/connectors/metadata.ts
index a0540c9f3..ccb733c2f 100644
--- a/packages/shared/src/connectors/metadata.ts
+++ b/packages/shared/src/connectors/metadata.ts
@@ -1254,7 +1254,7 @@ export const CONNECTORS_METADATA: ProvidersConfig = {
},
logoPath: 'https://images.ctfassets.net/p03bi75xct27/2tVvkghDdMJxzkMca2QLnr/31b520c5e07db0103948af171fb54e99/ashby_logo_square.jpeg?q=80&fm=webp&w=2048',
description: 'Sync & Create contacts, deals, companies, notes, engagements, stages, tasks and users',
- active: false,
+ active: true,
primaryColor: '#4a3ead',
authStrategy: {
strategy: AuthStrategy.basic,
@@ -1269,7 +1269,7 @@ export const CONNECTORS_METADATA: ProvidersConfig = {
},
logoPath: 'https://play-lh.googleusercontent.com/c4BW9wr_QAiIeVBYHhP7rs06w99xJzxgLvmL5I1mkucC3_ATMyL1t7Doz0_LQ0X-qS0',
description: 'Sync & Create contacts, deals, companies, notes, engagements, stages, tasks and users',
- active: true,
+ active: false,
primaryColor: '#599D16',
authStrategy: {
strategy: AuthStrategy.basic,
@@ -2465,7 +2465,7 @@ export const CONNECTORS_METADATA: ProvidersConfig = {
},
logoPath: 'https://assets.wheelhouse.com/media/_solution_logo_04042023_58844144.png',
description: 'Sync & Create contacts, deals, companies, notes, engagements, stages, tasks and users',
- active: true,
+ active: false,
primaryColor: '#F8A22D',
authStrategy: {
strategy: AuthStrategy.api_key,
From 3d5a922d9a1f5f9d84dd6e452da958f4da6e7ebb Mon Sep 17 00:00:00 2001
From: nael
Date: Fri, 16 Aug 2024 05:17:50 +0200
Subject: [PATCH 09/49] :rotating_light: Lint fix
---
packages/shared/src/connectors/metadata.ts | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/packages/shared/src/connectors/metadata.ts b/packages/shared/src/connectors/metadata.ts
index ccb733c2f..3bc4e8fb3 100644
--- a/packages/shared/src/connectors/metadata.ts
+++ b/packages/shared/src/connectors/metadata.ts
@@ -1121,7 +1121,7 @@ export const CONNECTORS_METADATA: ProvidersConfig = {
primaryColor: '#ffcf40',
authStrategy: {
strategy: AuthStrategy.api_key,
- properties: ["api_key"]
+ properties: ['api_key']
}
},
'hubspot_marketing_hub': {
@@ -2469,7 +2469,7 @@ export const CONNECTORS_METADATA: ProvidersConfig = {
primaryColor: '#F8A22D',
authStrategy: {
strategy: AuthStrategy.api_key,
- properties: ["api_key"]
+ properties: ['api_key']
}
},
'payfit': {
@@ -2576,7 +2576,7 @@ export const CONNECTORS_METADATA: ProvidersConfig = {
primaryColor: '#00d639',
authStrategy: {
strategy: AuthStrategy.api_key,
- properties: ["api_key", "subdomain"]
+ properties: ['api_key', 'subdomain']
},
},
'sap_successfactors': {
From 131d644990d7fba1c7399892535d28154ab7619c Mon Sep 17 00:00:00 2001
From: nael
Date: Fri, 16 Aug 2024 19:10:26 +0200
Subject: [PATCH 10/49] :bug: Fix build
---
docker-compose.dev.yml | 3 +-
docker-compose.source.yml | 3 +
docker-compose.yml | 3 +
packages/api/prisma/schema.prisma | 820 +++++++++++----------
packages/api/scripts/init.sql | 1 -
packages/api/swagger/swagger-spec.yaml | 12 +
packages/shared/src/connectors/metadata.ts | 1 +
7 files changed, 433 insertions(+), 410 deletions(-)
diff --git a/docker-compose.dev.yml b/docker-compose.dev.yml
index 061735d37..3e19f9fd6 100644
--- a/docker-compose.dev.yml
+++ b/docker-compose.dev.yml
@@ -182,7 +182,8 @@ services:
SMTP_PORT: ${SMTP_PORT}
SMTP_USER: ${SMTP_USER}
SMTP_PASSWORD: ${SMTP_PASSWORD}
-
+ MICROSOFTDYNAMICSSALES_CRM_CLOUD_CLIENT_ID: ${MICROSOFTDYNAMICSSALES_CRM_CLOUD_CLIENT_ID}
+ MICROSOFTDYNAMICSSALES_CRM_CLOUD_CLIENT_SECRET: ${MICROSOFTDYNAMICSSALES_CRM_CLOUD_CLIENT_SECRET}
restart: unless-stopped
ports:
diff --git a/docker-compose.source.yml b/docker-compose.source.yml
index ba207adf0..b1a4f161c 100644
--- a/docker-compose.source.yml
+++ b/docker-compose.source.yml
@@ -182,6 +182,9 @@ services:
SMTP_PORT: ${SMTP_PORT}
SMTP_USER: ${SMTP_USER}
SMTP_PASSWORD: ${SMTP_PASSWORD}
+ MICROSOFTDYNAMICSSALES_CRM_CLOUD_CLIENT_ID: ${MICROSOFTDYNAMICSSALES_CRM_CLOUD_CLIENT_ID}
+ MICROSOFTDYNAMICSSALES_CRM_CLOUD_CLIENT_SECRET: ${MICROSOFTDYNAMICSSALES_CRM_CLOUD_CLIENT_SECRET}
+
restart: unless-stopped
ports:
- 3000:3000
diff --git a/docker-compose.yml b/docker-compose.yml
index b03be3f08..c33ef1247 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -176,6 +176,9 @@ services:
SMTP_PORT: ${SMTP_PORT}
SMTP_USER: ${SMTP_USER}
SMTP_PASSWORD: ${SMTP_PASSWORD}
+ MICROSOFTDYNAMICSSALES_CRM_CLOUD_CLIENT_ID: ${MICROSOFTDYNAMICSSALES_CRM_CLOUD_CLIENT_ID}
+ MICROSOFTDYNAMICSSALES_CRM_CLOUD_CLIENT_SECRET: ${MICROSOFTDYNAMICSSALES_CRM_CLOUD_CLIENT_SECRET}
+
restart: unless-stopped
ports:
- 3000:3000
diff --git a/packages/api/prisma/schema.prisma b/packages/api/prisma/schema.prisma
index 58997c432..60a66a984 100644
--- a/packages/api/prisma/schema.prisma
+++ b/packages/api/prisma/schema.prisma
@@ -7,6 +7,403 @@ datasource db {
url = env("DATABASE_URL")
}
+model crm_deals_stages {
+ id_crm_deals_stage String @id(map: "pk_crm_deal_stages") @db.Uuid
+ stage_name String?
+ created_at DateTime @db.Timestamptz(6)
+ modified_at DateTime @db.Timestamptz(6)
+ id_linked_user String? @db.Uuid
+ remote_id String?
+ remote_platform String?
+ id_connection String @db.Uuid
+ crm_deals crm_deals[]
+}
+
+model crm_users {
+ id_crm_user String @id(map: "pk_crm_users") @db.Uuid
+ name String?
+ email String?
+ created_at DateTime @db.Timestamptz(6)
+ modified_at DateTime @db.Timestamptz(6)
+ 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[]
+ crm_engagements crm_engagements[]
+ crm_tasks crm_tasks[]
+}
+
+model cs_attributes {
+ id_cs_attribute String @id(map: "pk_ct_attributes") @db.Uuid
+ attribute_slug String
+ data_type String
+ id_cs_entity String @db.Uuid
+}
+
+model cs_entities {
+ id_cs_entity String @id(map: "pk_ct_entities") @db.Uuid
+ id_connection_strategy String @db.Uuid
+}
+
+model cs_values {
+ id_cs_value String @id(map: "pk_ct_values") @db.Uuid
+ value String
+ id_cs_attribute String @db.Uuid
+}
+
+model ecom_customers {
+ id_ecom_customer String @id(map: "pk_ecom_customers") @db.Uuid
+ remote_id String?
+ email String?
+ first_name String?
+ last_name String?
+ phone_number String?
+ modified_at DateTime @db.Timestamptz(6)
+ created_at DateTime @db.Timestamptz(6)
+ id_connection String @db.Uuid
+ remote_deleted Boolean
+ ecom_addresses ecom_addresses[]
+ ecom_orders ecom_orders[]
+}
+
+model ecom_fulfilment_orders {
+ id_ecom_fulfilment_order String @id(map: "pk_ecom_fulfilment_order") @db.Uuid
+}
+
+model ecom_order_line_items {
+ id_ecom_order_line_item String @id(map: "pk_106") @db.Uuid
+}
+
+model ecom_products {
+ id_ecom_product String @id(map: "pk_ecom_products") @db.Uuid
+ remote_id String?
+ product_url String?
+ product_type String?
+ product_status String?
+ images_urls String[]
+ description String?
+ vendor String?
+ tags String[]
+ modified_at DateTime @db.Timestamptz(6)
+ created_at DateTime @db.Timestamptz(6)
+ id_connection String @db.Uuid
+ remote_deleted Boolean
+ ecom_product_variants ecom_product_variants[]
+}
+
+/// 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 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[]
+}
+
+model fs_drives {
+ id_fs_drive String @id(map: "pk_fs_drives") @db.Uuid
+ drive_url String?
+ name String?
+ remote_created_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
+}
+
+/// 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 String[]
+ remote_id String?
+ remote_was_deleted Boolean
+ 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 fs_permissions {
+ id_fs_permission String @id(map: "pk_fs_permissions") @db.Uuid
+ remote_id String?
+ user String? @db.Uuid
+ group String? @db.Uuid
+ type String?
+ roles 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 fs_shared_links {
+ id_fs_shared_link String @id(map: "pk_fs_shared_links") @db.Uuid
+ url String?
+ download_url String?
+ 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?
+}
+
+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.Timestamptz(6)
+ modified_at DateTime @db.Timestamptz(6)
+ id_connection String @db.Uuid
+}
+
+model hris_companies {
+ id_hris_company String @id(map: "pk_hris_companies") @db.Uuid
+ legal_name String?
+ display_name String?
+ eins String[]
+ remote_id String?
+ remote_created_at DateTime? @db.Timestamptz(6)
+ created_at DateTime @db.Timestamptz(6)
+ modified_at DateTime @db.Timestamptz(6)
+ remote_was_deleted Boolean
+ id_connection String @db.Uuid
+ hris_employees hris_employees[]
+}
+
+model hris_employer_benefits {
+ id_hris_employer_benefit String @id(map: "pk_hris_employer_benefits") @db.Uuid
+ id_connection String @db.Uuid
+ benefit_plan_type String?
+ name String?
+ description String?
+ deduction_code String?
+ remote_id String?
+ remote_created_at DateTime? @db.Timestamptz(6)
+ remote_was_deleted Boolean
+ created_at DateTime @db.Timestamptz(6)
+ modified_at DateTime @db.Timestamptz(6)
+ hris_benefits hris_benefits[]
+}
+
+/// 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 hris_groups {
+ id_hris_group String @id(map: "pk_hris_groups") @db.Uuid
+ parent_group String? @db.Uuid
+ name String?
+ type String?
+ remote_id String
+ remote_created_at DateTime @db.Timestamptz(6)
+ created_at DateTime @db.Timestamptz(6)
+ modified_at DateTime @db.Timestamptz(6)
+ remote_was_deleted Boolean
+ 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 hris_locations {
+ id_hris_location String @id(map: "pk_hris_locations") @db.Uuid
+ name String?
+ phone_number String?
+ street_1 String?
+ street_2 String?
+ city String?
+ state String?
+ id_hris_company String? @db.Uuid
+ id_hris_employee String? @db.Uuid
+ zip_code String?
+ country String?
+ location_type String?
+ remote_id String?
+ remote_created_at DateTime @db.Timestamptz(6)
+ created_at DateTime @db.Timestamptz(6)
+ modified_at DateTime @db.Timestamptz(6)
+ remote_was_deleted Boolean
+ id_connection String @db.Uuid
+}
+
+model hris_pay_groups {
+ id_hris_pay_group String @id(map: "pk_hris_pay_groups") @db.Uuid
+ pay_group_name String?
+ remote_id String?
+ remote_created_at DateTime? @db.Timestamptz(6)
+ created_at DateTime @db.Timestamptz(6)
+ modified_at DateTime @db.Timestamptz(6)
+ remote_was_deleted Boolean
+ id_connection String @db.Uuid
+ hris_employments hris_employments[]
+}
+
+model hris_payroll_runs {
+ id_hris_payroll_run String @id(map: "pk_hris_payroll_runs") @db.Uuid
+ run_state String?
+ run_type String?
+ start_date DateTime? @db.Timestamptz(6)
+ end_date DateTime? @db.Timestamptz(6)
+ check_date DateTime? @db.Timestamptz(6)
+ remote_id String?
+ remote_created_at DateTime? @db.Timestamptz(6)
+ created_at DateTime @db.Timestamptz(6)
+ modified_at DateTime @db.Timestamptz(6)
+ remote_was_deleted Boolean
+ id_connection String @db.Uuid
+ hris_employee_payroll_runs hris_employee_payroll_runs[]
+}
+
+/// 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 hris_time_off {
+ id_hris_time_off String @id(map: "pk_hris_time_off") @db.Uuid
+ employee String? @db.Uuid
+ approver String? @db.Uuid
+ status String?
+ employee_note String?
+ units String?
+ amount BigInt?
+ request_type String?
+ start_time DateTime? @db.Timestamptz(6)
+ end_time DateTime? @db.Timestamptz(6)
+ remote_id String?
+ remote_created_at DateTime? @db.Timestamptz(6)
+ created_at DateTime @db.Timestamptz(6)
+ modified_at DateTime @db.Timestamptz(6)
+ remote_was_deleted Boolean
+ 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 managed_webhooks {
+ id_managed_webhook String @id(map: "pk_managed_webhooks") @db.Uuid
+ active Boolean
+ id_connection String @db.Uuid
+ endpoint String @db.Uuid
+ api_version String?
+ active_events String[]
+ remote_signing_secret String?
+ modified_at DateTime @db.Timestamptz(6)
+ created_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 remote_data {
+ id_remote_data String @id(map: "pk_remote_data") @db.Uuid
+ ressource_owner_id String? @unique(map: "force_unique_ressourceownerid") @db.Uuid
+ format String?
+ data String?
+ created_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 tcg_accounts {
+ id_tcg_account String @id(map: "pk_tcg_account") @db.Uuid
+ remote_id String?
+ name String?
+ domains String[]
+ remote_platform String?
+ created_at DateTime @db.Timestamptz(6)
+ modified_at DateTime @db.Timestamptz(6)
+ id_linked_user String? @db.Uuid
+ id_connection String @db.Uuid
+ tcg_contacts tcg_contacts[]
+}
+
+model tcg_collections {
+ id_tcg_collection String @id(map: "pk_tcg_collections") @db.Uuid
+ name String?
+ description String?
+ remote_id String?
+ remote_platform String?
+ collection_type String?
+ parent_collection String? @db.Uuid
+ id_tcg_ticket String? @db.Uuid
+ created_at DateTime @db.Timestamptz(6)
+ modified_at DateTime @db.Timestamptz(6)
+ id_linked_user String @db.Uuid
+ id_connection String @db.Uuid
+}
+
+model tcg_teams {
+ id_tcg_team String @id(map: "pk_tcg_teams") @db.Uuid
+ remote_id String?
+ remote_platform String?
+ name String?
+ description String?
+ 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
+model tcg_users {
+ id_tcg_user String @id(map: "pk_tcg_users") @db.Uuid
+ name String?
+ email_address String?
+ remote_id String?
+ remote_platform String?
+ teams String[]
+ id_linked_user String? @db.Uuid
+ id_connection String @db.Uuid
+ created_at DateTime? @db.Timestamptz(6)
+ modified_at DateTime? @db.Timestamptz(6)
+ tcg_comments tcg_comments[]
+}
+
+/// 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 users {
+ id_user String @id(map: "pk_users") @db.Uuid
+ identification_strategy String
+ email String? @unique(map: "unique_email")
+ password_hash String?
+ first_name String
+ last_name String
+ id_stytch String? @unique(map: "force_stytch_id_unique")
+ created_at DateTime @default(now()) @db.Timestamptz(6)
+ modified_at DateTime @default(now()) @db.Timestamptz(6)
+ reset_token String?
+ reset_token_expires_at DateTime? @db.Timestamptz(6)
+ api_keys api_keys[]
+ projects projects[]
+}
+
+/// 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 webhook_endpoints {
+ id_webhook_endpoint String @id(map: "pk_webhook_endpoint") @db.Uuid
+ endpoint_description String?
+ url String
+ secret String
+ active Boolean
+ created_at DateTime @db.Timestamptz(6)
+ scope String[]
+ id_project String @db.Uuid
+ last_update DateTime? @db.Timestamptz(6)
+ webhook_delivery_attempts webhook_delivery_attempts[]
+}
+
+model webhooks_payloads {
+ id_webhooks_payload String @id(map: "pk_webhooks_payload") @db.Uuid
+ data Json @db.Json
+ webhook_delivery_attempts webhook_delivery_attempts[]
+}
+
+/// 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 webhooks_reponses {
+ id_webhooks_reponse String @id(map: "pk_webhooks_reponse") @db.Uuid
+ http_response_data String
+ http_status_code String
+ webhook_delivery_attempts webhook_delivery_attempts[]
+}
+
/// 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
@@ -938,10 +1335,14 @@ model connector_sets {
crm_close Boolean?
fs_box Boolean?
tcg_github Boolean?
+ hris_gusto Boolean?
+ hris_deel Boolean?
+ hris_sage Boolean?
ecom_woocommerce Boolean?
ecom_shopify Boolean?
ecom_amazon Boolean?
ecom_squarespace Boolean?
+ ats_ashby Boolean?
projects projects[]
}
@@ -1039,18 +1440,6 @@ model crm_deals {
@@index([id_crm_company], map: "fk_crm_deal_crmcompanyid")
}
-model crm_deals_stages {
- id_crm_deals_stage String @id(map: "pk_crm_deal_stages") @db.Uuid
- stage_name String?
- created_at DateTime @db.Timestamptz(6)
- modified_at DateTime @db.Timestamptz(6)
- id_linked_user String? @db.Uuid
- remote_id String?
- remote_platform String?
- id_connection String @db.Uuid
- crm_deals crm_deals[]
-}
-
/// 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_email_addresses {
id_crm_email String @id(map: "pk_crm_contact_email_addresses") @db.Uuid
@@ -1160,41 +1549,6 @@ model crm_tasks {
@@index([id_crm_deal], map: "fk_crmtask_dealid")
}
-model crm_users {
- id_crm_user String @id(map: "pk_crm_users") @db.Uuid
- name String?
- email String?
- created_at DateTime @db.Timestamptz(6)
- modified_at DateTime @db.Timestamptz(6)
- 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[]
- crm_engagements crm_engagements[]
- crm_tasks crm_tasks[]
-}
-
-model cs_attributes {
- id_cs_attribute String @id(map: "pk_ct_attributes") @db.Uuid
- attribute_slug String
- data_type String
- id_cs_entity String @db.Uuid
-}
-
-model cs_entities {
- id_cs_entity String @id(map: "pk_ct_entities") @db.Uuid
- id_connection_strategy String @db.Uuid
-}
-
-model cs_values {
- id_cs_value String @id(map: "pk_ct_values") @db.Uuid
- value String
- id_cs_attribute 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 ecom_addresses {
id_ecom_address String @id(map: "pk_ecom_customer_addresses") @db.Uuid
@@ -1217,25 +1571,6 @@ model ecom_addresses {
@@index([id_ecom_order], map: "fk_index_fk_ecom_order_address")
}
-model ecom_customers {
- id_ecom_customer String @id(map: "pk_ecom_customers") @db.Uuid
- remote_id String?
- email String?
- first_name String?
- last_name String?
- phone_number String?
- modified_at DateTime @db.Timestamptz(6)
- created_at DateTime @db.Timestamptz(6)
- id_connection String @db.Uuid
- remote_deleted Boolean
- ecom_addresses ecom_addresses[]
- ecom_orders ecom_orders[]
-}
-
-model ecom_fulfilment_orders {
- id_ecom_fulfilment_order String @id(map: "pk_ecom_fulfilment_order") @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 ecom_fulfilments {
id_ecom_fulfilment String @id(map: "pk_ecom_fulfilments") @db.Uuid
@@ -1254,10 +1589,6 @@ model ecom_fulfilments {
@@index([id_ecom_order], map: "fk_index_ecom_order_fulfilment")
}
-model ecom_order_line_items {
- id_ecom_order_line_item String @id(map: "pk_106") @db.Uuid
-}
-
model ecom_orders {
id_ecom_order String @id(map: "pk_ecom_orders") @db.Uuid
order_status String?
@@ -1302,33 +1633,6 @@ model ecom_product_variants {
@@index([id_ecom_product], map: "fk_index_ecom_products_variants")
}
-model ecom_products {
- id_ecom_product String @id(map: "pk_ecom_products") @db.Uuid
- remote_id String?
- product_url String?
- product_type String?
- product_status String?
- images_urls String[]
- description String?
- vendor String?
- tags String[]
- modified_at DateTime @db.Timestamptz(6)
- created_at DateTime @db.Timestamptz(6)
- id_connection String @db.Uuid
- remote_deleted Boolean
- ecom_product_variants ecom_product_variants[]
-}
-
-/// 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 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[]
-}
-
/// 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 events {
id_event String @id(map: "pk_jobs") @db.Uuid
@@ -1349,17 +1653,6 @@ model events {
@@index([id_linked_user], map: "fk_linkeduserid_projectid")
}
-model fs_drives {
- id_fs_drive String @id(map: "pk_fs_drives") @db.Uuid
- drive_url String?
- name String?
- remote_created_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
-}
-
model fs_files {
id_fs_file String @id(map: "pk_fs_files") @db.Uuid
name String?
@@ -1381,71 +1674,18 @@ model fs_folders {
id_fs_folder String @id(map: "pk_fs_folders") @db.Uuid
folder_url String?
size BigInt?
- name String?
- description String?
- parent_folder String? @db.Uuid
- remote_id String?
- created_at DateTime @db.Timestamptz(6)
- modified_at DateTime @db.Timestamptz(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")
- @@index([id_fs_permission], map: "fk_fs_folder_permissionid")
-}
-
-/// 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 String[]
- remote_id String?
- remote_was_deleted Boolean
- 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 fs_permissions {
- id_fs_permission String @id(map: "pk_fs_permissions") @db.Uuid
- remote_id String?
- user String? @db.Uuid
- group String? @db.Uuid
- type String?
- roles 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 fs_shared_links {
- id_fs_shared_link String @id(map: "pk_fs_shared_links") @db.Uuid
- url String?
- download_url String?
- 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?
-}
+ name String?
+ description String?
+ parent_folder String? @db.Uuid
+ remote_id String?
+ created_at DateTime @db.Timestamptz(6)
+ modified_at DateTime @db.Timestamptz(6)
+ id_fs_drive String? @db.Uuid
+ id_connection String @db.Uuid
+ id_fs_permission 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.Timestamptz(6)
- modified_at DateTime @db.Timestamptz(6)
- id_connection String @db.Uuid
+ @@index([id_fs_drive], map: "fk_fs_folder_driveid")
+ @@index([id_fs_permission], map: "fk_fs_folder_permissionid")
}
model hris_bank_infos {
@@ -1488,20 +1728,6 @@ model hris_benefits {
@@index([id_hris_employee], map: "fkx_hris_benefits_employeeid")
}
-model hris_companies {
- id_hris_company String @id(map: "pk_hris_companies") @db.Uuid
- legal_name String?
- display_name String?
- eins String[]
- remote_id String?
- remote_created_at DateTime? @db.Timestamptz(6)
- created_at DateTime @db.Timestamptz(6)
- modified_at DateTime @db.Timestamptz(6)
- remote_was_deleted Boolean
- id_connection String @db.Uuid
- hris_employees hris_employees[]
-}
-
/// 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 hris_dependents {
id_hris_dependents String @id(map: "pk_hris_dependents") @db.Uuid
@@ -1636,21 +1862,6 @@ model hris_employees {
@@index([id_hris_company], map: "fkx_employee_companyid")
}
-model hris_employer_benefits {
- id_hris_employer_benefit String @id(map: "pk_hris_employer_benefits") @db.Uuid
- id_connection String @db.Uuid
- benefit_plan_type String?
- name String?
- description String?
- deduction_code String?
- remote_id String?
- remote_created_at DateTime? @db.Timestamptz(6)
- remote_was_deleted Boolean
- created_at DateTime @db.Timestamptz(6)
- modified_at DateTime @db.Timestamptz(6)
- hris_benefits hris_benefits[]
-}
-
/// 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 hris_employments {
id_hris_employment String @id(map: "pk_hris_employments") @db.Uuid
@@ -1677,90 +1888,6 @@ model hris_employments {
@@index([id_hris_pay_group], map: "fkx_employments_pay_group_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 hris_groups {
- id_hris_group String @id(map: "pk_hris_groups") @db.Uuid
- parent_group String? @db.Uuid
- name String?
- type String?
- remote_id String
- remote_created_at DateTime @db.Timestamptz(6)
- created_at DateTime @db.Timestamptz(6)
- modified_at DateTime @db.Timestamptz(6)
- remote_was_deleted Boolean
- 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 hris_locations {
- id_hris_location String @id(map: "pk_hris_locations") @db.Uuid
- name String?
- phone_number String?
- street_1 String?
- street_2 String?
- city String?
- state String?
- id_hris_company String? @db.Uuid
- id_hris_employee String? @db.Uuid
- zip_code String?
- country String?
- location_type String?
- remote_id String?
- remote_created_at DateTime @db.Timestamptz(6)
- created_at DateTime @db.Timestamptz(6)
- modified_at DateTime @db.Timestamptz(6)
- remote_was_deleted Boolean
- id_connection String @db.Uuid
-}
-
-model hris_pay_groups {
- id_hris_pay_group String @id(map: "pk_hris_pay_groups") @db.Uuid
- pay_group_name String?
- remote_id String?
- remote_created_at DateTime? @db.Timestamptz(6)
- created_at DateTime @db.Timestamptz(6)
- modified_at DateTime @db.Timestamptz(6)
- remote_was_deleted Boolean
- id_connection String @db.Uuid
- hris_employments hris_employments[]
-}
-
-model hris_payroll_runs {
- id_hris_payroll_run String @id(map: "pk_hris_payroll_runs") @db.Uuid
- run_state String?
- run_type String?
- start_date DateTime? @db.Timestamptz(6)
- end_date DateTime? @db.Timestamptz(6)
- check_date DateTime? @db.Timestamptz(6)
- remote_id String?
- remote_created_at DateTime? @db.Timestamptz(6)
- created_at DateTime @db.Timestamptz(6)
- modified_at DateTime @db.Timestamptz(6)
- remote_was_deleted Boolean
- id_connection String @db.Uuid
- hris_employee_payroll_runs hris_employee_payroll_runs[]
-}
-
-/// 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 hris_time_off {
- id_hris_time_off String @id(map: "pk_hris_time_off") @db.Uuid
- employee String? @db.Uuid
- approver String? @db.Uuid
- status String?
- employee_note String?
- units String?
- amount BigInt?
- request_type String?
- start_time DateTime? @db.Timestamptz(6)
- end_time DateTime? @db.Timestamptz(6)
- remote_id String?
- remote_created_at DateTime? @db.Timestamptz(6)
- created_at DateTime @db.Timestamptz(6)
- modified_at DateTime @db.Timestamptz(6)
- remote_was_deleted Boolean
- id_connection String @db.Uuid
-}
-
model hris_time_off_balances {
id_hris_time_off_balance String @id(map: "pk_hris_time_off_balances") @db.Uuid
balance BigInt?
@@ -1833,19 +1960,6 @@ model linked_users {
@@index([id_project], map: "fk_proectid_linked_users")
}
-/// 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 managed_webhooks {
- id_managed_webhook String @id(map: "pk_managed_webhooks") @db.Uuid
- active Boolean
- id_connection String @db.Uuid
- endpoint String @db.Uuid
- api_version String?
- active_events String[]
- remote_signing_secret String?
- modified_at DateTime @db.Timestamptz(6)
- created_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 projects {
id_project String @id(map: "pk_projects") @db.Uuid
@@ -1864,29 +1978,6 @@ model projects {
@@index([id_connector_set], map: "fk_connectors_sets")
}
-/// 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 remote_data {
- id_remote_data String @id(map: "pk_remote_data") @db.Uuid
- ressource_owner_id String? @unique(map: "force_unique_ressourceownerid") @db.Uuid
- format String?
- data String?
- created_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 tcg_accounts {
- id_tcg_account String @id(map: "pk_tcg_account") @db.Uuid
- remote_id String?
- name String?
- domains String[]
- remote_platform String?
- created_at DateTime @db.Timestamptz(6)
- modified_at DateTime @db.Timestamptz(6)
- id_linked_user String? @db.Uuid
- id_connection String @db.Uuid
- tcg_contacts tcg_contacts[]
-}
-
/// 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 tcg_attachments {
id_tcg_attachment String @id(map: "pk_tcg_attachments") @db.Uuid
@@ -1908,21 +1999,6 @@ model tcg_attachments {
@@index([id_tcg_ticket], map: "fk_tcg_attachment_tcg_ticketid")
}
-model tcg_collections {
- id_tcg_collection String @id(map: "pk_tcg_collections") @db.Uuid
- name String?
- description String?
- remote_id String?
- remote_platform String?
- collection_type String?
- parent_collection String? @db.Uuid
- id_tcg_ticket String? @db.Uuid
- created_at DateTime @db.Timestamptz(6)
- modified_at DateTime @db.Timestamptz(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
model tcg_comments {
id_tcg_comment String @id(map: "pk_tcg_comments") @db.Uuid
@@ -1984,18 +2060,6 @@ model tcg_tags {
@@index([id_tcg_ticket], map: "fk_tcg_tag_tcg_ticketid")
}
-model tcg_teams {
- id_tcg_team String @id(map: "pk_tcg_teams") @db.Uuid
- remote_id String?
- remote_platform String?
- name String?
- description String?
- 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
model tcg_tickets {
id_tcg_ticket String @id(map: "pk_tcg_tickets") @db.Uuid
@@ -2025,38 +2089,6 @@ model tcg_tickets {
@@index([id_tcg_user], map: "fk_tcg_ticket_tcg_user")
}
-/// 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 tcg_users {
- id_tcg_user String @id(map: "pk_tcg_users") @db.Uuid
- name String?
- email_address String?
- remote_id String?
- remote_platform String?
- teams String[]
- id_linked_user String? @db.Uuid
- id_connection String @db.Uuid
- created_at DateTime? @db.Timestamptz(6)
- modified_at DateTime? @db.Timestamptz(6)
- tcg_comments tcg_comments[]
-}
-
-/// 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 users {
- id_user String @id(map: "pk_users") @db.Uuid
- identification_strategy String
- email String? @unique(map: "unique_email")
- password_hash String?
- first_name String
- last_name String
- id_stytch String? @unique(map: "force_stytch_id_unique")
- created_at DateTime @default(now()) @db.Timestamptz(6)
- modified_at DateTime @default(now()) @db.Timestamptz(6)
- reset_token String?
- reset_token_expires_at DateTime? @db.Timestamptz(6)
- api_keys api_keys[]
- projects projects[]
-}
-
/// 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 value {
id_value String @id(map: "pk_value") @db.Uuid
@@ -2093,31 +2125,3 @@ model webhook_delivery_attempts {
@@index([id_event], map: "fk_webhook_delivery_attempt_eventid")
@@index([id_webhooks_reponse], map: "fk_webhook_delivery_attempt_webhook_responseid")
}
-
-/// 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 webhook_endpoints {
- id_webhook_endpoint String @id(map: "pk_webhook_endpoint") @db.Uuid
- endpoint_description String?
- url String
- secret String
- active Boolean
- created_at DateTime @db.Timestamptz(6)
- scope String[]
- id_project String @db.Uuid
- last_update DateTime? @db.Timestamptz(6)
- webhook_delivery_attempts webhook_delivery_attempts[]
-}
-
-model webhooks_payloads {
- id_webhooks_payload String @id(map: "pk_webhooks_payload") @db.Uuid
- data Json @db.Json
- webhook_delivery_attempts webhook_delivery_attempts[]
-}
-
-/// 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 webhooks_reponses {
- id_webhooks_reponse String @id(map: "pk_webhooks_reponse") @db.Uuid
- http_response_data String
- http_status_code String
- webhook_delivery_attempts webhook_delivery_attempts[]
-}
diff --git a/packages/api/scripts/init.sql b/packages/api/scripts/init.sql
index 4be270a83..71a8c80ec 100644
--- a/packages/api/scripts/init.sql
+++ b/packages/api/scripts/init.sql
@@ -549,7 +549,6 @@ CREATE TABLE connector_sets
ecom_amazon boolean NULL,
ecom_squarespace boolean NULL,
ats_ashby boolean NULL,
- hris_gusto boolean NULL,
CONSTRAINT PK_project_connector PRIMARY KEY ( id_connector_set )
);
diff --git a/packages/api/swagger/swagger-spec.yaml b/packages/api/swagger/swagger-spec.yaml
index 166080fe7..17b806d81 100644
--- a/packages/api/swagger/swagger-spec.yaml
+++ b/packages/api/swagger/swagger-spec.yaml
@@ -107,6 +107,8 @@ paths:
schema:
type: string
responses:
+ '200':
+ description: ''
'201':
description: ''
content:
@@ -127,6 +129,8 @@ paths:
schema:
type: string
responses:
+ '200':
+ description: ''
'201':
description: ''
content:
@@ -157,6 +161,8 @@ paths:
type: object
additionalProperties: true
description: Dynamic event payload
+ '201':
+ description: ''
tags: *ref_0
x-speakeasy-group: webhooks
/ticketing/tickets:
@@ -2215,6 +2221,12 @@ paths:
application/json:
schema:
type: object
+ '201':
+ description: ''
+ content:
+ application/json:
+ schema:
+ type: object
tags: &ref_21
- passthrough
x-speakeasy-group: passthrough
diff --git a/packages/shared/src/connectors/metadata.ts b/packages/shared/src/connectors/metadata.ts
index 3bc4e8fb3..9ffa15b32 100644
--- a/packages/shared/src/connectors/metadata.ts
+++ b/packages/shared/src/connectors/metadata.ts
@@ -215,6 +215,7 @@ export const CONNECTORS_METADATA: ProvidersConfig = {
logoPath: 'https://play-lh.googleusercontent.com/MC_Aoa7rlMjGtcgAdiLJGeIm3-kpVw7APQmQUrUZtXuoZokiqVOJqR-bTu7idJBD8g',
description: 'Sync & Create contacts, deals, companies, notes, engagements, stages, tasks and users',
active: false,
+ primaryColor: '#516EE2',
options: {
end_user_domain: true
},
From 2a8d95f2abdbfadc235052771429b8f3444bc161 Mon Sep 17 00:00:00 2001
From: speakeasybot
Date: Sat, 17 Aug 2024 00:05:09 +0000
Subject: [PATCH 11/49] ci: regenerated with Speakeasy CLI v1.374.2
---
.speakeasy/workflow.lock | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/.speakeasy/workflow.lock b/.speakeasy/workflow.lock
index c8370252e..665bf259f 100644
--- a/.speakeasy/workflow.lock
+++ b/.speakeasy/workflow.lock
@@ -1,8 +1,8 @@
-speakeasyVersion: 1.372.0
+speakeasyVersion: 1.374.2
sources:
merge-code-samples-into-spec:
sourceNamespace: merge-code-samples-into-spec
- sourceRevisionDigest: sha256:62bd8d64f8278dcb7b23d28bffcffbb549e57b5b9dc09bae93ac4c1112dbd09a
+ sourceRevisionDigest: sha256:1bcf3a8cca852c571571fad60c90aad27624f86e4f2fb58e3777f0c3a6ec712a
sourceBlobDigest: sha256:ebdf0ba69a79a32d558c774cfe0f0c32d742319ed3c3d3d887bf14ac67f417d8
tags:
- latest
From f9031753fcf1ab267d35e8cf530efa1d77bacc9d Mon Sep 17 00:00:00 2001
From: nael
Date: Sun, 18 Aug 2024 01:31:51 +0200
Subject: [PATCH 12/49] :bug: Fix shared package build
---
apps/magic-link/src/App.css | 1 +
docker-compose.dev.yml | 37 ++++-----
docker-compose.source.yml | 6 +-
docker-compose.yml | 6 +-
.../encryption/encryption.service.ts | 17 +++++
.../api/src/@core/auth/auth.controller.ts | 31 +++++---
.../services/snyk/snyk.service.ts | 76 +++++++++++++++----
packages/shared/package.json | 6 +-
packages/shared/src/authUrl.ts | 38 +++++-----
packages/shared/src/connectors/metadata.ts | 71 ++++++++---------
packages/shared/tsconfig.json | 2 +-
11 files changed, 188 insertions(+), 103 deletions(-)
diff --git a/apps/magic-link/src/App.css b/apps/magic-link/src/App.css
index b9d355df2..56229e6af 100644
--- a/apps/magic-link/src/App.css
+++ b/apps/magic-link/src/App.css
@@ -3,6 +3,7 @@
margin: 0 auto;
padding: 2rem;
text-align: center;
+ background: #09090B;
}
.logo {
diff --git a/docker-compose.dev.yml b/docker-compose.dev.yml
index 3e19f9fd6..e82cf3769 100644
--- a/docker-compose.dev.yml
+++ b/docker-compose.dev.yml
@@ -184,7 +184,10 @@ services:
SMTP_PASSWORD: ${SMTP_PASSWORD}
MICROSOFTDYNAMICSSALES_CRM_CLOUD_CLIENT_ID: ${MICROSOFTDYNAMICSSALES_CRM_CLOUD_CLIENT_ID}
MICROSOFTDYNAMICSSALES_CRM_CLOUD_CLIENT_SECRET: ${MICROSOFTDYNAMICSSALES_CRM_CLOUD_CLIENT_SECRET}
-
+ SNYK_CYBERSECURITY_CLOUD_CLIENT_ID: ${SNYK_CYBERSECURITY_CLOUD_CLIENT_ID}
+ SNYK_CYBERSECURITY_CLOUD_CLIENT_SECRET: ${SNYK_CYBERSECURITY_CLOUD_CLIENT_SECRET}
+ CROWDSTRIKE_CYBERSECURITY_CLOUD_CLIENT_ID: ${CROWDSTRIKE_CYBERSECURITY_CLOUD_CLIENT_ID}
+ CROWDSTRIKE_CYBERSECURITY_CLOUD_CLIENT_SECRET: ${CROWDSTRIKE_CYBERSECURITY_CLOUD_CLIENT_SECRET}
restart: unless-stopped
ports:
- 3000:3000
@@ -277,22 +280,22 @@ services:
# volumes:
# - pgadmin-data:/var/lib/pgadmin
- # ngrok:
- # image: ngrok/ngrok:latest
- # restart: always
- # command:
- # - "start"
- # - "--all"
- # - "--config"
- # - "/etc/ngrok.yml"
- # volumes:
- # - ./ngrok.yml:/etc/ngrok.yml
- # ports:
- # - 4040:4040
- # depends_on:
- # api:
- # condition: service_healthy
- # network_mode: "host"
+ ngrok:
+ image: ngrok/ngrok:latest
+ restart: always
+ command:
+ - "start"
+ - "--all"
+ - "--config"
+ - "/etc/ngrok.yml"
+ volumes:
+ - ./ngrok.yml:/etc/ngrok.yml
+ ports:
+ - 4040:4040
+ depends_on:
+ api:
+ condition: service_healthy
+ network_mode: "host"
docs:
build:
diff --git a/docker-compose.source.yml b/docker-compose.source.yml
index b1a4f161c..d81637773 100644
--- a/docker-compose.source.yml
+++ b/docker-compose.source.yml
@@ -184,7 +184,11 @@ services:
SMTP_PASSWORD: ${SMTP_PASSWORD}
MICROSOFTDYNAMICSSALES_CRM_CLOUD_CLIENT_ID: ${MICROSOFTDYNAMICSSALES_CRM_CLOUD_CLIENT_ID}
MICROSOFTDYNAMICSSALES_CRM_CLOUD_CLIENT_SECRET: ${MICROSOFTDYNAMICSSALES_CRM_CLOUD_CLIENT_SECRET}
-
+ SNYK_CYBERSECURITY_CLOUD_CLIENT_ID: ${SNYK_CYBERSECURITY_CLOUD_CLIENT_ID}
+ SNYK_CYBERSECURITY_CLOUD_CLIENT_SECRET: ${SNYK_CYBERSECURITY_CLOUD_CLIENT_SECRET}
+ CROWDSTRIKE_CYBERSECURITY_CLOUD_CLIENT_ID: ${CROWDSTRIKE_CYBERSECURITY_CLOUD_CLIENT_ID}
+ CROWDSTRIKE_CYBERSECURITY_CLOUD_CLIENT_SECRET: ${CROWDSTRIKE_CYBERSECURITY_CLOUD_CLIENT_SECRET}
+
restart: unless-stopped
ports:
- 3000:3000
diff --git a/docker-compose.yml b/docker-compose.yml
index c33ef1247..c8603707e 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -178,7 +178,11 @@ services:
SMTP_PASSWORD: ${SMTP_PASSWORD}
MICROSOFTDYNAMICSSALES_CRM_CLOUD_CLIENT_ID: ${MICROSOFTDYNAMICSSALES_CRM_CLOUD_CLIENT_ID}
MICROSOFTDYNAMICSSALES_CRM_CLOUD_CLIENT_SECRET: ${MICROSOFTDYNAMICSSALES_CRM_CLOUD_CLIENT_SECRET}
-
+ SNYK_CYBERSECURITY_CLOUD_CLIENT_ID: ${SNYK_CYBERSECURITY_CLOUD_CLIENT_ID}
+ SNYK_CYBERSECURITY_CLOUD_CLIENT_SECRET: ${SNYK_CYBERSECURITY_CLOUD_CLIENT_SECRET}
+ CROWDSTRIKE_CYBERSECURITY_CLOUD_CLIENT_ID: ${CROWDSTRIKE_CYBERSECURITY_CLOUD_CLIENT_ID}
+ CROWDSTRIKE_CYBERSECURITY_CLOUD_CLIENT_SECRET: ${CROWDSTRIKE_CYBERSECURITY_CLOUD_CLIENT_SECRET}
+
restart: unless-stopped
ports:
- 3000:3000
diff --git a/packages/api/src/@core/@core-services/encryption/encryption.service.ts b/packages/api/src/@core/@core-services/encryption/encryption.service.ts
index 25be858af..bdf660a9d 100644
--- a/packages/api/src/@core/@core-services/encryption/encryption.service.ts
+++ b/packages/api/src/@core/@core-services/encryption/encryption.service.ts
@@ -46,4 +46,21 @@ export class EncryptionService {
throw error;
}
}
+
+ generateCodes(): { codeVerifier: string; codeChallenge: string } {
+ const base64URLEncode = (str: Buffer): string => {
+ return str
+ .toString('base64')
+ .replace(/\+/g, '-')
+ .replace(/\//g, '_')
+ .replace(/=/g, '');
+ };
+
+ const verifier = base64URLEncode(Buffer.from(crypto.randomBytes(32)));
+ const challenge = base64URLEncode(
+ crypto.createHash('sha256').update(Buffer.from(verifier)).digest(),
+ );
+
+ return { codeVerifier: verifier, codeChallenge: challenge };
+ }
}
diff --git a/packages/api/src/@core/auth/auth.controller.ts b/packages/api/src/@core/auth/auth.controller.ts
index 860ec66ab..5a9895cf9 100644
--- a/packages/api/src/@core/auth/auth.controller.ts
+++ b/packages/api/src/@core/auth/auth.controller.ts
@@ -1,17 +1,14 @@
+import { LoggerService } from '@@core/@core-services/logger/logger.service';
import {
- Controller,
- Post,
Body,
- Get,
- UseGuards,
- Request,
+ Controller,
Delete,
+ Get,
Param,
+ Post,
+ Request,
+ UseGuards,
} from '@nestjs/common';
-import { CreateUserDto } from './dto/create-user.dto';
-import { AuthService } from './auth.service';
-import { JwtAuthGuard } from './guards/jwt-auth.guard';
-import { LoggerService } from '@@core/@core-services/logger/logger.service';
import {
ApiBody,
ApiExcludeEndpoint,
@@ -20,23 +17,35 @@ import {
ApiResponse,
ApiTags,
} from '@nestjs/swagger';
+import { AuthService } from './auth.service';
import { ApiKeyDto } from './dto/api-key.dto';
+import { CreateUserDto } from './dto/create-user.dto';
import { LoginDto } from './dto/login.dto';
import { RefreshDto } from './dto/refresh.dto';
-import { ResetPasswordDto } from './dto/reset-password.dto';
import { RequestPasswordResetDto } from './dto/request-password-reset.dto';
-import { ApiKeyAuthGuard } from './guards/api-key.guard';
+import { ResetPasswordDto } from './dto/reset-password.dto';
+import { JwtAuthGuard } from './guards/jwt-auth.guard';
+import { EncryptionService } from '@@core/@core-services/encryption/encryption.service';
@ApiTags('auth')
@Controller('auth')
export class AuthController {
constructor(
private readonly authService: AuthService,
+ private readonly encryptionService: EncryptionService,
private logger: LoggerService,
) {
this.logger.setContext(AuthController.name);
}
+ @ApiOperation({ operationId: 'generateCodes', summary: 'generateCodes' })
+ @ApiResponse({ status: 200 })
+ @Get('s256Codes')
+ @ApiExcludeEndpoint()
+ async generateCodes() {
+ return this.encryptionService.generateCodes();
+ }
+
@ApiOperation({ operationId: 'signUp', summary: 'Register' })
@ApiBody({ type: CreateUserDto })
@ApiResponse({ status: 201 })
diff --git a/packages/api/src/@core/connections/cybersecurity/services/snyk/snyk.service.ts b/packages/api/src/@core/connections/cybersecurity/services/snyk/snyk.service.ts
index ff77211ce..f5cb498c0 100644
--- a/packages/api/src/@core/connections/cybersecurity/services/snyk/snyk.service.ts
+++ b/packages/api/src/@core/connections/cybersecurity/services/snyk/snyk.service.ts
@@ -25,8 +25,10 @@ import axios from 'axios';
export interface SnykOAuthResponse {
access_token: string;
+ refresh_token: string;
token_type: string;
scope: string;
+ expires_in: string;
}
@Injectable()
@@ -69,7 +71,7 @@ export class SnykConnectionService extends AbstractBaseConnectionService {
config.headers = {
...config.headers,
...headers,
- Authorization: `Bearer ${access_token}`,
+ Authorization: `token ${access_token}`,
};
return await this.retryService.makeRequest(
@@ -89,7 +91,7 @@ export class SnykConnectionService extends AbstractBaseConnectionService {
async handleCallback(opts: OAuthCallbackParams) {
try {
- const { linkedUserId, projectId, code } = opts;
+ const { linkedUserId, projectId, code, code_verifier } = opts;
const isNotUnique = await this.prisma.connections.findFirst({
where: {
id_linked_user: linkedUserId,
@@ -115,9 +117,10 @@ export class SnykConnectionService extends AbstractBaseConnectionService {
client_secret: CREDENTIALS.CLIENT_SECRET,
code: code,
grant_type: 'authorization_code',
+ code_verifier: code_verifier,
});
const res = await axios.post(
- 'https://api.snyk.com/oauth/access_token',
+ 'https://api.snyk.io/oauth2/token',
formData.toString(),
{
headers: {
@@ -126,19 +129,12 @@ export class SnykConnectionService extends AbstractBaseConnectionService {
},
);
const data: SnykOAuthResponse = res.data;
+ console.log('result is ' + JSON.stringify(data));
// save tokens for this customer inside our db
let db_res;
const connection_token = uuidv4();
const BASE_API_URL = CONNECTORS_METADATA['cybersecurity']['snyk'].urls
.apiUrl as string;
- // get the site id for the token
- const site = await axios.get('https://api.snyk.com/v2/sites', {
- headers: {
- 'Content-Type': 'application/x-www-form-urlencoded;charset=utf-8',
- Authorization: `Bearer ${data.access_token}`,
- },
- });
- const site_id = site.data.sites[0].id;
if (isNotUnique) {
// Update existing connection
db_res = await this.prisma.connections.update({
@@ -147,6 +143,10 @@ export class SnykConnectionService extends AbstractBaseConnectionService {
},
data: {
access_token: this.cryptoService.encrypt(data.access_token),
+ refresh_token: this.cryptoService.encrypt(data.refresh_token),
+ expiration_timestamp: new Date(
+ new Date().getTime() + Number(data.expires_in) * 1000,
+ ),
status: 'valid',
created_at: new Date(),
},
@@ -160,8 +160,12 @@ export class SnykConnectionService extends AbstractBaseConnectionService {
provider_slug: 'snyk',
vertical: 'cybersecurity',
token_type: 'oauth2',
- account_url: `${BASE_API_URL}/sites/${site_id}`,
+ account_url: BASE_API_URL,
access_token: this.cryptoService.encrypt(data.access_token),
+ refresh_token: this.cryptoService.encrypt(data.refresh_token),
+ expiration_timestamp: new Date(
+ new Date().getTime() + Number(data.expires_in) * 1000,
+ ),
status: 'valid',
created_at: new Date(),
projects: {
@@ -186,6 +190,52 @@ export class SnykConnectionService extends AbstractBaseConnectionService {
}
async handleTokenRefresh(opts: RefreshParams) {
- return;
+ try {
+ const { connectionId, refreshToken, projectId } = opts;
+ const REDIRECT_URI = `${
+ this.env.getDistributionMode() == 'selfhost'
+ ? this.env.getTunnelIngress()
+ : this.env.getPanoraBaseUrl()
+ }/connections/oauth/callback`;
+
+ const CREDENTIALS = (await this.cService.getCredentials(
+ projectId,
+ this.type,
+ )) as OAuth2AuthData;
+
+ const formData = new URLSearchParams({
+ grant_type: 'refresh_token',
+ client_id: CREDENTIALS.CLIENT_ID,
+ client_secret: CREDENTIALS.CLIENT_SECRET,
+ refresh_token: this.cryptoService.decrypt(refreshToken),
+ redirect_uri: REDIRECT_URI,
+ });
+
+ const res = await axios.post(
+ `https://app.deel.com/oauth2/tokens`,
+ formData.toString(),
+ {
+ headers: {
+ 'Content-Type': 'application/x-www-form-urlencoded;charset=utf-8',
+ },
+ },
+ );
+ const data: SnykOAuthResponse = res.data;
+ await this.prisma.connections.update({
+ where: {
+ id_connection: connectionId,
+ },
+ data: {
+ access_token: this.cryptoService.encrypt(data.access_token),
+ refresh_token: this.cryptoService.encrypt(data.refresh_token),
+ expiration_timestamp: new Date(
+ new Date().getTime() + Number(data.expires_in) * 1000,
+ ),
+ },
+ });
+ this.logger.log('OAuth credentials updated : deel ');
+ } catch (error) {
+ throw error;
+ }
}
}
diff --git a/packages/shared/package.json b/packages/shared/package.json
index 9fdbd22e2..fc2065363 100644
--- a/packages/shared/package.json
+++ b/packages/shared/package.json
@@ -45,10 +45,10 @@
"supertest": "^6.3.3",
"ts-jest": "^29.1.0",
"ts-node": "^10.9.1",
- "tsconfig-paths": "^4.2.0",
- "typescript": "^5.1.3",
"tsc-watch": "2.2.1",
- "tslint": "5.16.0"
+ "tsconfig-paths": "^4.2.0",
+ "tslint": "5.16.0",
+ "typescript": "^5.1.3"
},
"jest": {
"moduleFileExtensions": [
diff --git a/packages/shared/src/authUrl.ts b/packages/shared/src/authUrl.ts
index 6b7d66e72..5a7ae7d8a 100644
--- a/packages/shared/src/authUrl.ts
+++ b/packages/shared/src/authUrl.ts
@@ -1,4 +1,3 @@
-import * as crypto from 'crypto';
import { CONNECTORS_METADATA } from './connectors/metadata';
import {
needsEndUserSubdomain,
@@ -31,22 +30,6 @@ interface AuthParams {
}
}
-function generateCodes() {
- const base64URLEncode = (str: Buffer): string => {
- return str.toString('base64')
- .replace(/\+/g, '-')
- .replace(/\//g, '_')
- .replace(/=/g, '');
- }
-
- const verifier = base64URLEncode(crypto.randomBytes(32));
- const challenge = base64URLEncode(
- crypto.createHash('sha256').update(Buffer.from(verifier)).digest()
- );
-
- return { codeVerifier: verifier, codeChallenge: challenge };
-}
-
export const constructAuthUrl = async ({
projectId,
linkedUserId,
@@ -84,6 +67,17 @@ export const constructAuthUrl = async ({
resource: additionalParams!.end_user_domain!
})).toString('base64'));
}
+ const opts: any = {};
+ if (['snyk', 'klaviyo'].includes(providerName)) {
+ const response = await fetch(`${apiUrl}/auth/s256Codes`);
+ const data = await response.json();
+ const { codeChallenge, codeVerifier } = data;
+ state = encodeURIComponent(JSON.stringify({
+ projectId, linkedUserId, providerName, vertical, returnUrl, code_verifier: codeVerifier
+ }));
+ opts.codeVerifier = codeVerifier;
+ opts.codeChallenge = codeChallenge;
+ }
if (vertical === null) {
throw new ReferenceError('vertical is null');
@@ -95,7 +89,7 @@ export const constructAuthUrl = async ({
case AuthStrategy.oauth2:
return handleOAuth2Url({
providerName, vertical, authStrategy, projectId, config,
- encodedRedirectUrl, state, apiUrl, additionalParams
+ encodedRedirectUrl, state, apiUrl, additionalParams, ...opts
});
case AuthStrategy.api_key:
return handleApiKeyUrl();
@@ -115,7 +109,8 @@ interface HandleOAuth2Url {
apiUrl: string;
additionalParams?: {
end_user_domain: string;
- }
+ };
+ [key: string]: any;
}
const handleOAuth2Url = async ({
@@ -128,6 +123,7 @@ const handleOAuth2Url = async ({
state,
apiUrl,
additionalParams,
+ ...dyn
}: HandleOAuth2Url) => {
const type = providerToType(providerName, vertical, authStrategy);
@@ -225,9 +221,9 @@ const handleOAuth2Url = async ({
case 'notion':
params += '&owner=user';
break;
+ case 'snyk':
case 'klaviyo':
- const { codeChallenge, codeVerifier } = generateCodes();
- params += `&code_challenge_method=S256&code_challenge=${codeChallenge}`;
+ params += `&code_challenge_method=S256&code_challenge=${dyn.codeChallenge}`;
break;
}
diff --git a/packages/shared/src/connectors/metadata.ts b/packages/shared/src/connectors/metadata.ts
index 9ffa15b32..e3fdab57e 100644
--- a/packages/shared/src/connectors/metadata.ts
+++ b/packages/shared/src/connectors/metadata.ts
@@ -130,7 +130,7 @@ export const CONNECTORS_METADATA: ProvidersConfig = {
},
logoPath: 'https://media.licdn.com/dms/image/C4D0BAQFOaK6KXEYj_w/company-logo_200_200/0/1630489791871/project_affinity_logo?e=2147483647&v=beta&t=u8j-1u3nO2m6vqgT170WJMCJyFSDiLYS_VguYOllNMI',
description: 'Sync & Create contacts, deals, companies, notes, engagements, stages, tasks and users',
- active: false,
+ active: true,
primaryColor: '#244CED',
authStrategy: {
strategy: AuthStrategy.basic,
@@ -458,7 +458,7 @@ export const CONNECTORS_METADATA: ProvidersConfig = {
},
logoPath: 'https://asset.brandfetch.io/iduDa181eM/idYYbqOlKi.png',
description: 'Sync & Create accounts, tickets, comments, attachments, contacts, tags, teams and users',
- active: false,
+ active: true,
authStrategy: {
strategy: AuthStrategy.oauth2
}
@@ -905,7 +905,7 @@ export const CONNECTORS_METADATA: ProvidersConfig = {
},
logoPath: 'https://play-lh.googleusercontent.com/EMobDJKabP1eY_63QHgPS_-TK3eRfxXaeOnERbcRaWAw573iaV74pXS9xOv997dRZtM',
description: 'Sync & Create contacts, deals, companies, notes, engagements, stages, tasks and users',
- active: false,
+ active: true,
authStrategy: {
strategy: AuthStrategy.oauth2
},
@@ -1020,9 +1020,9 @@ export const CONNECTORS_METADATA: ProvidersConfig = {
apiUrl: 'https://quickbooks.api.intuit.com/v3',
authBaseUrl: 'https://appcenter.intuit.com/connect/oauth2',
},
- logoPath: 'https://i.ibb.co/hMhHt5G/quickbooks-app-tips.png',
+ logoPath: 'https://media.licdn.com/dms/image/D4D12AQFduz3E6g6COg/article-cover_image-shrink_600_2000/0/1697053235030?e=2147483647&v=beta&t=c2Ia7g8fJ6wAHNlnogLV_Ii765HMqSw16HxgawsxmTw',
description: 'Sync & Create contacts, deals, companies, notes, engagements, stages, tasks and users',
- active: false,
+ active: true,
authStrategy: {
strategy: AuthStrategy.oauth2
}
@@ -1063,9 +1063,9 @@ export const CONNECTORS_METADATA: ProvidersConfig = {
apiUrl: 'https://api.xero.com/api.xro/2.0',
authBaseUrl: 'https://login.xero.com/identity/connect/authorize',
},
- logoPath: 'https://i.ibb.co/qpc2RQZ/xeroappicon.png',
+ logoPath: 'https://upload.wikimedia.org/wikipedia/en/archive/9/9f/20171204173437%21Xero_software_logo.svg',
description: 'Sync & Create contacts, deals, companies, notes, engagements, stages, tasks and users',
- active: false,
+ active: true,
authStrategy: {
strategy: AuthStrategy.oauth2
}
@@ -1270,7 +1270,7 @@ export const CONNECTORS_METADATA: ProvidersConfig = {
},
logoPath: 'https://play-lh.googleusercontent.com/c4BW9wr_QAiIeVBYHhP7rs06w99xJzxgLvmL5I1mkucC3_ATMyL1t7Doz0_LQ0X-qS0',
description: 'Sync & Create contacts, deals, companies, notes, engagements, stages, tasks and users',
- active: false,
+ active: true,
primaryColor: '#599D16',
authStrategy: {
strategy: AuthStrategy.basic,
@@ -1431,9 +1431,9 @@ export const CONNECTORS_METADATA: ProvidersConfig = {
apiUrl: 'https://api.greenhouse.io/v1/partner',
authBaseUrl: 'https://api.greenhouse.io/oauth/authorize'
},
- logoPath: 'https://play-lh.googleusercontent.com/EMobDJKabP1eY_63QHgPS_-TK3eRfxXaeOnERbcRaWAw573iaV74pXS9xOv997dRZtM',
+ logoPath: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSQRGdTs2tatWjail4b3hpHLIyI-6gXZLxhvw&s',
description: 'Sync & Create contacts, deals, companies, notes, engagements, stages, tasks and users',
- active: false,
+ active: true,
authStrategy: {
strategy: AuthStrategy.oauth2
}
@@ -1591,7 +1591,7 @@ export const CONNECTORS_METADATA: ProvidersConfig = {
},
logoPath: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQbR9XSB1lbZnYlLWyqMe5Px80ghtEOUqHeqw&s',
description: 'Sync & Create contacts, deals, companies, notes, engagements, stages, tasks and users',
- active: false,
+ active: true,
authStrategy: {
strategy: AuthStrategy.oauth2
}
@@ -1837,7 +1837,7 @@ export const CONNECTORS_METADATA: ProvidersConfig = {
},
logoPath: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSZTX2h9yFQ0u4ziDqvfQ224wW4N1s5JvJ5nA&s',
description: 'Sync & Create contacts, deals, companies, notes, engagements, stages, tasks and users',
- active: false,
+ active: true,
authStrategy: {
strategy: AuthStrategy.api_key
}
@@ -2043,7 +2043,7 @@ export const CONNECTORS_METADATA: ProvidersConfig = {
},
logoPath: 'https://avatars.githubusercontent.com/u/19614805?s=280&v=4',
description: 'Sync & Create contacts, deals, companies, notes, engagements, stages, tasks and users',
- active: false,
+ active: true,
authStrategy: {
strategy: AuthStrategy.oauth2
},
@@ -2719,9 +2719,9 @@ export const CONNECTORS_METADATA: ProvidersConfig = {
apiUrl: 'https://www.googleapis.com/drive',
authBaseUrl: 'https://accounts.google.com/o/oauth2/v2/auth'
},
- logoPath: 'https://static-00.iconduck.com/assets.00/google-drive-icon-2048x2048-j5sa1hcp.png',
+ logoPath: 'https://upload.wikimedia.org/wikipedia/commons/d/da/Google_Drive_logo.png',
description: 'Sync & Create contacts, deals, companies, notes, engagements, stages, tasks and users',
- active: false,
+ active: true,
authStrategy: {
strategy: AuthStrategy.oauth2
}
@@ -2735,7 +2735,7 @@ export const CONNECTORS_METADATA: ProvidersConfig = {
},
logoPath: 'https://logowik.com/content/uploads/images/4964-microsoft-onedrive-new.jpg',
description: 'Sync & Create contacts, deals, companies, notes, engagements, stages, tasks and users',
- active: false,
+ active: true,
authStrategy: {
strategy: AuthStrategy.oauth2
}
@@ -2748,7 +2748,7 @@ export const CONNECTORS_METADATA: ProvidersConfig = {
},
logoPath: 'https://cdn2.iconfinder.com/data/icons/metro-ui-dock/512/Dropbox.png',
description: 'Sync & Create contacts, deals, companies, notes, engagements, stages, tasks and users',
- active: false,
+ active: true,
authStrategy: {
strategy: AuthStrategy.oauth2
}
@@ -2762,7 +2762,8 @@ export const CONNECTORS_METADATA: ProvidersConfig = {
},
logoPath: 'https://pnghq.com/wp-content/uploads/pnghq.com-microsoft-sharepoint-logo-9.png',
description: 'Sync & Create contacts, deals, companies, notes, engagements, stages, tasks and users',
- active: false,
+ active: true,
+ primaryColor: '',
options: {
local_redirect_uri_in_https: true
},
@@ -2793,7 +2794,7 @@ export const CONNECTORS_METADATA: ProvidersConfig = {
},
logoPath: 'https://upload.wikimedia.org/wikipedia/commons/4/45/Notion_app_logo.png',
description: 'Sync & Create contacts, deals, companies, notes, engagements, stages, tasks and users',
- active: false,
+ active: true,
authStrategy: {
strategy: AuthStrategy.oauth2
}
@@ -2807,7 +2808,7 @@ export const CONNECTORS_METADATA: ProvidersConfig = {
},
logoPath: 'https://assets-global.website-files.com/621c8d7ad9e04933c4e51ffb/65eba5ffa14998827c92cc01_slack-octothorpe.png',
description: 'Sync & Create contacts, deals, companies, notes, engagements, stages, tasks and users',
- active: false,
+ active: true,
options: {
local_redirect_uri_in_https: true
},
@@ -2824,7 +2825,7 @@ export const CONNECTORS_METADATA: ProvidersConfig = {
},
logoPath: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTH_-bQ399xl-yfJYhbLraU-w0yWBcppLf8NA&s',
description: 'Sync & Create orders, fulfillments, fulfillment orders, customers and products',
- active: false,
+ active: true,
primaryColor: '#000001',
authStrategy: {
strategy: AuthStrategy.api_key,
@@ -2840,7 +2841,7 @@ export const CONNECTORS_METADATA: ProvidersConfig = {
},
logoPath: 'https://www.logodesignlove.com/images/evolution/ebay-logo-01.jpg',
description: 'Sync & Create orders, fulfillments, fulfillment orders, customers and products',
- active: false,
+ active: true,
options: {
local_redirect_uri_in_https: true,
oauth_attributes: ['ruvalue']
@@ -2903,7 +2904,7 @@ export const CONNECTORS_METADATA: ProvidersConfig = {
},
logoPath: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTKRidZq3jXGYOIZ2X2EruCx0pFMkbsHineLg&s',
description: 'Sync & Create orders, fulfillments, fulfillment orders, customers and products',
- active: false,
+ active: true,
authStrategy: {
strategy: AuthStrategy.oauth2
},
@@ -2917,7 +2918,7 @@ export const CONNECTORS_METADATA: ProvidersConfig = {
},
logoPath: 'https://dailybrand.co.zw/wp-content/uploads/2023/10/webflow-2.png',
description: 'Sync & Create orders, fulfillments, fulfillment orders, customers and products',
- active: false,
+ active: true,
authStrategy: {
strategy: AuthStrategy.oauth2
},
@@ -2934,7 +2935,7 @@ export const CONNECTORS_METADATA: ProvidersConfig = {
},
logoPath: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSSDg6WOKCYRvGFmwtaJ6Gv88PjAGRS9_h9EQ&s',
description: 'Sync & Create orders, fulfillments, fulfillment orders, customers and products',
- active: false,
+ active: true,
authStrategy: {
strategy: AuthStrategy.oauth2
},
@@ -2948,7 +2949,7 @@ export const CONNECTORS_METADATA: ProvidersConfig = {
},
logoPath: 'https://api.getkoala.com/web/companies/mercadolibre.com/logo',
description: 'Sync & Create orders, fulfillments, fulfillment orders, customers and products',
- active: false,
+ active: true,
authStrategy: {
strategy: AuthStrategy.oauth2
},
@@ -2976,7 +2977,7 @@ export const CONNECTORS_METADATA: ProvidersConfig = {
},
logoPath: 'https://yt3.googleusercontent.com/NWVXYvuzHDgJJsbda7eyyz21Ba2qnq5WmuGrt9ax1rs6PP-mlDl5LCJ4ZO0Z2ZbiCq4ZoxqiGg=s900-c-k-c0x00ffffff-no-rj',
description: 'Sync & Create orders, fulfillments, fulfillment orders, customers and products',
- active: false,
+ active: true,
primaryColor: '#10C096',
authStrategy: {
strategy: AuthStrategy.api_key,
@@ -2984,7 +2985,7 @@ export const CONNECTORS_METADATA: ProvidersConfig = {
}
},
'snyk': {
- scopes: '',
+ scopes: 'org.read org.report.read org.project.read',
urls: {
docsUrl: 'https://docs.snyk.io/snyk-api/',
apiUrl: 'https://api.snyk.io',
@@ -2992,7 +2993,7 @@ export const CONNECTORS_METADATA: ProvidersConfig = {
},
logoPath: 'https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Forganization%2Fprofile_image%2F1215%2Ffe4be452-1e68-444a-bf77-db21bf3a7bdc.png',
description: 'Sync & Create orders, fulfillments, fulfillment orders, customers and products',
- active: false,
+ active: true,
authStrategy: {
strategy: AuthStrategy.oauth2
},
@@ -3007,7 +3008,7 @@ export const CONNECTORS_METADATA: ProvidersConfig = {
},
logoPath: 'https://pbs.twimg.com/profile_images/1410604377757216768/ocEKYniC_400x400.jpg',
description: 'Sync & Create orders, fulfillments, fulfillment orders, customers and products',
- active: false,
+ active: true,
primaryColor: '#0D1E40',
authStrategy: {
strategy: AuthStrategy.basic,
@@ -3021,7 +3022,7 @@ export const CONNECTORS_METADATA: ProvidersConfig = {
},
logoPath: 'https://companieslogo.com/img/orig/QLYS-68c2032c.png?t=1720244493',
description: 'Sync & Create orders, fulfillments, fulfillment orders, customers and products',
- active: false,
+ active: true,
primaryColor: '#ED2E28',
authStrategy: {
strategy: AuthStrategy.basic,
@@ -3035,7 +3036,7 @@ export const CONNECTORS_METADATA: ProvidersConfig = {
},
logoPath: 'https://images.saasworthy.com/insightvm_9113_logo_1635748346_lc0gr.png',
description: 'Sync & Create orders, fulfillments, fulfillment orders, customers and products',
- active: false,
+ active: true,
primaryColor: '#E95722',
authStrategy: {
strategy: AuthStrategy.api_key,
@@ -3051,7 +3052,7 @@ export const CONNECTORS_METADATA: ProvidersConfig = {
},
logoPath: 'https://pbs.twimg.com/profile_images/1451022302578049024/6L-zG5oq_400x400.jpg',
description: 'Sync & Create orders, fulfillments, fulfillment orders, customers and products',
- active: false,
+ active: true,
primaryColor: '#FC0001',
authStrategy: {
strategy: AuthStrategy.oauth2,
@@ -3064,7 +3065,7 @@ export const CONNECTORS_METADATA: ProvidersConfig = {
},
logoPath: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTZHLye2za7fjLiggqC1upKhhM3T-laySJSLQ&s',
description: 'Sync & Create orders, fulfillments, fulfillment orders, customers and products',
- active: false,
+ active: true,
primaryColor: '#522E74',
authStrategy: {
strategy: AuthStrategy.api_key,
@@ -3080,7 +3081,7 @@ export const CONNECTORS_METADATA: ProvidersConfig = {
},
logoPath: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSuR4GZElDP7UNKhXS9jDGpElBTdchjg8hSsA&s',
description: 'Sync & Create orders, fulfillments, fulfillment orders, customers and products',
- active: false,
+ active: true,
primaryColor: '#0078D8',
authStrategy: {
strategy: AuthStrategy.oauth2,
diff --git a/packages/shared/tsconfig.json b/packages/shared/tsconfig.json
index 9e6f5265b..7bec40790 100644
--- a/packages/shared/tsconfig.json
+++ b/packages/shared/tsconfig.json
@@ -10,7 +10,7 @@
"outDir": "./dist",
"rootDir": "./src",
"baseUrl": "./",
- "noLib": false
+ "noLib": false,
},
"include": ["src/**/*.ts"],
"exclude": ["node_modules"]
From c1b815691d6f832f061f914af31e437a1549353e Mon Sep 17 00:00:00 2001
From: nael
Date: Sun, 18 Aug 2024 01:37:01 +0200
Subject: [PATCH 13/49] :fire: Remove true properties to some connectors
---
packages/shared/src/connectors/metadata.ts | 58 +++++++++++-----------
1 file changed, 29 insertions(+), 29 deletions(-)
diff --git a/packages/shared/src/connectors/metadata.ts b/packages/shared/src/connectors/metadata.ts
index e3fdab57e..62e424368 100644
--- a/packages/shared/src/connectors/metadata.ts
+++ b/packages/shared/src/connectors/metadata.ts
@@ -130,7 +130,7 @@ export const CONNECTORS_METADATA: ProvidersConfig = {
},
logoPath: 'https://media.licdn.com/dms/image/C4D0BAQFOaK6KXEYj_w/company-logo_200_200/0/1630489791871/project_affinity_logo?e=2147483647&v=beta&t=u8j-1u3nO2m6vqgT170WJMCJyFSDiLYS_VguYOllNMI',
description: 'Sync & Create contacts, deals, companies, notes, engagements, stages, tasks and users',
- active: true,
+ active: false,
primaryColor: '#244CED',
authStrategy: {
strategy: AuthStrategy.basic,
@@ -458,7 +458,7 @@ export const CONNECTORS_METADATA: ProvidersConfig = {
},
logoPath: 'https://asset.brandfetch.io/iduDa181eM/idYYbqOlKi.png',
description: 'Sync & Create accounts, tickets, comments, attachments, contacts, tags, teams and users',
- active: true,
+ active: false,
authStrategy: {
strategy: AuthStrategy.oauth2
}
@@ -1022,7 +1022,7 @@ export const CONNECTORS_METADATA: ProvidersConfig = {
},
logoPath: 'https://media.licdn.com/dms/image/D4D12AQFduz3E6g6COg/article-cover_image-shrink_600_2000/0/1697053235030?e=2147483647&v=beta&t=c2Ia7g8fJ6wAHNlnogLV_Ii765HMqSw16HxgawsxmTw',
description: 'Sync & Create contacts, deals, companies, notes, engagements, stages, tasks and users',
- active: true,
+ active: false,
authStrategy: {
strategy: AuthStrategy.oauth2
}
@@ -1065,7 +1065,7 @@ export const CONNECTORS_METADATA: ProvidersConfig = {
},
logoPath: 'https://upload.wikimedia.org/wikipedia/en/archive/9/9f/20171204173437%21Xero_software_logo.svg',
description: 'Sync & Create contacts, deals, companies, notes, engagements, stages, tasks and users',
- active: true,
+ active: false,
authStrategy: {
strategy: AuthStrategy.oauth2
}
@@ -1270,7 +1270,7 @@ export const CONNECTORS_METADATA: ProvidersConfig = {
},
logoPath: 'https://play-lh.googleusercontent.com/c4BW9wr_QAiIeVBYHhP7rs06w99xJzxgLvmL5I1mkucC3_ATMyL1t7Doz0_LQ0X-qS0',
description: 'Sync & Create contacts, deals, companies, notes, engagements, stages, tasks and users',
- active: true,
+ active: false,
primaryColor: '#599D16',
authStrategy: {
strategy: AuthStrategy.basic,
@@ -1433,7 +1433,7 @@ export const CONNECTORS_METADATA: ProvidersConfig = {
},
logoPath: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSQRGdTs2tatWjail4b3hpHLIyI-6gXZLxhvw&s',
description: 'Sync & Create contacts, deals, companies, notes, engagements, stages, tasks and users',
- active: true,
+ active: false,
authStrategy: {
strategy: AuthStrategy.oauth2
}
@@ -1591,7 +1591,7 @@ export const CONNECTORS_METADATA: ProvidersConfig = {
},
logoPath: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQbR9XSB1lbZnYlLWyqMe5Px80ghtEOUqHeqw&s',
description: 'Sync & Create contacts, deals, companies, notes, engagements, stages, tasks and users',
- active: true,
+ active: false,
authStrategy: {
strategy: AuthStrategy.oauth2
}
@@ -1837,7 +1837,7 @@ export const CONNECTORS_METADATA: ProvidersConfig = {
},
logoPath: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSZTX2h9yFQ0u4ziDqvfQ224wW4N1s5JvJ5nA&s',
description: 'Sync & Create contacts, deals, companies, notes, engagements, stages, tasks and users',
- active: true,
+ active: false,
authStrategy: {
strategy: AuthStrategy.api_key
}
@@ -2043,7 +2043,7 @@ export const CONNECTORS_METADATA: ProvidersConfig = {
},
logoPath: 'https://avatars.githubusercontent.com/u/19614805?s=280&v=4',
description: 'Sync & Create contacts, deals, companies, notes, engagements, stages, tasks and users',
- active: true,
+ active: false,
authStrategy: {
strategy: AuthStrategy.oauth2
},
@@ -2721,7 +2721,7 @@ export const CONNECTORS_METADATA: ProvidersConfig = {
},
logoPath: 'https://upload.wikimedia.org/wikipedia/commons/d/da/Google_Drive_logo.png',
description: 'Sync & Create contacts, deals, companies, notes, engagements, stages, tasks and users',
- active: true,
+ active: false,
authStrategy: {
strategy: AuthStrategy.oauth2
}
@@ -2735,7 +2735,7 @@ export const CONNECTORS_METADATA: ProvidersConfig = {
},
logoPath: 'https://logowik.com/content/uploads/images/4964-microsoft-onedrive-new.jpg',
description: 'Sync & Create contacts, deals, companies, notes, engagements, stages, tasks and users',
- active: true,
+ active: false,
authStrategy: {
strategy: AuthStrategy.oauth2
}
@@ -2748,7 +2748,7 @@ export const CONNECTORS_METADATA: ProvidersConfig = {
},
logoPath: 'https://cdn2.iconfinder.com/data/icons/metro-ui-dock/512/Dropbox.png',
description: 'Sync & Create contacts, deals, companies, notes, engagements, stages, tasks and users',
- active: true,
+ active: false,
authStrategy: {
strategy: AuthStrategy.oauth2
}
@@ -2762,7 +2762,7 @@ export const CONNECTORS_METADATA: ProvidersConfig = {
},
logoPath: 'https://pnghq.com/wp-content/uploads/pnghq.com-microsoft-sharepoint-logo-9.png',
description: 'Sync & Create contacts, deals, companies, notes, engagements, stages, tasks and users',
- active: true,
+ active: false,
primaryColor: '',
options: {
local_redirect_uri_in_https: true
@@ -2794,7 +2794,7 @@ export const CONNECTORS_METADATA: ProvidersConfig = {
},
logoPath: 'https://upload.wikimedia.org/wikipedia/commons/4/45/Notion_app_logo.png',
description: 'Sync & Create contacts, deals, companies, notes, engagements, stages, tasks and users',
- active: true,
+ active: false,
authStrategy: {
strategy: AuthStrategy.oauth2
}
@@ -2808,7 +2808,7 @@ export const CONNECTORS_METADATA: ProvidersConfig = {
},
logoPath: 'https://assets-global.website-files.com/621c8d7ad9e04933c4e51ffb/65eba5ffa14998827c92cc01_slack-octothorpe.png',
description: 'Sync & Create contacts, deals, companies, notes, engagements, stages, tasks and users',
- active: true,
+ active: false,
options: {
local_redirect_uri_in_https: true
},
@@ -2825,7 +2825,7 @@ export const CONNECTORS_METADATA: ProvidersConfig = {
},
logoPath: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTH_-bQ399xl-yfJYhbLraU-w0yWBcppLf8NA&s',
description: 'Sync & Create orders, fulfillments, fulfillment orders, customers and products',
- active: true,
+ active: false,
primaryColor: '#000001',
authStrategy: {
strategy: AuthStrategy.api_key,
@@ -2841,7 +2841,7 @@ export const CONNECTORS_METADATA: ProvidersConfig = {
},
logoPath: 'https://www.logodesignlove.com/images/evolution/ebay-logo-01.jpg',
description: 'Sync & Create orders, fulfillments, fulfillment orders, customers and products',
- active: true,
+ active: false,
options: {
local_redirect_uri_in_https: true,
oauth_attributes: ['ruvalue']
@@ -2904,7 +2904,7 @@ export const CONNECTORS_METADATA: ProvidersConfig = {
},
logoPath: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTKRidZq3jXGYOIZ2X2EruCx0pFMkbsHineLg&s',
description: 'Sync & Create orders, fulfillments, fulfillment orders, customers and products',
- active: true,
+ active: false,
authStrategy: {
strategy: AuthStrategy.oauth2
},
@@ -2918,7 +2918,7 @@ export const CONNECTORS_METADATA: ProvidersConfig = {
},
logoPath: 'https://dailybrand.co.zw/wp-content/uploads/2023/10/webflow-2.png',
description: 'Sync & Create orders, fulfillments, fulfillment orders, customers and products',
- active: true,
+ active: false,
authStrategy: {
strategy: AuthStrategy.oauth2
},
@@ -2935,7 +2935,7 @@ export const CONNECTORS_METADATA: ProvidersConfig = {
},
logoPath: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSSDg6WOKCYRvGFmwtaJ6Gv88PjAGRS9_h9EQ&s',
description: 'Sync & Create orders, fulfillments, fulfillment orders, customers and products',
- active: true,
+ active: false,
authStrategy: {
strategy: AuthStrategy.oauth2
},
@@ -2949,7 +2949,7 @@ export const CONNECTORS_METADATA: ProvidersConfig = {
},
logoPath: 'https://api.getkoala.com/web/companies/mercadolibre.com/logo',
description: 'Sync & Create orders, fulfillments, fulfillment orders, customers and products',
- active: true,
+ active: false,
authStrategy: {
strategy: AuthStrategy.oauth2
},
@@ -2977,7 +2977,7 @@ export const CONNECTORS_METADATA: ProvidersConfig = {
},
logoPath: 'https://yt3.googleusercontent.com/NWVXYvuzHDgJJsbda7eyyz21Ba2qnq5WmuGrt9ax1rs6PP-mlDl5LCJ4ZO0Z2ZbiCq4ZoxqiGg=s900-c-k-c0x00ffffff-no-rj',
description: 'Sync & Create orders, fulfillments, fulfillment orders, customers and products',
- active: true,
+ active: false,
primaryColor: '#10C096',
authStrategy: {
strategy: AuthStrategy.api_key,
@@ -2993,7 +2993,7 @@ export const CONNECTORS_METADATA: ProvidersConfig = {
},
logoPath: 'https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Forganization%2Fprofile_image%2F1215%2Ffe4be452-1e68-444a-bf77-db21bf3a7bdc.png',
description: 'Sync & Create orders, fulfillments, fulfillment orders, customers and products',
- active: true,
+ active: false,
authStrategy: {
strategy: AuthStrategy.oauth2
},
@@ -3008,7 +3008,7 @@ export const CONNECTORS_METADATA: ProvidersConfig = {
},
logoPath: 'https://pbs.twimg.com/profile_images/1410604377757216768/ocEKYniC_400x400.jpg',
description: 'Sync & Create orders, fulfillments, fulfillment orders, customers and products',
- active: true,
+ active: false,
primaryColor: '#0D1E40',
authStrategy: {
strategy: AuthStrategy.basic,
@@ -3022,7 +3022,7 @@ export const CONNECTORS_METADATA: ProvidersConfig = {
},
logoPath: 'https://companieslogo.com/img/orig/QLYS-68c2032c.png?t=1720244493',
description: 'Sync & Create orders, fulfillments, fulfillment orders, customers and products',
- active: true,
+ active: false,
primaryColor: '#ED2E28',
authStrategy: {
strategy: AuthStrategy.basic,
@@ -3036,7 +3036,7 @@ export const CONNECTORS_METADATA: ProvidersConfig = {
},
logoPath: 'https://images.saasworthy.com/insightvm_9113_logo_1635748346_lc0gr.png',
description: 'Sync & Create orders, fulfillments, fulfillment orders, customers and products',
- active: true,
+ active: false,
primaryColor: '#E95722',
authStrategy: {
strategy: AuthStrategy.api_key,
@@ -3052,7 +3052,7 @@ export const CONNECTORS_METADATA: ProvidersConfig = {
},
logoPath: 'https://pbs.twimg.com/profile_images/1451022302578049024/6L-zG5oq_400x400.jpg',
description: 'Sync & Create orders, fulfillments, fulfillment orders, customers and products',
- active: true,
+ active: false,
primaryColor: '#FC0001',
authStrategy: {
strategy: AuthStrategy.oauth2,
@@ -3065,7 +3065,7 @@ export const CONNECTORS_METADATA: ProvidersConfig = {
},
logoPath: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTZHLye2za7fjLiggqC1upKhhM3T-laySJSLQ&s',
description: 'Sync & Create orders, fulfillments, fulfillment orders, customers and products',
- active: true,
+ active: false,
primaryColor: '#522E74',
authStrategy: {
strategy: AuthStrategy.api_key,
@@ -3081,7 +3081,7 @@ export const CONNECTORS_METADATA: ProvidersConfig = {
},
logoPath: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSuR4GZElDP7UNKhXS9jDGpElBTdchjg8hSsA&s',
description: 'Sync & Create orders, fulfillments, fulfillment orders, customers and products',
- active: true,
+ active: false,
primaryColor: '#0078D8',
authStrategy: {
strategy: AuthStrategy.oauth2,
From 66be9acf1a5dcda528e1849a773491bee0c23528 Mon Sep 17 00:00:00 2001
From: nael
Date: Sun, 18 Aug 2024 07:29:10 +0200
Subject: [PATCH 14/49] :bug: Fix bamboihr connection
---
packages/api/src/@core/auth/auth.controller.ts | 5 ++++-
.../ats/services/bamboohr/bamboohr.service.ts | 16 +++++++---------
.../src/filestorage/file/services/box/index.ts | 17 ++++++++---------
packages/shared/src/connectors/metadata.ts | 8 +++++---
4 files changed, 24 insertions(+), 22 deletions(-)
diff --git a/packages/api/src/@core/auth/auth.controller.ts b/packages/api/src/@core/auth/auth.controller.ts
index 5a9895cf9..b0a3a761b 100644
--- a/packages/api/src/@core/auth/auth.controller.ts
+++ b/packages/api/src/@core/auth/auth.controller.ts
@@ -38,7 +38,10 @@ export class AuthController {
this.logger.setContext(AuthController.name);
}
- @ApiOperation({ operationId: 'generateCodes', summary: 'generateCodes' })
+ @ApiOperation({
+ operationId: 'generateCodes',
+ summary: 'generate codes for s256 challenge',
+ })
@ApiResponse({ status: 200 })
@Get('s256Codes')
@ApiExcludeEndpoint()
diff --git a/packages/api/src/@core/connections/ats/services/bamboohr/bamboohr.service.ts b/packages/api/src/@core/connections/ats/services/bamboohr/bamboohr.service.ts
index 92c56609f..3f0df3d4e 100644
--- a/packages/api/src/@core/connections/ats/services/bamboohr/bamboohr.service.ts
+++ b/packages/api/src/@core/connections/ats/services/bamboohr/bamboohr.service.ts
@@ -2,6 +2,7 @@ import { EncryptionService } from '@@core/@core-services/encryption/encryption.s
import { EnvironmentService } from '@@core/@core-services/environment/environment.service';
import { LoggerService } from '@@core/@core-services/logger/logger.service';
import { PrismaService } from '@@core/@core-services/prisma/prisma.service';
+import { RetryHandler } from '@@core/@core-services/request-retry/retry.handler';
import { ConnectionsStrategiesService } from '@@core/connections-strategies/connections-strategies.service';
import { ConnectionUtils } from '@@core/connections/@utils';
import {
@@ -10,6 +11,7 @@ import {
PassthroughInput,
RefreshParams,
} from '@@core/connections/@utils/types';
+import { PassthroughResponse } from '@@core/passthrough/types';
import { Injectable } from '@nestjs/common';
import {
AuthStrategy,
@@ -17,11 +19,8 @@ import {
DynamicApiUrl,
providerToType,
} from '@panora/shared';
-import axios from 'axios';
import { v4 as uuidv4 } from 'uuid';
import { ServiceRegistry } from '../registry.service';
-import { RetryHandler } from '@@core/@core-services/request-retry/retry.handler';
-import { PassthroughResponse } from '@@core/passthrough/types';
export type BamboohrOAuthResponse = {
access_token: string;
@@ -92,7 +91,7 @@ export class BamboohrConnectionService extends AbstractBaseConnectionService {
async handleCallback(opts: OAuthCallbackParams) {
try {
const { linkedUserId, projectId, body } = opts;
- const { username, company_subdomain } = body;
+ const { api_key, subdomain } = body;
const isNotUnique = await this.prisma.connections.findFirst({
where: {
id_linked_user: linkedUserId,
@@ -104,16 +103,15 @@ export class BamboohrConnectionService extends AbstractBaseConnectionService {
let db_res;
const connection_token = uuidv4();
const BASE_API_URL = (
- CONNECTORS_METADATA['ats']['bamboohr'].urls
- .apiUrl as DynamicApiUrl
- )(company_subdomain);
+ CONNECTORS_METADATA['ats']['bamboohr'].urls.apiUrl as DynamicApiUrl
+ )(subdomain);
if (isNotUnique) {
db_res = await this.prisma.connections.update({
where: {
id_connection: isNotUnique.id_connection,
},
data: {
- access_token: this.cryptoService.encrypt(username),
+ access_token: this.cryptoService.encrypt(api_key),
account_url: BASE_API_URL,
status: 'valid',
created_at: new Date(),
@@ -128,7 +126,7 @@ export class BamboohrConnectionService extends AbstractBaseConnectionService {
vertical: 'ats',
token_type: 'basic',
account_url: BASE_API_URL,
- access_token: this.cryptoService.encrypt(username),
+ access_token: this.cryptoService.encrypt(api_key),
status: 'valid',
created_at: new Date(),
projects: {
diff --git a/packages/api/src/filestorage/file/services/box/index.ts b/packages/api/src/filestorage/file/services/box/index.ts
index 5c4cf5b12..a5ba5f4c8 100644
--- a/packages/api/src/filestorage/file/services/box/index.ts
+++ b/packages/api/src/filestorage/file/services/box/index.ts
@@ -1,15 +1,14 @@
-import { Injectable } from '@nestjs/common';
-import { IFileService } from '@filestorage/file/types';
-import { FileStorageObject } from '@filestorage/@lib/@types';
-import axios from 'axios';
-import { PrismaService } from '@@core/@core-services/prisma/prisma.service';
-import { LoggerService } from '@@core/@core-services/logger/logger.service';
-import { ActionType, handle3rdPartyServiceError } from '@@core/utils/errors';
import { EncryptionService } from '@@core/@core-services/encryption/encryption.service';
+import { LoggerService } from '@@core/@core-services/logger/logger.service';
+import { PrismaService } from '@@core/@core-services/prisma/prisma.service';
import { ApiResponse } from '@@core/utils/types';
-import { ServiceRegistry } from '../registry.service';
-import { BoxFileInput, BoxFileOutput } from './types';
import { SyncParam } from '@@core/utils/types/interface';
+import { FileStorageObject } from '@filestorage/@lib/@types';
+import { IFileService } from '@filestorage/file/types';
+import { Injectable } from '@nestjs/common';
+import axios from 'axios';
+import { ServiceRegistry } from '../registry.service';
+import { BoxFileOutput } from './types';
@Injectable()
export class BoxService implements IFileService {
diff --git a/packages/shared/src/connectors/metadata.ts b/packages/shared/src/connectors/metadata.ts
index 62e424368..873590f9c 100644
--- a/packages/shared/src/connectors/metadata.ts
+++ b/packages/shared/src/connectors/metadata.ts
@@ -905,7 +905,7 @@ export const CONNECTORS_METADATA: ProvidersConfig = {
},
logoPath: 'https://play-lh.googleusercontent.com/EMobDJKabP1eY_63QHgPS_-TK3eRfxXaeOnERbcRaWAw573iaV74pXS9xOv997dRZtM',
description: 'Sync & Create contacts, deals, companies, notes, engagements, stages, tasks and users',
- active: true,
+ active: false,
authStrategy: {
strategy: AuthStrategy.oauth2
},
@@ -1274,7 +1274,7 @@ export const CONNECTORS_METADATA: ProvidersConfig = {
primaryColor: '#599D16',
authStrategy: {
strategy: AuthStrategy.basic,
- properties: ['username', 'subdomain']
+ properties: ['subdomain', 'api_key']
},
},
'breezy': {
@@ -1838,8 +1838,10 @@ export const CONNECTORS_METADATA: ProvidersConfig = {
logoPath: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSZTX2h9yFQ0u4ziDqvfQ224wW4N1s5JvJ5nA&s',
description: 'Sync & Create contacts, deals, companies, notes, engagements, stages, tasks and users',
active: false,
+ primaryColor: '#0167AB',
authStrategy: {
- strategy: AuthStrategy.api_key
+ strategy: AuthStrategy.api_key,
+ properties: ['api_key']
}
},
'zoho_recruit': {
From 68dae36aa952ebd8f91fd4a87edd361c66fca563 Mon Sep 17 00:00:00 2001
From: Subin C
Date: Thu, 22 Aug 2024 11:18:52 +0530
Subject: [PATCH 15/49] =?UTF-8?q?=F0=9F=90=9B=20If=20Column=20contains=20a?=
=?UTF-8?q?=20null=20data=20then=20act=20as=20if=20the=20colum=20was=20set?=
=?UTF-8?q?=20to=20true=20#561?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../react/src/components/PanoraDynamicCatalog.tsx | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/apps/embedded-catalog/react/src/components/PanoraDynamicCatalog.tsx b/apps/embedded-catalog/react/src/components/PanoraDynamicCatalog.tsx
index 27685e13e..f8208cc8e 100644
--- a/apps/embedded-catalog/react/src/components/PanoraDynamicCatalog.tsx
+++ b/apps/embedded-catalog/react/src/components/PanoraDynamicCatalog.tsx
@@ -168,7 +168,7 @@ const DynamicCatalog = ({projectId,linkedUserId, category, optionalApiUrl} : Dyn
return [{
connector_name: connector_name,
category: category,
- status: String(value)
+ status: value === null ? "true" : String(value)
}];
}
return [];
From 4c32cd424bccaa463a222465bcc193dad900fc3a Mon Sep 17 00:00:00 2001
From: Subin C
Date: Thu, 22 Aug 2024 15:46:29 +0530
Subject: [PATCH 16/49] =?UTF-8?q?=F0=9F=90=9B=20Removed=20returnurl=20in?=
=?UTF-8?q?=20code=20example=20#674?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
"removed returnurl in code example #674"
---
.../src/components/Configuration/Catalog/CopySnippet.tsx | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/apps/webapp/src/components/Configuration/Catalog/CopySnippet.tsx b/apps/webapp/src/components/Configuration/Catalog/CopySnippet.tsx
index f8ba24d40..464ebfd40 100644
--- a/apps/webapp/src/components/Configuration/Catalog/CopySnippet.tsx
+++ b/apps/webapp/src/components/Configuration/Catalog/CopySnippet.tsx
@@ -28,7 +28,7 @@ export const CopySnippet = () => {
``
);
@@ -131,7 +131,7 @@ export const CopySnippet = () => {
projectId{`={'c9a1b1f8-466d-442d-a95e-11cdd00baf49'}`}
- returnUrl{`={'https://acme.inc'}`}
+ optionalApiUrl{`={'https://acme.inc'}`}
linkedUserId{`={'b860d6c1-28f9-485c-86cd-fb09e60f10a2'}`}
@@ -191,7 +191,7 @@ export const CopySnippet = () => {
projectId{`={'c9a1b1f8-466d-442d-a95e-11cdd00baf49'}`}
- returnUrl{`={'https://acme.inc'}`}
+ optionalApiUrl{`={'https://acme.inc'}`}
linkedUserId{`={'b860d6c1-28f9-485c-86cd-fb09e60f10a2'}`}
From c08d89ec1babcf6c72515e1e4cd3186dd4a83e8f Mon Sep 17 00:00:00 2001
From: Subin C
Date: Thu, 22 Aug 2024 15:48:35 +0530
Subject: [PATCH 17/49] =?UTF-8?q?=F0=9F=90=9B=20Removed=20returnurl=20in?=
=?UTF-8?q?=20code=20example=20#674?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
removed returnurl in code example #674
---
.../webapp/src/components/Configuration/Catalog/CopySnippet.tsx | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/apps/webapp/src/components/Configuration/Catalog/CopySnippet.tsx b/apps/webapp/src/components/Configuration/Catalog/CopySnippet.tsx
index 464ebfd40..896f02c2d 100644
--- a/apps/webapp/src/components/Configuration/Catalog/CopySnippet.tsx
+++ b/apps/webapp/src/components/Configuration/Catalog/CopySnippet.tsx
@@ -50,7 +50,7 @@ export const CopySnippet = () => {
name={"hubspot"}
category={ConnectorCategory.Crm}
projectId={"c9a1b1f8-466d-442d-a95e-11cdd00baf49"}
- returnUrl={"https://acme.inc"}
+ optionalApiUrl={"https://acme.inc"}
linkedUserId={"b860d6c1-28f9-485c-86cd-fb09e60f10a2"}
/>`
);
From bdab891c6d3eaba2d0d334cb18ecbf08d7788b62 Mon Sep 17 00:00:00 2001
From: Ram Krishna Singh
Date: Sat, 24 Aug 2024 12:07:20 +0530
Subject: [PATCH 18/49] stores account output api data in remote_data
---
packages/api/src/ticketing/account/services/front/mappers.ts | 1 +
packages/api/src/ticketing/account/services/zendesk/mappers.ts | 1 +
2 files changed, 2 insertions(+)
diff --git a/packages/api/src/ticketing/account/services/front/mappers.ts b/packages/api/src/ticketing/account/services/front/mappers.ts
index ba545a04d..c467955c8 100644
--- a/packages/api/src/ticketing/account/services/front/mappers.ts
+++ b/packages/api/src/ticketing/account/services/front/mappers.ts
@@ -63,6 +63,7 @@ export class FrontAccountMapper implements IAccountMapper {
name: account.name,
domains: account.domains.flat(),
field_mappings: field_mappings,
+ remote_data: account
};
return unifiedAccount;
diff --git a/packages/api/src/ticketing/account/services/zendesk/mappers.ts b/packages/api/src/ticketing/account/services/zendesk/mappers.ts
index d4e128d80..5f40bfd32 100644
--- a/packages/api/src/ticketing/account/services/zendesk/mappers.ts
+++ b/packages/api/src/ticketing/account/services/zendesk/mappers.ts
@@ -60,6 +60,7 @@ export class ZendeskAccountMapper implements IAccountMapper {
remote_id: String(account.id),
name: account.name,
domains: account.domain_names,
+ remote_data: account
};
return unifiedAccount;
From cc1f8ef6ffd0a566d642ba4f67821c5bdd104931 Mon Sep 17 00:00:00 2001
From: mit-27
Date: Mon, 26 Aug 2024 01:31:26 -0600
Subject: [PATCH 19/49] =?UTF-8?q?=E2=9C=A8=20Add=20Microsoft=20Dynamics=20?=
=?UTF-8?q?365=20Sales=20CRM=20{Company,=20Contact,=20Deal,=20Note,=20Task?=
=?UTF-8?q?,=20User}=20objects?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
packages/api/scripts/init.sql | 3 +-
packages/api/scripts/seed.sql | 8 +-
.../utils/types/original/original.crm.ts | 36 +-
.../api/src/crm/company/company.module.ts | 4 +
.../services/microsoftdynamicssales/index.ts | 97 ++++++
.../microsoftdynamicssales/mappers.ts | 309 ++++++++++++++++++
.../services/microsoftdynamicssales/types.ts | 153 +++++++++
.../api/src/crm/contact/contact.module.ts | 4 +
.../services/microsoftdynamicssales/index.ts | 99 ++++++
.../microsoftdynamicssales/mappers.ts | 235 +++++++++++++
.../services/microsoftdynamicssales/types.ts | 228 +++++++++++++
packages/api/src/crm/deal/deal.module.ts | 4 +
.../services/microsoftdynamicssales/index.ts | 96 ++++++
.../microsoftdynamicssales/mappers.ts | 130 ++++++++
.../services/microsoftdynamicssales/types.ts | 125 +++++++
packages/api/src/crm/note/note.module.ts | 4 +
.../services/microsoftdynamicssales/index.ts | 93 ++++++
.../microsoftdynamicssales/mappers.ts | 151 +++++++++
.../services/microsoftdynamicssales/types.ts | 32 ++
.../services/microsoftdynamicssales/index.ts | 94 ++++++
.../microsoftdynamicssales/mappers.ts | 165 ++++++++++
.../services/microsoftdynamicssales/types.ts | 70 ++++
packages/api/src/crm/task/task.module.ts | 4 +
.../services/microsoftdynamicssales/index.ts | 67 ++++
.../microsoftdynamicssales/mappers.ts | 71 ++++
.../services/microsoftdynamicssales/types.ts | 123 +++++++
packages/api/src/crm/user/user.module.ts | 4 +
packages/shared/src/authUrl.ts | 4 +-
packages/shared/src/connectors/enum.ts | 3 +-
packages/shared/src/connectors/index.ts | 2 +-
packages/shared/src/connectors/metadata.ts | 2 +-
31 files changed, 2398 insertions(+), 22 deletions(-)
create mode 100644 packages/api/src/crm/company/services/microsoftdynamicssales/index.ts
create mode 100644 packages/api/src/crm/company/services/microsoftdynamicssales/mappers.ts
create mode 100644 packages/api/src/crm/company/services/microsoftdynamicssales/types.ts
create mode 100644 packages/api/src/crm/contact/services/microsoftdynamicssales/index.ts
create mode 100644 packages/api/src/crm/contact/services/microsoftdynamicssales/mappers.ts
create mode 100644 packages/api/src/crm/contact/services/microsoftdynamicssales/types.ts
create mode 100644 packages/api/src/crm/deal/services/microsoftdynamicssales/index.ts
create mode 100644 packages/api/src/crm/deal/services/microsoftdynamicssales/mappers.ts
create mode 100644 packages/api/src/crm/deal/services/microsoftdynamicssales/types.ts
create mode 100644 packages/api/src/crm/note/services/microsoftdynamicssales/index.ts
create mode 100644 packages/api/src/crm/note/services/microsoftdynamicssales/mappers.ts
create mode 100644 packages/api/src/crm/note/services/microsoftdynamicssales/types.ts
create mode 100644 packages/api/src/crm/task/services/microsoftdynamicssales/index.ts
create mode 100644 packages/api/src/crm/task/services/microsoftdynamicssales/mappers.ts
create mode 100644 packages/api/src/crm/task/services/microsoftdynamicssales/types.ts
create mode 100644 packages/api/src/crm/user/services/microsoftdynamicssales/index.ts
create mode 100644 packages/api/src/crm/user/services/microsoftdynamicssales/mappers.ts
create mode 100644 packages/api/src/crm/user/services/microsoftdynamicssales/types.ts
diff --git a/packages/api/scripts/init.sql b/packages/api/scripts/init.sql
index 71a8c80ec..4aa51a322 100644
--- a/packages/api/scripts/init.sql
+++ b/packages/api/scripts/init.sql
@@ -549,7 +549,8 @@ CREATE TABLE connector_sets
ecom_amazon boolean NULL,
ecom_squarespace boolean NULL,
ats_ashby boolean NULL,
- CONSTRAINT PK_project_connector PRIMARY KEY ( id_connector_set )
+ crm_microsoftdynamicssales boolean NULL,
+CONSTRAINT PK_project_connector PRIMARY KEY ( id_connector_set )
);
diff --git a/packages/api/scripts/seed.sql b/packages/api/scripts/seed.sql
index 233841fa2..9acc8bff4 100644
--- a/packages/api/scripts/seed.sql
+++ b/packages/api/scripts/seed.sql
@@ -1,10 +1,10 @@
INSERT INTO users (id_user, identification_strategy, email, password_hash, first_name, last_name) VALUES
('0ce39030-2901-4c56-8db0-5e326182ec6b', 'b2c','local@panora.dev', '$2b$10$Y7Q8TWGyGuc5ecdIASbBsuXMo3q/Rs3/cnY.mLZP4tUgfGUOCUBlG', 'local', 'Panora');
-INSERT INTO connector_sets (id_connector_set, crm_hubspot, crm_zoho, crm_pipedrive, crm_attio, crm_zendesk, crm_close, tcg_zendesk, tcg_gorgias, tcg_front, tcg_jira, tcg_gitlab, fs_box, tcg_github, hris_deel, hris_sage, ats_ashby) VALUES
- ('1709da40-17f7-4d3a-93a0-96dc5da6ddd7', TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE),
- ('852dfff8-ab63-4530-ae49-e4b2924407f8', TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE),
- ('aed0f856-f802-4a79-8640-66d441581a99', TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE);
+INSERT INTO connector_sets (id_connector_set, crm_hubspot, crm_zoho, crm_pipedrive, crm_attio, crm_zendesk, crm_close, tcg_zendesk, tcg_gorgias, tcg_front, tcg_jira, tcg_gitlab, fs_box, tcg_github, hris_deel, hris_sage, ats_ashby, crm_microsoftdynamicssales) VALUES
+ ('1709da40-17f7-4d3a-93a0-96dc5da6ddd7', TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE),
+ ('852dfff8-ab63-4530-ae49-e4b2924407f8', TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE),
+ ('aed0f856-f802-4a79-8640-66d441581a99', TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE);
INSERT INTO projects (id_project, name, sync_mode, id_user, id_connector_set) VALUES
('1e468c15-aa57-4448-aa2b-7fed640d1e3d', 'Project 1', 'pull', '0ce39030-2901-4c56-8db0-5e326182ec6b', '1709da40-17f7-4d3a-93a0-96dc5da6ddd7'),
diff --git a/packages/api/src/@core/utils/types/original/original.crm.ts b/packages/api/src/@core/utils/types/original/original.crm.ts
index aaeae0263..2e64529d6 100644
--- a/packages/api/src/@core/utils/types/original/original.crm.ts
+++ b/packages/api/src/@core/utils/types/original/original.crm.ts
@@ -1,3 +1,15 @@
+import { MicrosoftdynamicssalesTaskInput, MicrosoftdynamicssalesTaskOutput } from '@crm/task/services/microsoftdynamicssales/types';
+
+import { MicrosoftdynamicssalesNoteInput, MicrosoftdynamicssalesNoteOutput } from '@crm/note/services/microsoftdynamicssales/types';
+
+import { MicrosoftdynamicssalesDealInput, MicrosoftdynamicssalesDealOutput } from '@crm/deal/services/microsoftdynamicssales/types';
+
+import { MicrosoftdynamicssalesContactInput, MicrosoftdynamicssalesContactOutput } from '@crm/contact/services/microsoftdynamicssales/types';
+
+import { MicrosoftdynamicssalesCompanyInput, MicrosoftdynamicssalesCompanyOutput } from '@crm/company/services/microsoftdynamicssales/types';
+
+import { MicrosoftdynamicssalesUserInput, MicrosoftdynamicssalesUserOutput } from '@crm/user/services/microsoftdynamicssales/types';
+
import { AttioCompanyOutput } from '@crm/company/services/attio/types';
import { HubspotCompanyOutput } from '@crm/company/services/hubspot/types';
import { PipedriveCompanyOutput } from '@crm/company/services/pipedrive/types';
@@ -148,7 +160,7 @@ export type OriginalContactInput =
| ZendeskContactInput
| PipedriveContactInput
| AttioContactInput
- | CloseContactInput;
+ | CloseContactInput | MicrosoftdynamicssalesContactInput;
/* deal */
export type OriginalDealInput =
@@ -157,7 +169,7 @@ export type OriginalDealInput =
| ZendeskDealOutput
| PipedriveDealOutput
| CloseDealOutput
- | AttioDealInput;
+ | AttioDealInput | MicrosoftdynamicssalesDealInput;
/* company */
export type OriginalCompanyInput =
@@ -166,7 +178,7 @@ export type OriginalCompanyInput =
| ZendeskCompanyOutput
| PipedriveCompanyOutput
| AttioCompanyOutput
- | CloseCompanyOutput;
+ | CloseCompanyOutput | MicrosoftdynamicssalesCompanyInput;
/* engagement */
export type OriginalEngagementInput =
@@ -183,7 +195,7 @@ export type OriginalNoteInput =
| ZendeskNoteInput
| PipedriveNoteInput
| CloseNoteInput
- | AttioNoteInput;
+ | AttioNoteInput | MicrosoftdynamicssalesNoteInput;
/* task */
export type OriginalTaskInput =
@@ -192,7 +204,7 @@ export type OriginalTaskInput =
| ZendeskTaskInput
| PipedriveTaskInput
| CloseTaskInput
- | AttioTaskInput;
+ | AttioTaskInput | MicrosoftdynamicssalesTaskInput;
/* stage */
export type OriginalStageInput =
@@ -210,7 +222,7 @@ export type OriginalUserInput =
| ZohoUserInput
| ZendeskUserInput
| PipedriveUserInput
- | CloseUserOutput;
+ | CloseUserOutput | MicrosoftdynamicssalesUserInput;
export type CrmObjectInput =
| OriginalContactInput
@@ -230,7 +242,7 @@ export type OriginalContactOutput =
| ZendeskContactOutput
| PipedriveContactOutput
| AttioContactOutput
- | CloseContactOutput;
+ | CloseContactOutput | MicrosoftdynamicssalesContactOutput;
/* deal */
export type OriginalDealOutput =
@@ -239,7 +251,7 @@ export type OriginalDealOutput =
| ZendeskDealOutput
| PipedriveDealOutput
| CloseDealOutput
- | AttioDealOutput;
+ | AttioDealOutput | MicrosoftdynamicssalesDealOutput;
/* company */
export type OriginalCompanyOutput =
@@ -248,7 +260,7 @@ export type OriginalCompanyOutput =
| ZendeskCompanyOutput
| PipedriveCompanyOutput
| AttioCompanyOutput
- | CloseCompanyOutput;
+ | CloseCompanyOutput | MicrosoftdynamicssalesCompanyOutput;
/* engagement */
export type OriginalEngagementOutput =
@@ -265,7 +277,7 @@ export type OriginalNoteOutput =
| ZendeskNoteOutput
| PipedriveNoteOutput
| CloseNoteOutput
- | AttioNoteOutput;
+ | AttioNoteOutput | MicrosoftdynamicssalesNoteOutput;
/* task */
export type OriginalTaskOutput =
@@ -274,7 +286,7 @@ export type OriginalTaskOutput =
| ZendeskTaskOutput
| PipedriveTaskOutput
| CloseTaskOutput
- | AttioTaskOutput;
+ | AttioTaskOutput | MicrosoftdynamicssalesTaskOutput;
/* stage */
export type OriginalStageOutput =
@@ -293,7 +305,7 @@ export type OriginalUserOutput =
| ZendeskUserOutput
| PipedriveUserOutput
| CloseUserInput
- | AttioUserOutput;
+ | AttioUserOutput | MicrosoftdynamicssalesUserOutput;
export type CrmObjectOutput =
| OriginalContactOutput
diff --git a/packages/api/src/crm/company/company.module.ts b/packages/api/src/crm/company/company.module.ts
index a77852e29..e822f855d 100644
--- a/packages/api/src/crm/company/company.module.ts
+++ b/packages/api/src/crm/company/company.module.ts
@@ -1,3 +1,5 @@
+import { MicrosoftdynamicssalesCompanyMapper } from './services/microsoftdynamicssales/mappers';
+import { MicrosoftdynamicssalesService } from './services/microsoftdynamicssales';
import { EncryptionService } from '@@core/@core-services/encryption/encryption.service';
import { LoggerService } from '@@core/@core-services/logger/logger.service';
import { BullQueueModule } from '@@core/@core-services/queues/queue.module';
@@ -52,6 +54,8 @@ import { SyncService } from './sync/sync.service';
PipedriveCompanyMapper,
ZendeskCompanyMapper,
ZohoCompanyMapper,
+ MicrosoftdynamicssalesService,
+ MicrosoftdynamicssalesCompanyMapper,
],
exports: [SyncService, ServiceRegistry, WebhookService],
})
diff --git a/packages/api/src/crm/company/services/microsoftdynamicssales/index.ts b/packages/api/src/crm/company/services/microsoftdynamicssales/index.ts
new file mode 100644
index 000000000..b04664a29
--- /dev/null
+++ b/packages/api/src/crm/company/services/microsoftdynamicssales/index.ts
@@ -0,0 +1,97 @@
+/* eslint-disable @typescript-eslint/no-unused-vars */
+import { Injectable } from '@nestjs/common';
+import axios from 'axios';
+import { CrmObject } from '@crm/@lib/@types';
+import { PrismaService } from '@@core/@core-services/prisma/prisma.service';
+import { LoggerService } from '@@core/@core-services/logger/logger.service';
+import { ActionType, handle3rdPartyServiceError } from '@@core/utils/errors';
+import { EncryptionService } from '@@core/@core-services/encryption/encryption.service';
+import { ApiResponse } from '@@core/utils/types';
+import { ICompanyService } from '@crm/company/types';
+import { ServiceRegistry } from '../registry.service';
+import { MicrosoftdynamicssalesCompanyInput, MicrosoftdynamicssalesCompanyOutput } from './types';
+import { SyncParam } from '@@core/utils/types/interface';
+import { OriginalCompanyOutput } from '@@core/utils/types/original/original.crm';
+
+@Injectable()
+export class MicrosoftdynamicssalesService implements ICompanyService {
+ constructor(
+ private prisma: PrismaService,
+ private logger: LoggerService,
+ private cryptoService: EncryptionService,
+ private registry: ServiceRegistry,
+ ) {
+ this.logger.setContext(
+ CrmObject.company.toUpperCase() + ':' + MicrosoftdynamicssalesService.name,
+ );
+ this.registry.registerService('microsoftdynamicssales', this);
+ }
+ async addCompany(
+ companyData: MicrosoftdynamicssalesCompanyInput,
+ linkedUserId: string,
+ ): Promise> {
+ try {
+ const connection = await this.prisma.connections.findFirst({
+ where: {
+ id_linked_user: linkedUserId,
+ provider_slug: 'microsoftdynamicssales',
+ vertical: 'crm',
+ },
+ });
+
+ const resp = await axios.post(
+ `${connection.account_url}/api/data/v9.2/accounts`,
+ JSON.stringify({
+ data: companyData,
+ }),
+ {
+ headers: {
+ Authorization: `Bearer ${this.cryptoService.decrypt(
+ connection.access_token,
+ )}`,
+ 'Content-Type': 'application/json',
+ },
+ },
+ );
+ return {
+ data: resp.data.value,
+ message: 'Microsoftdynamicssales company created',
+ statusCode: 201,
+ };
+ } catch (error) {
+ throw error;
+ }
+ }
+
+ async sync(data: SyncParam): Promise> {
+ try {
+ const { linkedUserId } = data;
+
+ const connection = await this.prisma.connections.findFirst({
+ where: {
+ id_linked_user: linkedUserId,
+ provider_slug: 'microsoftdynamicssales',
+ vertical: 'crm',
+ },
+ });
+ const resp = await axios.get(
+ `${connection.account_url}/api/data/v9.2/accounts`,
+ {
+ headers: {
+ 'Content-Type': 'application/json',
+ Authorization: `Bearer ${this.cryptoService.decrypt(
+ connection.access_token,
+ )}`,
+ },
+ },
+ );
+ return {
+ data: resp.data.value,
+ message: 'Microsoftdynamicssales companies retrieved',
+ statusCode: 200,
+ };
+ } catch (error) {
+ throw error;
+ }
+ }
+}
diff --git a/packages/api/src/crm/company/services/microsoftdynamicssales/mappers.ts b/packages/api/src/crm/company/services/microsoftdynamicssales/mappers.ts
new file mode 100644
index 000000000..3e4db043a
--- /dev/null
+++ b/packages/api/src/crm/company/services/microsoftdynamicssales/mappers.ts
@@ -0,0 +1,309 @@
+import { MicrosoftdynamicssalesCompanyInput, MicrosoftdynamicssalesCompanyOutput } from './types';
+import {
+ UnifiedCrmCompanyInput,
+ UnifiedCrmCompanyOutput,
+} from '@crm/company/types/model.unified';
+import { ICompanyMapper } from '@crm/company/types';
+import { Utils } from '@crm/@lib/@utils';
+import { Injectable } from '@nestjs/common';
+import { MappersRegistry } from '@@core/@core-services/registries/mappers.registry';
+import { getCountryCode, getCountryName } from '@@core/utils/types';
+
+@Injectable()
+export class MicrosoftdynamicssalesCompanyMapper implements ICompanyMapper {
+ constructor(private mappersRegistry: MappersRegistry, private utils: Utils) {
+ this.mappersRegistry.registerService('crm', 'company', 'microsoftdynamicssales', this);
+ }
+ async desunify(
+ source: UnifiedCrmCompanyInput,
+ customFieldMappings?: {
+ slug: string;
+ remote_id: string;
+ }[],
+ ): Promise {
+ const result: MicrosoftdynamicssalesCompanyInput = {
+ name: source.name,
+ }
+
+ const industryToCodeJSON = {
+ "accounting": 1,
+ "agriculture and non-petrol natural resource extraction": 2,
+ "broadcasting printing and publishing": 3,
+ "brokers": 4,
+ "building supply retail": 5,
+ "business services": 6,
+ "consulting": 7,
+ "consumer services": 8,
+ "design, direction and creative management": 9,
+ "distributors, dispatchers and processors": 10,
+ "doctor's offices and clinics": 11,
+ "durable manufacturing": 12,
+ "eating and drinking places": 13,
+ "entertainment retail": 14,
+ "equipment rental and leasing": 15,
+ "financial": 16,
+ "food and tobacco processing": 17,
+ "inbound capital intensive processing": 18,
+ "inbound repair and services": 19,
+ "insurance": 20,
+ "legal services": 21,
+ "non-durable merchandise retail": 22,
+ "outbound consumer service": 23,
+ "petrochemical extraction and distribution": 24,
+ "service retail": 25,
+ "sig affiliations": 26,
+ "social services": 27,
+ "special outbound trade contractors": 28,
+ "specialty realty": 29,
+ "transportation": 30,
+ "utility creation and distribution": 31,
+ "vehicle retail": 32,
+ "wholesale": 33
+ }
+
+ if (source.industry) {
+ result.industrycode = industryToCodeJSON[source.industry.toLowerCase()];
+ }
+
+ if (source.number_of_employees) {
+ result.numberofemployees = source.number_of_employees;
+ }
+
+ if (source.email_addresses[0]) {
+ result.emailaddress1 = source.email_addresses[0]?.email_address;
+ }
+ if (source.email_addresses[1]) {
+ result.emailaddress2 = source.email_addresses[1]?.email_address;
+ }
+ if (source.email_addresses[2]) {
+ result.emailaddress2 = source.email_addresses[2]?.email_address;
+ }
+ if (source.addresses[0]) {
+ result.address1_line1 = source.addresses[0].street_1;
+ result.address1_city = source.addresses[0].city;
+ result.address1_country = source.addresses[0].country;
+ result.address1_stateorprovince = source.addresses[0].state;
+ result.address1_postalcode = source.addresses[0].postal_code;
+ }
+ if (source.addresses[1]) {
+ result.address2_line1 = source.addresses[1].street_1;
+ result.address2_city = source.addresses[1].city;
+ result.address2_country = source.addresses[1].country;
+ result.address2_stateorprovince = source.addresses[1].state;
+ result.address2_postalcode = source.addresses[1].postal_code;
+ }
+
+ if (source.phone_numbers[0]) {
+ result.telephone1 = source.phone_numbers[0].phone_number;
+ }
+ if (source.phone_numbers[1]) {
+ result.telephone2 = source.phone_numbers[1].phone_number;
+ }
+ if (source.phone_numbers[2]) {
+ result.telephone3 = source.phone_numbers[2].phone_number;
+ }
+
+
+
+
+ // Cannot set read only property _createdby_value
+ // if (source.user_id) {
+ // const owner_id = await this.utils.getRemoteIdFromUserUuid(source.user_id);
+ // if (owner_id) {
+ // result._createdby_value = source.user_id;
+ // }
+ // }
+
+ // Microsoftdynamicssales company does not have attribute for email address
+ // Microsoftdynamicssales Company doest not have direct mapping of number of employees
+
+ if (customFieldMappings && source.field_mappings) {
+ for (const [k, v] of Object.entries(source.field_mappings)) {
+ const mapping = customFieldMappings.find(
+ (mapping) => mapping.slug === k,
+ );
+ if (mapping) {
+ result[mapping.remote_id] = v;
+ }
+ }
+ }
+
+ return result;
+ }
+
+ async unify(
+ source: MicrosoftdynamicssalesCompanyOutput | MicrosoftdynamicssalesCompanyOutput[],
+ connectionId: string,
+ customFieldMappings?: {
+ slug: string;
+ remote_id: string;
+ }[],
+ ): Promise {
+ if (!Array.isArray(source)) {
+ return this.mapSingleCompanyToUnified(
+ source,
+ connectionId,
+ customFieldMappings,
+ );
+ }
+ // Handling array of MicrosoftdynamicssalesCompanyOutput
+ return Promise.all(
+ source.map((company) =>
+ this.mapSingleCompanyToUnified(
+ company,
+ connectionId,
+ customFieldMappings,
+ ),
+ ),
+ );
+ }
+
+ private async mapSingleCompanyToUnified(
+ company: MicrosoftdynamicssalesCompanyOutput,
+ connectionId: string,
+ customFieldMappings?: {
+ slug: string;
+ remote_id: string;
+ }[],
+ ): Promise {
+ const field_mappings: { [key: string]: any } = {};
+ if (customFieldMappings) {
+ for (const mapping of customFieldMappings) {
+ field_mappings[mapping.slug] = company[mapping.remote_id];
+ }
+ }
+
+ let opts: any = {
+ addresses: [],
+ email_addresses: [],
+ phone_numbers: []
+ };
+
+ const industryJSON = {
+ 1: "Accounting",
+ 2: "Agriculture and Non-petrol Natural Resource Extraction",
+ 3: "Broadcasting Printing and Publishing",
+ 4: "Brokers",
+ 5: "Building Supply Retail",
+ 6: "Business Services",
+ 7: "Consulting",
+ 8: "Consumer Services",
+ 9: "Design, Direction and Creative Management",
+ 10: "Distributors, Dispatchers and Processors",
+ 11: "Doctor's Offices and Clinics",
+ 12: "Durable Manufacturing",
+ 13: "Eating and Drinking Places",
+ 14: "Entertainment Retail",
+ 15: "Equipment Rental and Leasing",
+ 16: "Financial",
+ 17: "Food and Tobacco Processing",
+ 18: "Inbound Capital Intensive Processing",
+ 19: "Inbound Repair and Services",
+ 20: "Insurance",
+ 21: "Legal Services",
+ 22: "Non-Durable Merchandise Retail",
+ 23: "Outbound Consumer Service",
+ 24: "Petrochemical Extraction and Distribution",
+ 25: "Service Retail",
+ 26: "SIG Affiliations",
+ 27: "Social Services",
+ 28: "Special Outbound Trade Contractors",
+ 29: "Specialty Realty",
+ 30: "Transportation",
+ 31: "Utility Creation and Distribution",
+ 32: "Vehicle Retail",
+ 33: "Wholesale"
+ }
+
+ let address: any = {};
+
+ if (company.address1_line1) {
+ address = {
+ street_1: company.address1_line1 ?? '',
+ city: company.address1_city ?? '',
+ state: company.address1_stateorprovince ?? '',
+ postal_code: company.address2_postalcode ?? '',
+ country: company.address1_country ?? '',
+ address_type: 'WORK',
+ owner_type: 'COMPANY',
+ }
+ opts.addresses.push(address);
+ }
+ if (company.address2_line1) {
+ address = {
+ street_1: company.address2_line1 ?? '',
+ city: company.address2_city ?? '',
+ state: company.address2_stateorprovince ?? '',
+ postal_code: company.address2_postalcode ?? '',
+ country: company.address2_country ?? '',
+ address_type: 'WORK',
+ owner_type: 'COMPANY',
+ }
+ opts.addresses.push(address);
+ }
+
+
+ if (company.emailaddress1) {
+ opts.email_addresses.push({
+ email_address: company.emailaddress1,
+ email_address_type: "WORK"
+ })
+ }
+ if (company.emailaddress2) {
+ opts.email_addresses.push({
+ email_address: company.emailaddress2,
+ email_address_type: "WORK"
+ })
+ }
+ if (company.emailaddress2) {
+ opts.email_addresses.push({
+ email_address: company.emailaddress3,
+ email_address_type: "WORK"
+ })
+ }
+ if (company.telephone1) {
+ opts.phone_numbers.push({
+ phone_number: company.telephone1,
+ phone_type: "MOBILE"
+ });
+ }
+ if (company.telephone2) {
+ opts.phone_numbers.push({
+ phone_number: company.telephone2,
+ phone_type: "MOBILE"
+ });
+ }
+ if (company.telephone3) {
+ opts.phone_numbers.push({
+ phone_number: company.telephone3,
+ phone_type: "MOBILE"
+ });
+ }
+
+
+
+ if (company._createdby_value) {
+ const owner_id = await this.utils.getUserUuidFromRemoteId(
+ company._createdby_value,
+ connectionId,
+ );
+ if (owner_id) {
+ opts = {
+ ...opts,
+ user_id: owner_id,
+ };
+ }
+ }
+
+ return {
+ remote_id: company.accountid,
+ remote_data: company,
+ name: company.name,
+ industry:
+ company.industrycode ? industryJSON[company.industrycode] : null,
+ number_of_employees: company.numberofemployees ?? null,
+ field_mappings,
+ ...opts,
+ };
+ }
+}
diff --git a/packages/api/src/crm/company/services/microsoftdynamicssales/types.ts b/packages/api/src/crm/company/services/microsoftdynamicssales/types.ts
new file mode 100644
index 000000000..96232c05f
--- /dev/null
+++ b/packages/api/src/crm/company/services/microsoftdynamicssales/types.ts
@@ -0,0 +1,153 @@
+interface MicrosoftdynamicssalesCompany {
+ accountcategorycode: number; // Edm.Int32
+ accountclassificationcode: number; // Edm.Int32
+ accountid: string; // Edm.Guid
+ accountnumber: string; // Edm.String
+ accountratingcode: number; // Edm.Int32
+ address1_addressid: string; // Edm.Guid
+ address1_addresstypecode: number; // Edm.Int32
+ address1_city: string; // Edm.String
+ address1_composite: string; // Edm.String
+ address1_country: string; // Edm.String
+ address1_county: string; // Edm.String
+ address1_fax: string; // Edm.String
+ address1_freighttermscode: number; // Edm.Int32
+ address1_latitude: number; // Edm.Double
+ address1_line1: string; // Edm.String
+ address1_line2: string; // Edm.String
+ address1_line3: string; // Edm.String
+ address1_longitude: number; // Edm.Double
+ address1_name: string; // Edm.String
+ address1_postalcode: string; // Edm.String
+ address1_postofficebox: string; // Edm.String
+ address1_primarycontactname: string; // Edm.String
+ address1_shippingmethodcode: number; // Edm.Int32
+ address1_stateorprovince: string; // Edm.String
+ address1_telephone1: string; // Edm.String
+ address1_telephone2: string; // Edm.String
+ address1_telephone3: string; // Edm.String
+ address1_upszone: string; // Edm.String
+ address1_utcoffset: number; // Edm.Int32
+ address2_addressid: string; // Edm.Guid
+ address2_addresstypecode: number; // Edm.Int32
+ address2_city: string; // Edm.String
+ address2_composite: string; // Edm.String
+ address2_country: string; // Edm.String
+ address2_county: string; // Edm.String
+ address2_fax: string; // Edm.String
+ address2_freighttermscode: number; // Edm.Int32
+ address2_latitude: number; // Edm.Double
+ address2_line1: string; // Edm.String
+ address2_line2: string; // Edm.String
+ address2_line3: string; // Edm.String
+ address2_longitude: number; // Edm.Double
+ address2_name: string; // Edm.String
+ address2_postalcode: string; // Edm.String
+ address2_postofficebox: string; // Edm.String
+ address2_primarycontactname: string; // Edm.String
+ address2_shippingmethodcode: number; // Edm.Int32
+ address2_stateorprovince: string; // Edm.String
+ address2_telephone1: string; // Edm.String
+ address2_telephone2: string; // Edm.String
+ address2_telephone3: string; // Edm.String
+ address2_upszone: string; // Edm.String
+ address2_utcoffset: number; // Edm.Int32
+ adx_createdbyipaddress: string; // Edm.String
+ adx_createdbyusername: string; // Edm.String
+ adx_modifiedbyipaddress: string; // Edm.String
+ adx_modifiedbyusername: string; // Edm.String
+ aging30: number; // Edm.Decimal
+ aging30_base: number; // Edm.Decimal
+ aging60: number; // Edm.Decimal
+ aging60_base: number; // Edm.Decimal
+ aging90: number; // Edm.Decimal
+ aging90_base: number; // Edm.Decimal
+ businesstypecode: number; // Edm.Int32
+ createdon: string; // Edm.DateTimeOffset
+ creditlimit: number; // Edm.Decimal
+ creditlimit_base: number; // Edm.Decimal
+ creditonhold: boolean; // Edm.Boolean
+ customersizecode: number; // Edm.Int32
+ customertypecode: number; // Edm.Int32
+ description: string; // Edm.String
+ donotbulkemail: boolean; // Edm.Boolean
+ donotbulkpostalmail: boolean; // Edm.Boolean
+ donotemail: boolean; // Edm.Boolean
+ donotfax: boolean; // Edm.Boolean
+ donotphone: boolean; // Edm.Boolean
+ donotpostalmail: boolean; // Edm.Boolean
+ donotsendmm: boolean; // Edm.Boolean
+ emailaddress1: string; // Edm.String
+ emailaddress2: string; // Edm.String
+ emailaddress3: string; // Edm.String
+ entityimage: Uint8Array; // Edm.Binary
+ entityimage_timestamp: number; // Edm.Int64
+ entityimage_url: string; // Edm.String
+ entityimageid: string; // Edm.Guid
+ exchangerate: number; // Edm.Decimal
+ fax: string; // Edm.String
+ followemail: boolean; // Edm.Boolean
+ ftpsiteurl: string; // Edm.String
+ importsequencenumber: number; // Edm.Int32
+ industrycode: number; // Edm.Int32
+ lastonholdtime: string; // Edm.DateTimeOffset
+ lastusedincampaign: string; // Edm.DateTimeOffset
+ marketcap: number; // Edm.Decimal
+ marketcap_base: number; // Edm.Decimal
+ marketingonly: boolean; // Edm.Boolean
+ merged: boolean; // Edm.Boolean
+ modifiedon: string; // Edm.DateTimeOffset
+ name: string; // Edm.String
+ numberofemployees: number; // Edm.Int32
+ onholdtime: number; // Edm.Int32
+ overriddencreatedon: string; // Edm.DateTimeOffset
+ ownershipcode: number; // Edm.Int32
+ participatesinworkflow: boolean; // Edm.Boolean
+ paymenttermscode: number; // Edm.Int32
+ preferredappointmentdaycode: number; // Edm.Int32
+ preferredappointmenttimecode: number; // Edm.Int32
+ preferredcontactmethodcode: number; // Edm.Int32
+ primarysatoriid: string; // Edm.String
+ primarytwitterid: string; // Edm.String
+ processid: string; // Edm.Guid
+ revenue: number; // Edm.Decimal
+ revenue_base: number; // Edm.Decimal
+ sharesoutstanding: number; // Edm.Int32
+ shippingmethodcode: number; // Edm.Int32
+ sic: string; // Edm.String
+ stageid: string; // Edm.Guid
+ statecode: number; // Edm.Int32
+ statuscode: number; // Edm.Int32
+ stockexchange: string; // Edm.String
+ telephone1: string; // Edm.String
+ telephone2: string; // Edm.String
+ telephone3: string; // Edm.String
+ territorycode: number; // Edm.Int32
+ tickersymbol: string; // Edm.String
+ timezoneruleversionnumber: number; // Edm.Int32
+ transactioncurrencyid: string; // Edm.Guid
+ traversedpath: string; // Edm.String
+ utcconversiontimezonecode: number; // Edm.Int32
+ versionnumber: number; // Edm.Int64
+ websiteurl: string; // Edm.String
+ yominame: string; // Edm.String
+ _createdby_value: string;
+ _createdonbehalfby_value: string;
+ _masterid_value: string;
+ _modifiedby_value: string;
+ _modifiedonbehalfby_value: string;
+ _msa_managingpartnerid_value: string;
+ _ownerid_value: string;
+ _owningbusinessunit_value: string;
+ _owningteam_value: string;
+ _owninguser_value: string;
+ _parentaccountid_value: string;
+ _preferredsystemuserid_value: string;
+ _primarycontactid_value: string;
+ _slaid_value: string;
+ _slainvokedid_value: string;
+ _transactioncurrencyid_value: string;
+}
+
+export type MicrosoftdynamicssalesCompanyInput = Partial;
+export type MicrosoftdynamicssalesCompanyOutput = MicrosoftdynamicssalesCompanyInput;
\ No newline at end of file
diff --git a/packages/api/src/crm/contact/contact.module.ts b/packages/api/src/crm/contact/contact.module.ts
index 9cda6805c..56e51789a 100644
--- a/packages/api/src/crm/contact/contact.module.ts
+++ b/packages/api/src/crm/contact/contact.module.ts
@@ -1,3 +1,5 @@
+import { MicrosoftdynamicssalesContactMapper } from './services/microsoftdynamicssales/mappers';
+import { MicrosoftdynamicssalesService } from './services/microsoftdynamicssales';
import { BullQueueModule } from '@@core/@core-services/queues/queue.module';
import { IngestDataService } from '@@core/@core-services/unification/ingest-data.service';
import { WebhookService } from '@@core/@core-services/webhooks/panora-webhooks/webhook.service';
@@ -45,6 +47,8 @@ import { SyncService } from './sync/sync.service';
PipedriveContactMapper,
ZendeskContactMapper,
ZohoContactMapper,
+ MicrosoftdynamicssalesService,
+ MicrosoftdynamicssalesContactMapper,
],
exports: [SyncService, ServiceRegistry, WebhookService],
})
diff --git a/packages/api/src/crm/contact/services/microsoftdynamicssales/index.ts b/packages/api/src/crm/contact/services/microsoftdynamicssales/index.ts
new file mode 100644
index 000000000..f585e6966
--- /dev/null
+++ b/packages/api/src/crm/contact/services/microsoftdynamicssales/index.ts
@@ -0,0 +1,99 @@
+import { Injectable } from '@nestjs/common';
+import { IContactService } from '@crm/contact/types';
+import { CrmObject } from '@crm/@lib/@types';
+import axios from 'axios';
+import { PrismaService } from '@@core/@core-services/prisma/prisma.service';
+import { LoggerService } from '@@core/@core-services/logger/logger.service';
+import { ActionType, handle3rdPartyServiceError } from '@@core/utils/errors';
+import { EncryptionService } from '@@core/@core-services/encryption/encryption.service';
+import { ApiResponse } from '@@core/utils/types';
+import { ServiceRegistry } from '../registry.service';
+import { MicrosoftdynamicssalesContactInput, MicrosoftdynamicssalesContactOutput } from './types';
+import { SyncParam } from '@@core/utils/types/interface';
+
+@Injectable()
+export class MicrosoftdynamicssalesService implements IContactService {
+ constructor(
+ private prisma: PrismaService,
+ private logger: LoggerService,
+ private cryptoService: EncryptionService,
+ private registry: ServiceRegistry,
+ ) {
+ this.logger.setContext(
+ CrmObject.contact.toUpperCase() + ':' + MicrosoftdynamicssalesService.name,
+ );
+ this.registry.registerService('microsoftdynamicssales', this);
+ }
+
+ async addContact(
+ contactData: MicrosoftdynamicssalesContactInput,
+ linkedUserId: string,
+ ): Promise> {
+ try {
+ const connection = await this.prisma.connections.findFirst({
+ where: {
+ id_linked_user: linkedUserId,
+ provider_slug: 'microsoftdynamicssales',
+ vertical: 'crm',
+ },
+ });
+
+ const resp = await axios.post(
+ `${connection.account_url}/api/data/v9.2/contacts`,
+ JSON.stringify({
+ data: contactData,
+ }),
+ {
+ headers: {
+ 'Content-Type': 'application/json',
+ Authorization: `Bearer ${this.cryptoService.decrypt(
+ connection.access_token,
+ )}`,
+ },
+ },
+ );
+ return {
+ data: resp.data.value,
+ message: 'microsoftdynamicssales contact created',
+ statusCode: 201,
+ };
+ } catch (error) {
+ throw error;
+ }
+ }
+
+ async sync(data: SyncParam): Promise> {
+ try {
+ const { linkedUserId } = data;
+
+ const connection = await this.prisma.connections.findFirst({
+ where: {
+ id_linked_user: linkedUserId,
+ provider_slug: 'microsoftdynamicssales',
+ vertical: 'crm',
+ },
+ });
+
+ const resp = await axios.get(
+ `${connection.account_url}/api/data/v9.2/contacts`,
+ {
+ headers: {
+ accept: 'application/json',
+ 'Content-Type': 'application/json',
+ Authorization: `Bearer ${this.cryptoService.decrypt(
+ connection.access_token,
+ )}`,
+ },
+ },
+ );
+
+ return {
+ data: resp.data.value,
+ message: 'Microsoftdynamicssales contacts retrieved',
+ statusCode: 200,
+ };
+ } catch (error) {
+ throw error;
+ }
+ }
+}
diff --git a/packages/api/src/crm/contact/services/microsoftdynamicssales/mappers.ts b/packages/api/src/crm/contact/services/microsoftdynamicssales/mappers.ts
new file mode 100644
index 000000000..d9c8acdce
--- /dev/null
+++ b/packages/api/src/crm/contact/services/microsoftdynamicssales/mappers.ts
@@ -0,0 +1,235 @@
+import {
+ UnifiedCrmContactInput,
+ UnifiedCrmContactOutput,
+} from '@crm/contact/types/model.unified';
+import { IContactMapper } from '@crm/contact/types';
+import { MicrosoftdynamicssalesContactInput, MicrosoftdynamicssalesContactOutput } from './types';
+import { Utils } from '@crm/@lib/@utils';
+import { Injectable } from '@nestjs/common';
+import { MappersRegistry } from '@@core/@core-services/registries/mappers.registry';
+
+@Injectable()
+export class MicrosoftdynamicssalesContactMapper implements IContactMapper {
+ constructor(private mappersRegistry: MappersRegistry, private utils: Utils) {
+ this.mappersRegistry.registerService('crm', 'contact', 'microsoftdynamicssales', this);
+ }
+
+ async desunify(
+ source: UnifiedCrmContactInput,
+ customFieldMappings?: {
+ slug: string;
+ remote_id: string;
+ }[],
+ ): Promise {
+
+
+ const result: MicrosoftdynamicssalesContactInput = {
+ firstname: source.first_name,
+ lastname: source.last_name,
+ fullname: `${source.first_name} ${source.last_name}`,
+ };
+ if (source.email_addresses[0]) {
+ result.emailaddress1 = source.email_addresses[0]?.email_address;
+ }
+ if (source.email_addresses[1]) {
+ result.emailaddress2 = source.email_addresses[1]?.email_address;
+ }
+ if (source.email_addresses[2]) {
+ result.emailaddress2 = source.email_addresses[2]?.email_address;
+ }
+ if (source.addresses[0]) {
+ result.address1_line1 = source.addresses[0].street_1;
+ result.address1_city = source.addresses[0].city;
+ result.address1_country = source.addresses[0].country;
+ result.address1_stateorprovince = source.addresses[0].state;
+ result.address1_postalcode = source.addresses[0].postal_code;
+ }
+ if (source.addresses[1]) {
+ result.address2_line1 = source.addresses[1].street_1;
+ result.address2_city = source.addresses[1].city;
+ result.address2_country = source.addresses[1].country;
+ result.address2_stateorprovince = source.addresses[1].state;
+ result.address2_postalcode = source.addresses[1].postal_code;
+ }
+ if (source.addresses[2]) {
+ result.address3_line1 = source.addresses[2].street_1;
+ result.address3_city = source.addresses[2].city;
+ result.address3_country = source.addresses[2].country;
+ result.address3_stateorprovince = source.addresses[2].state;
+ result.address3_postalcode = source.addresses[2].postal_code;
+ }
+
+ if (source.phone_numbers[0]) {
+ result.telephone1 = source.phone_numbers[0].phone_number;
+ }
+ if (source.phone_numbers[1]) {
+ result.telephone2 = source.phone_numbers[1].phone_number;
+ }
+ if (source.phone_numbers[2]) {
+ result.telephone3 = source.phone_numbers[2].phone_number;
+ }
+
+
+
+
+ if (customFieldMappings && source.field_mappings) {
+ for (const [k, v] of Object.entries(source.field_mappings)) {
+ const mapping = customFieldMappings.find(
+ (mapping) => mapping.slug === k,
+ );
+ if (mapping) {
+ result[mapping.remote_id] = v;
+ }
+ }
+ }
+ return result;
+ }
+
+ async unify(
+ source: MicrosoftdynamicssalesContactOutput | MicrosoftdynamicssalesContactOutput[],
+ connectionId: string,
+ customFieldMappings?: {
+ slug: string;
+ remote_id: string;
+ }[],
+ ): Promise {
+ if (!Array.isArray(source)) {
+ return await this.mapSingleContactToUnified(
+ source,
+ connectionId,
+ customFieldMappings,
+ );
+ }
+
+ // Handling array of HubspotContactOutput
+ return Promise.all(
+ source.map((contact) =>
+ this.mapSingleContactToUnified(
+ contact,
+ connectionId,
+ customFieldMappings,
+ ),
+ ),
+ );
+ }
+
+ private async mapSingleContactToUnified(
+ contact: MicrosoftdynamicssalesContactOutput,
+ connectionId: string,
+ customFieldMappings?: {
+ slug: string;
+ remote_id: string;
+ }[],
+ ): Promise {
+ const field_mappings: { [key: string]: any } = {};
+ if (customFieldMappings) {
+ for (const mapping of customFieldMappings) {
+ field_mappings[mapping.slug] = contact[mapping.remote_id];
+ }
+ }
+
+ let opts: any = {
+ addresses: [],
+ email_addresses: [],
+ phone_numbers: []
+ };
+
+ let address: any = {};
+
+ if (contact.address1_line1) {
+ address = {
+ street_1: contact.address1_line1 ?? '',
+ city: contact.address1_city ?? '',
+ state: contact.address1_stateorprovince ?? '',
+ postal_code: contact.address2_postalcode ?? '',
+ country: contact.address1_country ?? '',
+ address_type: 'PERSONAL',
+ owner_type: 'CONTACT',
+ }
+ opts.addresses.push(address);
+ }
+ if (contact.address2_line1) {
+ address = {
+ street_1: contact.address2_line1 ?? '',
+ city: contact.address2_city ?? '',
+ state: contact.address2_stateorprovince ?? '',
+ postal_code: contact.address2_postalcode ?? '',
+ country: contact.address2_country ?? '',
+ address_type: 'PERSONAL',
+ owner_type: 'CONTACT',
+ }
+ opts.addresses.push(address);
+ }
+ if (contact.address3_line1) {
+ address = {
+ street_1: contact.address3_line1 ?? '',
+ city: contact.address3_city ?? '',
+ state: contact.address3_stateorprovince ?? '',
+ postal_code: contact.address3_postalcode ?? '',
+ country: contact.address3_country ?? '',
+ address_type: 'PERSONAL',
+ owner_type: 'CONTACT',
+ }
+ opts.addresses.push(address);
+ }
+
+ if (contact.emailaddress1) {
+ opts.email_addresses.push({
+ email_address: contact.emailaddress1,
+ email_address_type: "PERSONAL"
+ })
+ }
+ if (contact.emailaddress2) {
+ opts.email_addresses.push({
+ email_address: contact.emailaddress2,
+ email_address_type: "PERSONAL"
+ })
+ }
+ if (contact.emailaddress2) {
+ opts.email_addresses.push({
+ email_address: contact.emailaddress3,
+ email_address_type: "PERSONAL"
+ })
+ }
+ if (contact.telephone1) {
+ opts.phone_numbers.push({
+ phone_number: contact.telephone1,
+ phone_type: "MOBILE"
+ });
+ }
+ if (contact.telephone2) {
+ opts.phone_numbers.push({
+ phone_number: contact.telephone2,
+ phone_type: "MOBILE"
+ });
+ }
+ if (contact.telephone3) {
+ opts.phone_numbers.push({
+ phone_number: contact.telephone3,
+ phone_type: "MOBILE"
+ });
+ }
+
+ if (contact._createdby_value) {
+ const owner_id = await this.utils.getUserUuidFromRemoteId(
+ contact._createdby_value,
+ connectionId,
+ );
+ if (owner_id) {
+ opts = {
+ ...opts,
+ user_id: owner_id,
+ };
+ }
+ }
+
+ return {
+ remote_id: contact.contactid,
+ remote_data: contact,
+ first_name: contact.firstname ?? '',
+ last_name: contact.lastname ?? '',
+ field_mappings,
+ ...opts,
+ };
+ }
+}
diff --git a/packages/api/src/crm/contact/services/microsoftdynamicssales/types.ts b/packages/api/src/crm/contact/services/microsoftdynamicssales/types.ts
new file mode 100644
index 000000000..9bb1a30f9
--- /dev/null
+++ b/packages/api/src/crm/contact/services/microsoftdynamicssales/types.ts
@@ -0,0 +1,228 @@
+interface MicrosoftdynamicssalesContact {
+ accountrolecode: number;
+ address1_addressid: string;
+ address1_addresstypecode: number;
+ address1_city: string;
+ address1_composite: string;
+ address1_country: string;
+ address1_county: string;
+ address1_fax: string;
+ address1_freighttermscode: number;
+ address1_latitude: number;
+ address1_line1: string;
+ address1_line2: string;
+ address1_line3: string;
+ address1_longitude: number;
+ address1_name: string;
+ address1_postalcode: string;
+ address1_postofficebox: string;
+ address1_primarycontactname: string;
+ address1_shippingmethodcode: number;
+ address1_stateorprovince: string;
+ address1_telephone1: string;
+ address1_telephone2: string;
+ address1_telephone3: string;
+ address1_upszone: string;
+ address1_utcoffset: number;
+ address2_addressid: string;
+ address2_addresstypecode: number;
+ address2_city: string;
+ address2_composite: string;
+ address2_country: string;
+ address2_county: string;
+ address2_fax: string;
+ address2_freighttermscode: number;
+ address2_latitude: number;
+ address2_line1: string;
+ address2_line2: string;
+ address2_line3: string;
+ address2_longitude: number;
+ address2_name: string;
+ address2_postalcode: string;
+ address2_postofficebox: string;
+ address2_primarycontactname: string;
+ address2_shippingmethodcode: number;
+ address2_stateorprovince: string;
+ address2_telephone1: string;
+ address2_telephone2: string;
+ address2_telephone3: string;
+ address2_upszone: string;
+ address2_utcoffset: number;
+ address3_addressid: string;
+ address3_addresstypecode: number;
+ address3_city: string;
+ address3_composite: string;
+ address3_country: string;
+ address3_county: string;
+ address3_fax: string;
+ address3_freighttermscode: number;
+ address3_latitude: number;
+ address3_line1: string;
+ address3_line2: string;
+ address3_line3: string;
+ address3_longitude: number;
+ address3_name: string;
+ address3_postalcode: string;
+ address3_postofficebox: string;
+ address3_primarycontactname: string;
+ address3_shippingmethodcode: number;
+ address3_stateorprovince: string;
+ address3_telephone1: string;
+ address3_telephone2: string;
+ address3_telephone3: string;
+ address3_upszone: string;
+ address3_utcoffset: number;
+ adx_confirmremovepassword: boolean;
+ adx_createdbyipaddress: string;
+ adx_createdbyusername: string;
+ adx_identity_accessfailedcount: number;
+ adx_identity_emailaddress1confirmed: boolean;
+ adx_identity_lastsuccessfullogin: string;
+ adx_identity_locallogindisabled: boolean;
+ adx_identity_lockoutenabled: boolean;
+ adx_identity_lockoutenddate: string;
+ adx_identity_logonenabled: boolean;
+ adx_identity_mobilephoneconfirmed: boolean;
+ adx_identity_newpassword: string;
+ adx_identity_passwordhash: string;
+ adx_identity_securitystamp: string;
+ adx_identity_twofactorenabled: boolean;
+ adx_identity_username: string;
+ adx_modifiedbyipaddress: string;
+ adx_modifiedbyusername: string;
+ adx_organizationname: string;
+ adx_preferredlcid: number;
+ adx_profilealert: boolean;
+ adx_profilealertdate: string;
+ adx_profilealertinstructions: string;
+ adx_profileisanonymous: boolean;
+ adx_profilelastactivity: string;
+ adx_profilemodifiedon: string;
+ adx_publicprofilecopy: string;
+ adx_timezone: number;
+ aging30: number;
+ aging30_base: number;
+ aging60: number;
+ aging60_base: number;
+ aging90: number;
+ aging90_base: number;
+ anniversary: string;
+ annualincome: number;
+ annualincome_base: number;
+ assistantname: string;
+ assistantphone: string;
+ birthdate: string;
+ business2: string;
+ callback: string;
+ childrensnames: string;
+ company: string;
+ contactid: string;
+ createdon: string;
+ creditlimit: number;
+ creditlimit_base: number;
+ creditonhold: boolean;
+ customersizecode: number;
+ customertypecode: number;
+ department: string;
+ description: string;
+ donotbulkemail: boolean;
+ donotbulkpostalmail: boolean;
+ donotemail: boolean;
+ donotfax: boolean;
+ donotphone: boolean;
+ donotpostalmail: boolean;
+ donotsendmm: boolean;
+ educationcode: number;
+ emailaddress1: string;
+ emailaddress2: string;
+ emailaddress3: string;
+ employeeid: string;
+ entityimage: string;
+ entityimage_timestamp: number;
+ entityimage_url: string;
+ entityimageid: string;
+ exchangerate: number;
+ externaluseridentifier: string;
+ familystatuscode: number;
+ fax: string;
+ firstname: string;
+ followemail: boolean;
+ ftpsiteurl: string;
+ fullname: string;
+ gendercode: number;
+ governmentid: string;
+ haschildrencode: number;
+ home2: string;
+ importsequencenumber: number;
+ isbackofficecustomer: boolean;
+ jobtitle: string;
+ lastname: string;
+ lastonholdtime: string;
+ lastusedincampaign: string;
+ leadsourcecode: number;
+ managername: string;
+ managerphone: string;
+ marketingonly: boolean;
+ merged: boolean;
+ middlename: string;
+ mobilephone: string;
+ modifiedon: string;
+ msdyn_disablewebtracking: boolean;
+ msdyn_isminor: boolean;
+ msdyn_isminorwithparentalconsent: boolean;
+ msdyn_portaltermsagreementdate: string;
+ mspp_userpreferredlcid: number;
+ nickname: string;
+ numberofchildren: number;
+ onholdtime: number;
+ overriddencreatedon: string;
+ pager: string;
+ participatesinworkflow: boolean;
+ paymenttermscode: number;
+ preferredappointmentdaycode: number;
+ preferredappointmenttimecode: number;
+ preferredcontactmethodcode: number;
+ processid: string;
+ salutation: string;
+ shippingmethodcode: number;
+ spousesname: string;
+ stageid: string;
+ statecode: number;
+ statuscode: number;
+ subscriptionid: string;
+ suffix: string;
+ telephone1: string;
+ telephone2: string;
+ telephone3: string;
+ territorycode: number;
+ timespentbymeonemailandmeetings: string;
+ timezoneruleversionnumber: number;
+ traversedpath: string;
+ utcconversiontimezonecode: number;
+ versionnumber: number;
+ websiteurl: string;
+ yomifirstname: string;
+ yomifullname: string;
+ yomilastname: string;
+ yomimiddlename: string;
+ _createdby_value: string;
+ _createdonbehalfby_value: string;
+ _masterid_value: string;
+ _modifiedby_value: string;
+ _modifiedonbehalfby_value: string;
+ _msa_managingpartnerid_value: string;
+ _ownerid_value: string;
+ _owningbusinessunit_value: string;
+ _owningteam_value: string;
+ _owninguser_value: string;
+ _parentcustomerid_value: string;
+ _preferredsystemuserid_value: string;
+ _slaid_value: string;
+ _slainvokedid_value: string;
+ _transactioncurrencyid_value: string;
+
+
+}
+
+export type MicrosoftdynamicssalesContactInput = Partial;
+export type MicrosoftdynamicssalesContactOutput = MicrosoftdynamicssalesContactInput;
\ No newline at end of file
diff --git a/packages/api/src/crm/deal/deal.module.ts b/packages/api/src/crm/deal/deal.module.ts
index d27a59782..334d7367b 100644
--- a/packages/api/src/crm/deal/deal.module.ts
+++ b/packages/api/src/crm/deal/deal.module.ts
@@ -1,3 +1,5 @@
+import { MicrosoftdynamicssalesDealMapper } from './services/microsoftdynamicssales/mappers';
+import { MicrosoftdynamicssalesService } from './services/microsoftdynamicssales';
import { BullQueueModule } from '@@core/@core-services/queues/queue.module';
import { IngestDataService } from '@@core/@core-services/unification/ingest-data.service';
import { WebhookService } from '@@core/@core-services/webhooks/panora-webhooks/webhook.service';
@@ -43,6 +45,8 @@ import { SyncService } from './sync/sync.service';
HubspotDealMapper,
AttioDealMapper,
CloseDealMapper,
+ MicrosoftdynamicssalesService,
+ MicrosoftdynamicssalesDealMapper,
],
exports: [SyncService, ServiceRegistry, WebhookService],
})
diff --git a/packages/api/src/crm/deal/services/microsoftdynamicssales/index.ts b/packages/api/src/crm/deal/services/microsoftdynamicssales/index.ts
new file mode 100644
index 000000000..12979121b
--- /dev/null
+++ b/packages/api/src/crm/deal/services/microsoftdynamicssales/index.ts
@@ -0,0 +1,96 @@
+/* eslint-disable @typescript-eslint/no-unused-vars */
+import { Injectable } from '@nestjs/common';
+import axios from 'axios';
+import { CrmObject } from '@crm/@lib/@types';
+import { PrismaService } from '@@core/@core-services/prisma/prisma.service';
+import { LoggerService } from '@@core/@core-services/logger/logger.service';
+import { EncryptionService } from '@@core/@core-services/encryption/encryption.service';
+import { ApiResponse } from '@@core/utils/types';
+import { IDealService } from '@crm/deal/types';
+import { ServiceRegistry } from '../registry.service';
+import { MicrosoftdynamicssalesDealInput, MicrosoftdynamicssalesDealOutput } from './types';
+import { SyncParam } from '@@core/utils/types/interface';
+
+@Injectable()
+export class MicrosoftdynamicssalesService implements IDealService {
+ constructor(
+ private prisma: PrismaService,
+ private logger: LoggerService,
+ private cryptoService: EncryptionService,
+ private registry: ServiceRegistry,
+ ) {
+ this.logger.setContext(
+ CrmObject.deal.toUpperCase() + ':' + MicrosoftdynamicssalesService.name,
+ );
+ this.registry.registerService('microsoftdynamicssales', this);
+ }
+ async addDeal(
+ dealData: MicrosoftdynamicssalesDealInput,
+ linkedUserId: string,
+ ): Promise> {
+ try {
+ const connection = await this.prisma.connections.findFirst({
+ where: {
+ id_linked_user: linkedUserId,
+ provider_slug: 'microsoftdynamicssales',
+ vertical: 'crm',
+ },
+ });
+
+ const resp = await axios.post(
+ `${connection.account_url}/api/data/v9.2/opportunities`,
+ JSON.stringify({
+ data: dealData,
+ }),
+ {
+ headers: {
+ Authorization: `Bearer ${this.cryptoService.decrypt(
+ connection.access_token,
+ )}`,
+ 'Content-Type': 'application/json',
+ },
+ },
+ );
+ return {
+ data: resp.data.value,
+ message: 'Microsoftdynamicssales deal created',
+ statusCode: 201,
+ };
+ } catch (error) {
+ throw error;
+ }
+ }
+
+ async sync(data: SyncParam): Promise> {
+ try {
+ const { linkedUserId } = data;
+
+ const connection = await this.prisma.connections.findFirst({
+ where: {
+ id_linked_user: linkedUserId,
+ provider_slug: 'microsoftdynamicssales',
+ vertical: 'crm',
+ },
+ });
+ const resp = await axios.get(
+ `${connection.account_url}/api/data/v9.2/opportunities`,
+ {
+ headers: {
+ accept: 'application/json',
+ 'Content-Type': 'application/json',
+ Authorization: `Bearer ${this.cryptoService.decrypt(
+ connection.access_token,
+ )}`,
+ },
+ },
+ );
+ return {
+ data: resp.data.value,
+ message: 'Microsoftdynamicssales deals retrieved',
+ statusCode: 200,
+ };
+ } catch (error) {
+ throw error;
+ }
+ }
+}
diff --git a/packages/api/src/crm/deal/services/microsoftdynamicssales/mappers.ts b/packages/api/src/crm/deal/services/microsoftdynamicssales/mappers.ts
new file mode 100644
index 000000000..b8e64523d
--- /dev/null
+++ b/packages/api/src/crm/deal/services/microsoftdynamicssales/mappers.ts
@@ -0,0 +1,130 @@
+import { Injectable } from '@nestjs/common';
+import {
+ UnifiedCrmDealInput,
+ UnifiedCrmDealOutput,
+} from '@crm/deal/types/model.unified';
+import { IDealMapper } from '@crm/deal/types';
+import { Utils } from '@crm/@lib/@utils';
+import { MappersRegistry } from '@@core/@core-services/registries/mappers.registry';
+import { MicrosoftdynamicssalesDealInput, MicrosoftdynamicssalesDealOutput } from './types';
+
+@Injectable()
+export class MicrosoftdynamicssalesDealMapper implements IDealMapper {
+ constructor(private mappersRegistry: MappersRegistry, private utils: Utils) {
+ this.mappersRegistry.registerService('crm', 'deal', 'microsoftdynamicssales', this);
+ }
+
+ async desunify(
+ source: UnifiedCrmDealInput,
+ customFieldMappings?: {
+ slug: string;
+ remote_id: string;
+ }[],
+ ): Promise {
+ const result: MicrosoftdynamicssalesDealInput = {
+ name: source.name,
+ description: source.description,
+ totalamount: source.amount
+ }
+
+
+
+
+ if (source.company_id) {
+ const id = await this.utils.getRemoteIdFromCompanyUuid(source.company_id);
+ result["parentaccountid@odata.bind"] = `/accounts(${id})`;
+ }
+
+
+ if (customFieldMappings && source.field_mappings) {
+ for (const [k, v] of Object.entries(source.field_mappings)) {
+ const mapping = customFieldMappings.find(
+ (mapping) => mapping.slug === k,
+ );
+ if (mapping) {
+ result[mapping.remote_id] = v;
+ }
+ }
+ }
+
+ return result;
+ }
+
+ async unify(
+ source: MicrosoftdynamicssalesDealOutput | MicrosoftdynamicssalesDealOutput[],
+ connectionId: string,
+ customFieldMappings?: {
+ slug: string;
+ remote_id: string;
+ }[],
+ ): Promise {
+ if (!Array.isArray(source)) {
+ return await this.mapSingleDealToUnified(
+ source,
+ connectionId,
+ customFieldMappings,
+ );
+ }
+ // Handling array of MicrosoftdynamicssalesDealOutput
+ return Promise.all(
+ source.map((deal) =>
+ this.mapSingleDealToUnified(deal, connectionId, customFieldMappings),
+ ),
+ );
+ }
+
+ private async mapSingleDealToUnified(
+ deal: MicrosoftdynamicssalesDealOutput,
+ connectionId: string,
+ customFieldMappings?: {
+ slug: string;
+ remote_id: string;
+ }[],
+ ): Promise {
+ const field_mappings: { [key: string]: any } = {};
+ if (customFieldMappings) {
+ for (const mapping of customFieldMappings) {
+ field_mappings[mapping.slug] = deal[mapping.remote_id];
+ }
+ }
+
+ let opts: any = {};
+
+ if (deal._ownerid_value) {
+ const user_id = await this.utils.getUserUuidFromRemoteId(
+ deal._ownerid_value,
+ connectionId
+ );
+ if (user_id) {
+ opts = {
+ ...opts,
+ user_id: user_id
+ }
+ }
+ }
+
+ if (deal._accountid_value) {
+ const company_id = await this.utils.getCompanyUuidFromRemoteId(
+ deal._accountid_value,
+ connectionId
+ );
+ if (company_id) {
+ opts = {
+ ...opts,
+ company_id: company_id
+ }
+ }
+ }
+
+
+ return {
+ remote_id: deal.opportunityid,
+ remote_data: deal,
+ name: deal.name ?? '',
+ description: deal.description ?? '',
+ amount: deal.totalamount ?? 0,
+ field_mappings,
+ ...opts,
+ };
+ }
+}
diff --git a/packages/api/src/crm/deal/services/microsoftdynamicssales/types.ts b/packages/api/src/crm/deal/services/microsoftdynamicssales/types.ts
new file mode 100644
index 000000000..363c7ef79
--- /dev/null
+++ b/packages/api/src/crm/deal/services/microsoftdynamicssales/types.ts
@@ -0,0 +1,125 @@
+interface MicrosoftdynamicssalesDeal {
+ msdyn_opportunityscore: any,
+ totalamount_base: number,
+ pursuitdecision: boolean,
+ msdyn_scorehistory: any,
+ _msdyn_predictivescoreid_value: string,
+ actualvalue_base: any,
+ totallineitemdiscountamount: number,
+ totalamount: number,
+ identifypursuitteam: boolean,
+ statuscode: number,
+ msdyn_opportunityscoretrend: any,
+ totaldiscountamount_base: number,
+ _createdby_value: string,
+ name: string,
+ _owninguser_value: string,
+ _parentcontactid_value: string,
+ _msdyn_segmentid_value: any,
+ totaltax: number,
+ budgetstatus: any,
+ _accountid_value: any,
+ closeprobability: number,
+ finaldecisiondate: string,
+ _modifiedby_value: string,
+ _slainvokedid_value: any,
+ msdyn_similaropportunities: any,
+ msdyn_opportunitygrade: any,
+ quotecomments: any,
+ timeline: any,
+ qualificationcomments: any,
+ customerneed: string,
+ estimatedclosedate: string,
+ estimatedvalue: number,
+ identifycustomercontacts: boolean,
+ _contactid_value: any,
+ presentproposal: boolean,
+ captureproposalfeedback: boolean,
+ _campaignid_value: any,
+ estimatedvalue_base: number,
+ salesstagecode: number,
+ msdyn_forecastcategory: number,
+ stageid: any,
+ lastonholdtime: any,
+ need: any,
+ purchaseprocess: number,
+ sendthankyounote: boolean,
+ _parentaccountid_value: string,
+ totalamountlessfreight: number,
+ _modifiedonbehalfby_value: string,
+ _ownerid_value: string,
+ stepid: any,
+ developproposal: boolean,
+ freightamount_base: any,
+ description: string,
+ processid: any,
+ skippricecalculation: number,
+ discountamount_base: any,
+ onholdtime: any,
+ schedulefollowup_qualify: any,
+ importsequencenumber: any,
+ modifiedon: string,
+ totaltax_base: number,
+ opportunityratingcode: number,
+ utcconversiontimezonecode: any,
+ totallineitemdiscountamount_base: number,
+ salesstage: any,
+ discountamount: any,
+ traversedpath: any,
+ _createdonbehalfby_value: any,
+ _originatingleadid_value: any,
+ stepname: string,
+ customerpainpoints: any,
+ identifycompetitors: boolean,
+ emailaddress: string,
+ budgetamount: number,
+ msdyn_gdproptout: boolean,
+ totallineitemamount: number,
+ _owningteam_value: any,
+ _owningbusinessunit_value: string,
+ decisionmaker: boolean,
+ opportunityid: string,
+ totaldiscountamount: number,
+ evaluatefit: boolean,
+ _msdyn_opportunitykpiid_value: string,
+ proposedsolution: string,
+ scheduleproposalmeeting: any,
+ presentfinalproposal: boolean,
+ statecode: number,
+ isrevenuesystemcalculated: boolean,
+ participatesinworkflow: boolean,
+ exchangerate: number,
+ timespentbymeonemailandmeetings: any,
+ purchasetimeframe: number,
+ filedebrief: boolean,
+ teamsfollowed: any,
+ _customerid_value: string,
+ totalamountlessfreight_base: number,
+ _pricelevelid_value: string,
+ timezoneruleversionnumber: number,
+ overriddencreatedon: any,
+ prioritycode: number,
+ initialcommunication: any,
+ _transactioncurrencyid_value: string,
+ schedulefollowup_prospect: any,
+ currentsituation: string,
+ totallineitemamount_base: number,
+ msdyn_scorereasons: any,
+ budgetamount_base: number,
+ freightamount: any,
+ actualclosedate: any,
+ actualvalue: any,
+ discountpercentage: any,
+ confirminterest: boolean,
+ completeinternalreview: boolean,
+ completefinalproposal: boolean,
+ _slaid_value: any,
+ resolvefeedback: boolean,
+ createdon: string,
+ pricingerrorcode: number,
+ versionnumber: number,
+ [key: string]: any
+}
+
+export type MicrosoftdynamicssalesDealInput = Partial;
+export type MicrosoftdynamicssalesDealOutput = MicrosoftdynamicssalesDealInput;
\ No newline at end of file
diff --git a/packages/api/src/crm/note/note.module.ts b/packages/api/src/crm/note/note.module.ts
index 0191db40a..280f0f69e 100644
--- a/packages/api/src/crm/note/note.module.ts
+++ b/packages/api/src/crm/note/note.module.ts
@@ -1,3 +1,5 @@
+import { MicrosoftdynamicssalesNoteMapper } from './services/microsoftdynamicssales/mappers';
+import { MicrosoftdynamicssalesService } from './services/microsoftdynamicssales';
import { BullQueueModule } from '@@core/@core-services/queues/queue.module';
import { IngestDataService } from '@@core/@core-services/unification/ingest-data.service';
import { WebhookService } from '@@core/@core-services/webhooks/panora-webhooks/webhook.service';
@@ -42,6 +44,8 @@ import { SyncService } from './sync/sync.service';
AttioNoteMapper,
HubspotNoteMapper,
CloseNoteMapper,
+ MicrosoftdynamicssalesService,
+ MicrosoftdynamicssalesNoteMapper,
],
exports: [SyncService, ServiceRegistry, WebhookService],
})
diff --git a/packages/api/src/crm/note/services/microsoftdynamicssales/index.ts b/packages/api/src/crm/note/services/microsoftdynamicssales/index.ts
new file mode 100644
index 000000000..8a17ca8d7
--- /dev/null
+++ b/packages/api/src/crm/note/services/microsoftdynamicssales/index.ts
@@ -0,0 +1,93 @@
+import { EncryptionService } from '@@core/@core-services/encryption/encryption.service';
+import { LoggerService } from '@@core/@core-services/logger/logger.service';
+import { PrismaService } from '@@core/@core-services/prisma/prisma.service';
+import { ApiResponse } from '@@core/utils/types';
+import { SyncParam } from '@@core/utils/types/interface';
+import { CrmObject } from '@crm/@lib/@types';
+import { INoteService } from '@crm/note/types';
+import { Injectable } from '@nestjs/common';
+import axios from 'axios';
+import { ServiceRegistry } from '../registry.service';
+import { MicrosoftdynamicssalesNoteInput, MicrosoftdynamicssalesNoteOutput } from './types';
+
+@Injectable()
+export class MicrosoftdynamicssalesService implements INoteService {
+ constructor(
+ private prisma: PrismaService,
+ private logger: LoggerService,
+ private cryptoService: EncryptionService,
+ private registry: ServiceRegistry,
+ ) {
+ this.logger.setContext(
+ CrmObject.note.toUpperCase() + ':' + MicrosoftdynamicssalesService.name,
+ );
+ this.registry.registerService('microsoftdynamicssales', this);
+ }
+
+ async addNote(
+ noteData: MicrosoftdynamicssalesNoteInput,
+ linkedUserId: string,
+ ): Promise> {
+ try {
+ const connection = await this.prisma.connections.findFirst({
+ where: {
+ id_linked_user: linkedUserId,
+ provider_slug: 'microsoftdynamicssales',
+ vertical: 'crm',
+ },
+ });
+ const resp = await axios.post(
+ `${connection.account_url}/api/data/v9.2/annotations`,
+ JSON.stringify(noteData),
+ {
+ headers: {
+ 'Content-Type': 'application/json',
+ Authorization: `Bearer ${this.cryptoService.decrypt(
+ connection.access_token,
+ )}`,
+ },
+ },
+ );
+ return {
+ data: resp?.data.value,
+ message: 'Microsoftdynamicssales note created',
+ statusCode: 201,
+ };
+ } catch (error) {
+ throw error;
+ }
+ }
+
+ async sync(data: SyncParam): Promise> {
+ try {
+ const { linkedUserId } = data;
+
+ const connection = await this.prisma.connections.findFirst({
+ where: {
+ id_linked_user: linkedUserId,
+ provider_slug: 'microsoftdynamicssales',
+ vertical: 'crm',
+ },
+ });
+
+ const baseURL = `${connection.account_url}/api/data/v9.2/annotations`;
+
+ const resp = await axios.get(baseURL, {
+ headers: {
+ 'Content-Type': 'application/json',
+ Authorization: `Bearer ${this.cryptoService.decrypt(
+ connection.access_token,
+ )}`,
+ },
+ });
+ this.logger.log(`Synced microsoftdynamicssales notes !`);
+ return {
+ data: resp?.data?.value,
+ message: 'Microsoftdynamicssales notes retrieved',
+ statusCode: 200,
+ };
+ } catch (error) {
+ throw error;
+ }
+ }
+}
diff --git a/packages/api/src/crm/note/services/microsoftdynamicssales/mappers.ts b/packages/api/src/crm/note/services/microsoftdynamicssales/mappers.ts
new file mode 100644
index 000000000..6052d8f14
--- /dev/null
+++ b/packages/api/src/crm/note/services/microsoftdynamicssales/mappers.ts
@@ -0,0 +1,151 @@
+import { MicrosoftdynamicssalesNoteInput, MicrosoftdynamicssalesNoteOutput } from './types';
+import {
+ UnifiedCrmNoteInput,
+ UnifiedCrmNoteOutput,
+} from '@crm/note/types/model.unified';
+import { INoteMapper } from '@crm/note/types';
+import { Utils } from '@crm/@lib/@utils';
+import { MappersRegistry } from '@@core/@core-services/registries/mappers.registry';
+import { Injectable } from '@nestjs/common';
+
+@Injectable()
+export class MicrosoftdynamicssalesNoteMapper implements INoteMapper {
+ constructor(private mappersRegistry: MappersRegistry, private utils: Utils) {
+ this.mappersRegistry.registerService('crm', 'note', 'microsoftdynamicssales', this);
+ }
+ async desunify(
+ source: UnifiedCrmNoteInput,
+ customFieldMappings?: {
+ slug: string;
+ remote_id: string;
+ }[],
+ ): Promise {
+ //get the parent id of the object tied to the note
+ let opts: any = {};
+
+ if (source.company_id) {
+ const id = await this.utils.getRemoteIdFromCompanyUuid(source.company_id);
+ opts = {
+ ...opts,
+ "objectid_account@odata.bind": `/accounts(${id})`
+ }
+ }
+ if (source.contact_id) {
+ const id = await this.utils.getRemoteIdFromContactUuid(source.contact_id);
+ opts = {
+ ...opts,
+ "objectid_contact@odata.bind": `/contacts(${id})`
+ }
+ }
+
+ // Do not think there is option to add opportunity
+
+
+
+ const result: MicrosoftdynamicssalesNoteInput = {
+ notetext: source.content,
+ ...opts
+ };
+
+ return result;
+ }
+
+ async unify(
+ source: MicrosoftdynamicssalesNoteOutput | MicrosoftdynamicssalesNoteOutput[],
+ connectionId: string,
+ customFieldMappings?: {
+ slug: string;
+ remote_id: string;
+ }[],
+ ): Promise {
+ if (!Array.isArray(source)) {
+ return await this.mapSingleNoteToUnified(
+ source,
+ connectionId,
+ customFieldMappings,
+ );
+ }
+
+ return Promise.all(
+ source.map((note) =>
+ this.mapSingleNoteToUnified(note, connectionId, customFieldMappings),
+ ),
+ );
+ }
+
+ private async mapSingleNoteToUnified(
+ note: MicrosoftdynamicssalesNoteOutput,
+ connectionId: string,
+ customFieldMappings?: {
+ slug: string;
+ remote_id: string;
+ }[],
+ ): Promise {
+ const field_mappings: { [key: string]: any } = {};
+ if (customFieldMappings) {
+ for (const mapping of customFieldMappings) {
+ field_mappings[mapping.slug] = note[mapping.remote_id];
+ }
+ }
+
+ let opts: any = {};
+
+ if (note._ownerid_value) {
+ const user_id = await this.utils.getUserUuidFromRemoteId(
+ note._ownerid_value,
+ connectionId
+ );
+ if (user_id) {
+ opts = {
+ ...opts,
+ user_id: user_id
+ }
+ }
+ }
+
+ // This could only contain either contact, comapany or deal id
+ if (note._objectid_value) {
+ const company_id = await this.utils.getCompanyUuidFromRemoteId(
+ note._objectid_value,
+ connectionId
+ );
+ if (company_id) {
+ opts = {
+ ...opts,
+ company_id: company_id
+ }
+ }
+
+ const contact_id = await this.utils.getContactUuidFromRemoteId(
+ note._objectid_value,
+ connectionId
+ );
+ if (contact_id) {
+ opts = {
+ ...opts,
+ contact_id: contact_id
+ }
+ }
+
+ const deal_id = await this.utils.getDealUuidFromRemoteId(
+ note._objectid_value,
+ connectionId
+ );
+ if (deal_id) {
+ opts = {
+ ...opts,
+ deal_id: deal_id
+ }
+ }
+
+ }
+
+ return {
+ remote_id: note.annotationid,
+ remote_data: note,
+ content: note.notetext ?? '',
+ field_mappings,
+ ...opts,
+ };
+ }
+}
diff --git a/packages/api/src/crm/note/services/microsoftdynamicssales/types.ts b/packages/api/src/crm/note/services/microsoftdynamicssales/types.ts
new file mode 100644
index 000000000..fcdff526a
--- /dev/null
+++ b/packages/api/src/crm/note/services/microsoftdynamicssales/types.ts
@@ -0,0 +1,32 @@
+interface MicrosoftdynamicssalesNote {
+ annotationid: string;
+ createdon: string;
+ documentbody: string;
+ documentbody_binary: string;
+ filename: string;
+ filesize: number;
+ importsequencenumber: number;
+ isdocument: boolean;
+ langid: string;
+ mimetype: string;
+ modifiedon: string;
+ notetext: string;
+ objecttypecode: string;
+ overriddencreatedon: string;
+ prefix: string;
+ stepid: string;
+ subject: string;
+ versionnumber: number;
+ _createdby_value: string;
+ _createdonbehalfby_value: string;
+ _modifiedby_value: string;
+ _modifiedonbehalfby_value: string;
+ _objectid_value: string;
+ _ownerid_value: string;
+ _owningbusinessunit_value: string;
+ _owningteam_value: string;
+ _owninguser_value: string
+}
+
+export type MicrosoftdynamicssalesNoteInput = Partial;
+export type MicrosoftdynamicssalesNoteOutput = MicrosoftdynamicssalesNoteInput;
\ No newline at end of file
diff --git a/packages/api/src/crm/task/services/microsoftdynamicssales/index.ts b/packages/api/src/crm/task/services/microsoftdynamicssales/index.ts
new file mode 100644
index 000000000..b536fc781
--- /dev/null
+++ b/packages/api/src/crm/task/services/microsoftdynamicssales/index.ts
@@ -0,0 +1,94 @@
+import { EncryptionService } from '@@core/@core-services/encryption/encryption.service';
+import { LoggerService } from '@@core/@core-services/logger/logger.service';
+import { PrismaService } from '@@core/@core-services/prisma/prisma.service';
+import { ApiResponse } from '@@core/utils/types';
+import { SyncParam } from '@@core/utils/types/interface';
+import { CrmObject } from '@crm/@lib/@types';
+import { ITaskService } from '@crm/task/types';
+import { Injectable } from '@nestjs/common';
+import axios from 'axios';
+import { ServiceRegistry } from '../registry.service';
+import { MicrosoftdynamicssalesTaskInput, MicrosoftdynamicssalesTaskOutput } from './types';
+
+@Injectable()
+export class MicrosoftdynamicssalesService implements ITaskService {
+ constructor(
+ private prisma: PrismaService,
+ private logger: LoggerService,
+ private cryptoService: EncryptionService,
+ private registry: ServiceRegistry,
+ ) {
+ this.logger.setContext(
+ CrmObject.task.toUpperCase() + ':' + MicrosoftdynamicssalesService.name,
+ );
+ this.registry.registerService('microsoftdynamicssales', this);
+ }
+
+ async addTask(
+ taskData: MicrosoftdynamicssalesTaskInput,
+ linkedUserId: string,
+ ): Promise> {
+ try {
+ const connection = await this.prisma.connections.findFirst({
+ where: {
+ id_linked_user: linkedUserId,
+ provider_slug: 'microsoftdynamicssales',
+ vertical: 'crm',
+ },
+ });
+ const resp = await axios.post(
+ `${connection.account_url}/api/data/v9.2/tasks`,
+ JSON.stringify(taskData),
+ {
+ headers: {
+ 'Content-Type': 'application/json',
+ Authorization: `Bearer ${this.cryptoService.decrypt(
+ connection.access_token,
+ )}`,
+ },
+ },
+ );
+
+ return {
+ data: resp?.data?.value,
+ message: 'Microsoftdynamicssales task created',
+ statusCode: 201,
+ };
+ } catch (error) {
+ throw error;
+ }
+ }
+
+ async sync(data: SyncParam): Promise> {
+ try {
+ const { linkedUserId } = data;
+
+ const connection = await this.prisma.connections.findFirst({
+ where: {
+ id_linked_user: linkedUserId,
+ provider_slug: 'microsoftdynamicssales',
+ vertical: 'crm',
+ },
+ });
+
+ const baseURL = `${connection.account_url}/api/data/v9.2/tasks`;
+
+ const resp = await axios.get(baseURL, {
+ headers: {
+ 'Content-Type': 'application/json',
+ Authorization: `Bearer ${this.cryptoService.decrypt(
+ connection.access_token,
+ )}`,
+ },
+ });
+ this.logger.log(`Synced microsoftdynamicssales tasks !`);
+ return {
+ data: resp?.data?.value,
+ message: 'Microsoftdynamicssales tasks retrieved',
+ statusCode: 200,
+ };
+ } catch (error) {
+ throw error;
+ }
+ }
+}
diff --git a/packages/api/src/crm/task/services/microsoftdynamicssales/mappers.ts b/packages/api/src/crm/task/services/microsoftdynamicssales/mappers.ts
new file mode 100644
index 000000000..794a2e2fd
--- /dev/null
+++ b/packages/api/src/crm/task/services/microsoftdynamicssales/mappers.ts
@@ -0,0 +1,165 @@
+import { MicrosoftdynamicssalesTaskInput, MicrosoftdynamicssalesTaskOutput } from './types';
+import {
+ UnifiedCrmTaskInput,
+ UnifiedCrmTaskOutput,
+} from '@crm/task/types/model.unified';
+import { ITaskMapper } from '@crm/task/types';
+import { Utils } from '@crm/@lib/@utils';
+import { MappersRegistry } from '@@core/@core-services/registries/mappers.registry';
+import { Injectable } from '@nestjs/common';
+
+@Injectable()
+export class MicrosoftdynamicssalesTaskMapper implements ITaskMapper {
+ constructor(private mappersRegistry: MappersRegistry, private utils: Utils) {
+ this.mappersRegistry.registerService('crm', 'task', 'microsoftdynamicssales', this);
+ }
+
+ async desunify(
+ source: UnifiedCrmTaskInput,
+ customFieldMappings?: {
+ slug: string;
+ remote_id: string;
+ }[],
+ ): Promise {
+ const result: MicrosoftdynamicssalesTaskInput = {
+ subject: source.subject,
+ description: source.content
+ };
+
+ if (source.status) {
+ result.statecode = source.status === "COMPLETED" ? 1 : 0;
+ }
+
+ if (source.due_date) {
+ result.scheduledend = source.due_date.toUTCString();
+ }
+
+ if (source.finished_date) {
+ result.actualend = source.finished_date.toUTCString();
+ }
+
+ // User have to provide either company_id or deal_id which will be associated with current task
+ if (source.company_id) {
+ const id = await this.utils.getRemoteIdFromCompanyUuid(source.company_id);
+ result["regardingobjectid_account@odata.bind"] = `/accounts(${id})`;
+ }
+
+ else if (source.deal_id) {
+ const id = await this.utils.getRemoteIdFromDealUuid(source.deal_id);
+ result["regardingobjectid_opportunity@odata.bind"] = `/opportunities(${id})`;
+ }
+
+ return result;
+ }
+
+ async unify(
+ source: MicrosoftdynamicssalesTaskOutput | MicrosoftdynamicssalesTaskOutput[],
+ connectionId: string,
+ customFieldMappings?: {
+ slug: string;
+ remote_id: string;
+ }[],
+ ): Promise {
+ if (!Array.isArray(source)) {
+ return await this.mapSingleTaskToUnified(
+ source,
+ connectionId,
+ customFieldMappings,
+ );
+ }
+
+ return Promise.all(
+ source.map((task) =>
+ this.mapSingleTaskToUnified(task, connectionId, customFieldMappings),
+ ),
+ );
+ }
+
+ private async mapSingleTaskToUnified(
+ task: MicrosoftdynamicssalesTaskOutput,
+ connectionId: string,
+ customFieldMappings?: {
+ slug: string;
+ remote_id: string;
+ }[],
+ ): Promise {
+ const field_mappings: { [key: string]: any } = {};
+ if (customFieldMappings) {
+ for (const mapping of customFieldMappings) {
+ field_mappings[mapping.slug] = task[mapping.remote_id];
+ }
+ }
+
+ let opts: any = {};
+
+ if (task.statecode) {
+ opts = {
+ ...opts,
+ status: task.statecode === 1 ? "COMPLETED" : "PENDING"
+ }
+ }
+
+ if (task.scheduledend) {
+ opts = {
+ ...opts,
+ due_date: new Date(task.scheduledend)
+ }
+ }
+
+ if (task.actualend) {
+ opts = {
+ ...opts,
+ finished_date: new Date(task.actualend)
+ }
+ }
+
+
+ // Here the task either associated to deal or company
+ if (task._regardingobjectid_value) {
+ const company_id = await this.utils.getCompanyUuidFromRemoteId(
+ task._regardingobjectid_value,
+ connectionId,
+ );
+
+ if (company_id) {
+ opts = {
+ ...opts,
+ company_id: company_id,
+ }
+ }
+
+ const deal_id = await this.utils.getDealUuidFromRemoteId(
+ task._regardingobjectid_value,
+ connectionId,
+ )
+
+ if (deal_id) {
+ opts = {
+ ...opts,
+ deal_id: deal_id,
+ }
+ }
+ }
+
+ if (task._createdby_value) {
+ const user_id = await this.utils.getUserUuidFromRemoteId(
+ task._createdby_value,
+ connectionId
+ )
+
+ opts = {
+ ...opts,
+ user_id: user_id
+ }
+ }
+
+ return {
+ remote_id: task.activityid,
+ subject: task.subject ?? '',
+ remote_data: task,
+ content: task.description ?? '',
+ field_mappings,
+ ...opts,
+ };
+ }
+}
diff --git a/packages/api/src/crm/task/services/microsoftdynamicssales/types.ts b/packages/api/src/crm/task/services/microsoftdynamicssales/types.ts
new file mode 100644
index 000000000..374c8208e
--- /dev/null
+++ b/packages/api/src/crm/task/services/microsoftdynamicssales/types.ts
@@ -0,0 +1,70 @@
+interface MicrosoftdynamicssalesTask {
+ activityadditionalparams: string;
+ activityid: string;
+ activitytypecode: string;
+ actualdurationminutes: number;
+ actualend: string;
+ actualstart: string;
+ category: string;
+ community: number;
+ createdon: string;
+ crmtaskassigneduniqueid: string;
+ deliverylastattemptedon: string;
+ deliveryprioritycode: number;
+ description: string;
+ descriptionblobid: string;
+ descriptionblobid_name: string;
+ exchangeitemid: string;
+ exchangerate: number;
+ exchangeweblink: string;
+ formattedscheduledend: string;
+ formattedscheduledstart: string;
+ importsequencenumber: number;
+ instancetypecode: number;
+ isbilled: boolean;
+ ismapiprivate: boolean;
+ isregularactivity: boolean;
+ isworkflowcreated: boolean;
+ lastonholdtime: string;
+ leftvoicemail: boolean;
+ modifiedon: string;
+ onholdtime: number;
+ overriddencreatedon: string;
+ percentcomplete: number;
+ postponeactivityprocessinguntil: string;
+ prioritycode: number;
+ processid: string;
+ scheduleddurationminutes: number;
+ scheduledend: string;
+ scheduledstart: string;
+ senton: string;
+ seriesid: string;
+ sortdate: string;
+ stageid: string;
+ statecode: number;
+ statuscode: number;
+ subcategory: string;
+ subject: string;
+ subscriptionid: string;
+ timezoneruleversionnumber: number;
+ traversedpath: string;
+ utcconversiontimezonecode: number;
+ versionnumber: number;
+ _createdby_value: string;
+ _createdonbehalfby_value: string;
+ _modifiedby_value: string;
+ _modifiedonbehalfby_value: string;
+ _ownerid_value: string;
+ _owningbusinessunit_value: string;
+ _owningteam_value: string;
+ _owninguser_value: string;
+ _regardingobjectid_value: string;
+ _sendermailboxid_value: string;
+ _slaid_value: string;
+ _slainvokedid_value: string;
+ _transactioncurrencyid_value: string;
+ [key: string]: any;
+}
+
+export type MicrosoftdynamicssalesTaskInput = Partial;
+export type MicrosoftdynamicssalesTaskOutput = MicrosoftdynamicssalesTaskInput;
\ No newline at end of file
diff --git a/packages/api/src/crm/task/task.module.ts b/packages/api/src/crm/task/task.module.ts
index c790a2e36..63800e06a 100644
--- a/packages/api/src/crm/task/task.module.ts
+++ b/packages/api/src/crm/task/task.module.ts
@@ -1,3 +1,5 @@
+import { MicrosoftdynamicssalesTaskMapper } from './services/microsoftdynamicssales/mappers';
+import { MicrosoftdynamicssalesService } from './services/microsoftdynamicssales';
import { BullQueueModule } from '@@core/@core-services/queues/queue.module';
import { IngestDataService } from '@@core/@core-services/unification/ingest-data.service';
@@ -43,6 +45,8 @@ import { TaskController } from './task.controller';
HubspotTaskMapper,
CloseTaskMapper,
AttioTaskMapper,
+ MicrosoftdynamicssalesService,
+ MicrosoftdynamicssalesTaskMapper,
],
exports: [SyncService, ServiceRegistry, WebhookService],
})
diff --git a/packages/api/src/crm/user/services/microsoftdynamicssales/index.ts b/packages/api/src/crm/user/services/microsoftdynamicssales/index.ts
new file mode 100644
index 000000000..83b1170b6
--- /dev/null
+++ b/packages/api/src/crm/user/services/microsoftdynamicssales/index.ts
@@ -0,0 +1,67 @@
+import { EncryptionService } from '@@core/@core-services/encryption/encryption.service';
+import { LoggerService } from '@@core/@core-services/logger/logger.service';
+import { PrismaService } from '@@core/@core-services/prisma/prisma.service';
+import { ApiResponse } from '@@core/utils/types';
+import { SyncParam } from '@@core/utils/types/interface';
+import { CrmObject } from '@crm/@lib/@types';
+import { IUserService } from '@crm/user/types';
+import { Injectable } from '@nestjs/common';
+import axios from 'axios';
+import { ServiceRegistry } from '../registry.service';
+import { MicrosoftdynamicssalesUserOutput } from './types';
+
+@Injectable()
+export class MicrosoftdynamicssalesService implements IUserService {
+ constructor(
+ private prisma: PrismaService,
+ private logger: LoggerService,
+ private cryptoService: EncryptionService,
+ private registry: ServiceRegistry,
+ ) {
+ this.logger.setContext(
+ CrmObject.user.toUpperCase() + ':' + MicrosoftdynamicssalesService.name,
+ );
+ this.registry.registerService('microsoftdynamicssales', this);
+ }
+
+ async sync(data: SyncParam): Promise> {
+ try {
+ const { linkedUserId } = data;
+
+ const connection = await this.prisma.connections.findFirst({
+ where: {
+ id_linked_user: linkedUserId,
+ provider_slug: 'microsoftdynamicssales',
+ vertical: 'crm',
+ },
+ });
+
+ this.logger.log("===========");
+ this.logger.log(this.cryptoService.decrypt(
+ connection.access_token,
+ ));
+ this.logger.log("===========");
+
+
+ const baseURL = `${connection.account_url}/api/data/v9.2/systemusers`;
+ const resp = await axios.get(baseURL, {
+ headers: {
+ 'Content-Type': 'application/json',
+ Authorization: `Bearer ${this.cryptoService.decrypt(
+ connection.access_token,
+ )}`,
+ },
+ });
+
+ this.logger.log(`Synced microsoftdynamicssales users ! : ${JSON.stringify(resp.data.value)}`);
+
+ return {
+ data: resp.data.value,
+ message: 'Microsoftdynamicssales users retrieved',
+ statusCode: 200,
+ };
+ } catch (error) {
+ throw error;
+ }
+ }
+}
diff --git a/packages/api/src/crm/user/services/microsoftdynamicssales/mappers.ts b/packages/api/src/crm/user/services/microsoftdynamicssales/mappers.ts
new file mode 100644
index 000000000..fa88aa44b
--- /dev/null
+++ b/packages/api/src/crm/user/services/microsoftdynamicssales/mappers.ts
@@ -0,0 +1,71 @@
+import { MicrosoftdynamicssalesUserOutput } from './types';
+import {
+ UnifiedCrmUserInput,
+ UnifiedCrmUserOutput,
+} from '@crm/user/types/model.unified';
+import { IUserMapper } from '@crm/user/types';
+import { MappersRegistry } from '@@core/@core-services/registries/mappers.registry';
+import { Injectable } from '@nestjs/common';
+import { Utils } from '@crm/@lib/@utils';
+
+@Injectable()
+export class MicrosoftdynamicssalesUserMapper implements IUserMapper {
+ constructor(private mappersRegistry: MappersRegistry, private utils: Utils) {
+ this.mappersRegistry.registerService('crm', 'user', 'microsoftdynamicssales', this);
+ }
+ desunify(
+ source: UnifiedCrmUserInput,
+ customFieldMappings?: {
+ slug: string;
+ remote_id: string;
+ }[],
+ ) {
+ return;
+ }
+
+ unify(
+ source: MicrosoftdynamicssalesUserOutput | MicrosoftdynamicssalesUserOutput[],
+ connectionId: string,
+ customFieldMappings?: {
+ slug: string;
+ remote_id: string;
+ }[],
+ ): Promise {
+ if (!Array.isArray(source)) {
+ return this.mapSingleUserToUnified(
+ source,
+ connectionId,
+ customFieldMappings,
+ );
+ }
+ // Handling array of MicrosoftdynamicssalesUserOutput
+ return Promise.all(
+ source.map((user) =>
+ this.mapSingleUserToUnified(user, connectionId, customFieldMappings),
+ ),
+ );
+ }
+
+ private async mapSingleUserToUnified(
+ user: MicrosoftdynamicssalesUserOutput,
+ connectionId: string,
+ customFieldMappings?: {
+ slug: string;
+ remote_id: string;
+ }[],
+ ): Promise {
+ const field_mappings: { [key: string]: any } = {};
+ if (customFieldMappings) {
+ for (const mapping of customFieldMappings) {
+ field_mappings[mapping.slug] = user[mapping.remote_id];
+ }
+ }
+ return {
+ remote_id: user.ownerid,
+ remote_data: user,
+ name: `${user.firstname} ${user.lastname}`,
+ email: user.personalemailaddress,
+ field_mappings,
+ };
+ }
+}
diff --git a/packages/api/src/crm/user/services/microsoftdynamicssales/types.ts b/packages/api/src/crm/user/services/microsoftdynamicssales/types.ts
new file mode 100644
index 000000000..94437e339
--- /dev/null
+++ b/packages/api/src/crm/user/services/microsoftdynamicssales/types.ts
@@ -0,0 +1,123 @@
+interface MicrosoftdynamicssalesUser {
+ accessmode: number; // Edm.Int32
+ address1_addressid: string; // Edm.Guid
+ address1_addresstypecode: number; // Edm.Int32
+ address1_city: string; // Edm.String
+ address1_composite: string; // Edm.String
+ address1_country: string; // Edm.String
+ address1_county: string; // Edm.String
+ address1_fax: string; // Edm.String
+ address1_latitude: number; // Edm.Double
+ address1_line1: string; // Edm.String
+ address1_line2: string; // Edm.String
+ address1_line3: string; // Edm.String
+ address1_longitude: number; // Edm.Double
+ address1_name: string; // Edm.String
+ address1_postalcode: string; // Edm.String
+ address1_postofficebox: string; // Edm.String
+ address1_shippingmethodcode: number; // Edm.Int32
+ address1_stateorprovince: string; // Edm.String
+ address1_telephone1: string; // Edm.String
+ address1_telephone2: string; // Edm.String
+ address1_telephone3: string; // Edm.String
+ address1_upszone: string; // Edm.String
+ address1_utcoffset: number; // Edm.Int32
+ address2_addressid: string; // Edm.Guid
+ address2_addresstypecode: number; // Edm.Int32
+ address2_city: string; // Edm.String
+ address2_composite: string; // Edm.String
+ address2_country: string; // Edm.String
+ address2_county: string; // Edm.String
+ address2_fax: string; // Edm.String
+ address2_latitude: number; // Edm.Double
+ address2_line1: string; // Edm.String
+ address2_line2: string; // Edm.String
+ address2_line3: string; // Edm.String
+ address2_longitude: number; // Edm.Double
+ address2_name: string; // Edm.String
+ address2_postalcode: string; // Edm.String
+ address2_postofficebox: string; // Edm.String
+ address2_shippingmethodcode: number; // Edm.Int32
+ address2_stateorprovince: string; // Edm.String
+ address2_telephone1: string; // Edm.String
+ address2_telephone2: string; // Edm.String
+ address2_telephone3: string; // Edm.String
+ address2_upszone: string; // Edm.String
+ address2_utcoffset: number; // Edm.Int32
+ applicationid: string; // Edm.Guid
+ applicationiduri: string; // Edm.String
+ azureactivedirectoryobjectid: string; // Edm.Guid
+ azuredeletedon: string; // Edm.DateTimeOffset
+ azurestate: number; // Edm.Int32
+ caltype: number; // Edm.Int32
+ createdon: string; // Edm.DateTimeOffset
+ defaultfilterspopulated: boolean; // Edm.Boolean
+ defaultodbfoldername: string; // Edm.String
+ deletedstate: number; // Edm.Int32
+ disabledreason: string; // Edm.String
+ displayinserviceviews: boolean; // Edm.Boolean
+ domainname: string; // Edm.String
+ emailrouteraccessapproval: number; // Edm.Int32
+ employeeid: string; // Edm.String
+ entityimage: string; // Edm.Binary
+ entityimage_timestamp: number; // Edm.Int64
+ entityimage_url: string; // Edm.String
+ entityimageid: string; // Edm.Guid
+ exchangerate: number; // Edm.Decimal
+ firstname: string; // Edm.String
+ fullname: string; // Edm.String
+ governmentid: string; // Edm.String
+ homephone: string; // Edm.String
+ identityid: number; // Edm.Int32
+ importsequencenumber: number; // Edm.Int32
+ incomingemaildeliverymethod: number; // Edm.Int32
+ internalemailaddress: string; // Edm.String
+ invitestatuscode: number; // Edm.Int32
+ isdisabled: boolean; // Edm.Boolean
+ isemailaddressapprovedbyo365admin: boolean; // Edm.Boolean
+ isintegrationuser: boolean; // Edm.Boolean
+ islicensed: boolean; // Edm.Boolean
+ issyncwithdirectory: boolean; // Edm.Boolean
+ jobtitle: string; // Edm.String
+ lastname: string; // Edm.String
+ middlename: string; // Edm.String
+ mobilealertemail: string; // Edm.String
+ mobilephone: string; // Edm.String
+ modifiedon: string; // Edm.DateTimeOffset
+ nickname: string; // Edm.String
+ organizationid: string; // Edm.Guid
+ outgoingemaildeliverymethod: number; // Edm.Int32
+ overriddencreatedon: string; // Edm.DateTimeOffset
+ ownerid: string; // Edm.Guid
+ passporthi: number; // Edm.Int32
+ passportlo: number; // Edm.Int32
+ personalemailaddress: string; // Edm.String
+ photourl: string; // Edm.String
+ preferredaddresscode: number; // Edm.Int32
+ preferredemailcode: number; // Edm.Int32
+ preferredphonecode: number; // Edm.Int32
+ processid: string; // Edm.Guid
+ salutation: string; // Edm.String
+ setupuser: boolean; // Edm.Boolean
+ sharepointemailaddress: string; // Edm.String
+ skills: string; // Edm.String
+ stageid: string; // Edm.Guid
+ systemuserid: string; // Edm.Guid
+ timezoneruleversionnumber: number; // Edm.Int32
+ title: string; // Edm.String
+ traversedpath: string; // Edm.String
+ userlicensetype: number; // Edm.Int32
+ userpuid: string; // Edm.String
+ utcconversiontimezonecode: number; // Edm.Int32
+ versionnumber: number; // Edm.Int64
+ windowsliveid: string; // Edm.String
+ yammeremailaddress: string; // Edm.String
+ yammeruserid: string; // Edm.String
+ yomifirstname: string; // Edm.String
+ yomifullname: string; // Edm.String
+ yomilastname: string; // Edm.String
+ yomimiddlename: string; // Edm.String
+}
+
+export type MicrosoftdynamicssalesUserInput = Partial;
+export type MicrosoftdynamicssalesUserOutput = MicrosoftdynamicssalesUserInput;
\ No newline at end of file
diff --git a/packages/api/src/crm/user/user.module.ts b/packages/api/src/crm/user/user.module.ts
index 0957b622f..9ca93bd02 100644
--- a/packages/api/src/crm/user/user.module.ts
+++ b/packages/api/src/crm/user/user.module.ts
@@ -1,3 +1,5 @@
+import { MicrosoftdynamicssalesUserMapper } from './services/microsoftdynamicssales/mappers';
+import { MicrosoftdynamicssalesService } from './services/microsoftdynamicssales';
import { BullQueueModule } from '@@core/@core-services/queues/queue.module';
import { IngestDataService } from '@@core/@core-services/unification/ingest-data.service';
@@ -43,6 +45,8 @@ import { UserController } from './user.controller';
HubspotUserMapper,
AttioUserMapper,
CloseUserMapper,
+ MicrosoftdynamicssalesService,
+ MicrosoftdynamicssalesUserMapper,
],
exports: [SyncService, ServiceRegistry, WebhookService],
})
diff --git a/packages/shared/src/authUrl.ts b/packages/shared/src/authUrl.ts
index 5a7ae7d8a..04f048dad 100644
--- a/packages/shared/src/authUrl.ts
+++ b/packages/shared/src/authUrl.ts
@@ -126,13 +126,13 @@ const handleOAuth2Url = async ({
...dyn
}: HandleOAuth2Url) => {
const type = providerToType(providerName, vertical, authStrategy);
-
+
const response = await fetch(`${apiUrl}/connection_strategies/getCredentials?projectId=${projectId}&type=${type}`);
const data = await response.json() as OAuth2AuthData;
const clientId = data.CLIENT_ID;
if (!clientId) throw new ReferenceError(`No client id for type ${type}`);
-
+
const scopes = data.SCOPE;
const { urls: { authBaseUrl: baseUrl } } = config;
if (!baseUrl) throw new ReferenceError(`No authBaseUrl found for type ${type}`);
diff --git a/packages/shared/src/connectors/enum.ts b/packages/shared/src/connectors/enum.ts
index a66547391..0679963b8 100644
--- a/packages/shared/src/connectors/enum.ts
+++ b/packages/shared/src/connectors/enum.ts
@@ -4,7 +4,8 @@ export enum CrmConnectors {
HUBSPOT = 'hubspot',
PIPEDRIVE = 'pipedrive',
ATTIO = 'attio',
- CLOSE = 'close'
+ CLOSE = 'close',
+ MICROSOFTDYNAMICSSALES = 'microsoftdynamicssales'
}
export enum EcommerceConnectors {
diff --git a/packages/shared/src/connectors/index.ts b/packages/shared/src/connectors/index.ts
index 105ca557a..c99c194d7 100644
--- a/packages/shared/src/connectors/index.ts
+++ b/packages/shared/src/connectors/index.ts
@@ -1,4 +1,4 @@
-export const CRM_PROVIDERS = ['zoho', 'zendesk', 'hubspot', 'pipedrive', 'attio', 'close'];
+export const CRM_PROVIDERS = ['zoho', 'zendesk', 'hubspot', 'pipedrive', 'attio', 'close', 'microsoftdynamicssales'];
export const HRIS_PROVIDERS = [];
export const ATS_PROVIDERS = ['ashby'];
export const ACCOUNTING_PROVIDERS = [];
diff --git a/packages/shared/src/connectors/metadata.ts b/packages/shared/src/connectors/metadata.ts
index 873590f9c..3d2251a14 100644
--- a/packages/shared/src/connectors/metadata.ts
+++ b/packages/shared/src/connectors/metadata.ts
@@ -3090,4 +3090,4 @@ export const CONNECTORS_METADATA: ProvidersConfig = {
}
},
}
-};
+};
\ No newline at end of file
From b32940f1cbe7cba43283595589b89832797f6cc8 Mon Sep 17 00:00:00 2001
From: nael
Date: Mon, 26 Aug 2024 22:02:27 +0200
Subject: [PATCH 20/49] :bug: Fix verifyEvent return response type
---
.../panora-webhooks/webhook.controller.ts | 5 ++-
.../panora-webhooks/webhook.processor.ts | 36 ++++++++++-------
.../panora-webhooks/webhook.service.ts | 7 ----
.../ats/services/ashby/ashby.service.ts | 4 +-
.../@core/utils/dtos/openapi.respone.dto.ts | 2 +-
packages/api/src/crm/@lib/@utils/index.ts | 1 +
.../src/crm/company/services/hubspot/index.ts | 2 +-
.../src/crm/contact/services/hubspot/index.ts | 2 +-
.../api/src/crm/contact/sync/sync.service.ts | 40 +++++++++----------
.../src/crm/deal/services/hubspot/index.ts | 2 +-
.../api/src/crm/deal/sync/sync.service.ts | 39 +++++++++---------
.../crm/engagement/services/hubspot/index.ts | 6 +--
.../src/crm/note/services/hubspot/index.ts | 4 +-
.../src/crm/task/services/hubspot/index.ts | 19 +++++----
.../src/crm/user/services/hubspot/index.ts | 17 ++++----
packages/api/swagger/swagger-spec.yaml | 4 +-
packages/shared/src/authUrl.ts | 2 +-
packages/shared/src/connectors/metadata.ts | 2 +-
18 files changed, 97 insertions(+), 97 deletions(-)
diff --git a/packages/api/src/@core/@core-services/webhooks/panora-webhooks/webhook.controller.ts b/packages/api/src/@core/@core-services/webhooks/panora-webhooks/webhook.controller.ts
index 38b311ade..5cd8b1857 100644
--- a/packages/api/src/@core/@core-services/webhooks/panora-webhooks/webhook.controller.ts
+++ b/packages/api/src/@core/@core-services/webhooks/panora-webhooks/webhook.controller.ts
@@ -176,10 +176,13 @@ export class WebhookController {
@Post('verifyEvent')
async verifyPayloadSignature(@Body() data: SignatureVerificationDto) {
const { payload, signature, secret } = data;
- return await this.webhookService.verifyPayloadSignature(
+ const resp = await this.webhookService.verifyPayloadSignature(
payload,
signature,
secret,
);
+ return {
+ data: resp,
+ };
}
}
diff --git a/packages/api/src/@core/@core-services/webhooks/panora-webhooks/webhook.processor.ts b/packages/api/src/@core/@core-services/webhooks/panora-webhooks/webhook.processor.ts
index cc43e3f23..741209b02 100644
--- a/packages/api/src/@core/@core-services/webhooks/panora-webhooks/webhook.processor.ts
+++ b/packages/api/src/@core/@core-services/webhooks/panora-webhooks/webhook.processor.ts
@@ -6,6 +6,7 @@ import { Job } from 'bull';
import { v4 as uuidv4 } from 'uuid';
import { WebhookService } from './webhook.service';
import { Queues } from '@@core/@core-services/queues/types';
+import { response } from 'express';
@Processor(Queues.PANORA_WEBHOOKS_SENDER)
export class WebhookProcessor {
@@ -60,19 +61,24 @@ export class WebhookProcessor {
deliveryAttempt.webhooks_payloads.data,
deliveryAttempt.webhook_endpoints.secret,
);
- const response = await axios.post(
- deliveryAttempt.webhook_endpoints.url,
- {
- id_event: deliveryAttempt.id_event,
- data: deliveryAttempt.webhooks_payloads.data,
- type: event.type,
- },
- {
- headers: {
- 'Panora-Signature': signature,
+ let response;
+ try {
+ response = await axios.post(
+ deliveryAttempt.webhook_endpoints.url,
+ {
+ id_event: deliveryAttempt.id_event,
+ data: deliveryAttempt.webhooks_payloads.data,
+ type: event.type,
},
- },
- );
+ {
+ headers: {
+ 'Panora-Signature': signature,
+ },
+ },
+ );
+ } catch (error) {
+ throw error;
+ }
// Populate the webhooks_responses table
await this.prisma.webhooks_reponses.create({
@@ -92,7 +98,7 @@ export class WebhookProcessor {
this.logger.log('Webhook delivered !');
} catch (error) {
// If the POST request fails, set a next retry time and reinsert the job in the queue
- const nextRetry = new Date();
+ /*const nextRetry = new Date();
nextRetry.setSeconds(nextRetry.getSeconds() + 60); // Retry after 60 seconds
await this.prisma.webhook_delivery_attempts.update({
@@ -104,10 +110,10 @@ export class WebhookProcessor {
});
//re-insert the webhook in the queue
- await this.webhookService.dispatchFailedWebhook(id_webhook_delivery);
+ await this.webhookService.dispatchFailedWebhook(id_webhook_delivery);*/
this.logger.log(
- 'Webhook delivery failed. Job reinserted in the queue for retry.',
+ `Webhook delivery failed. Job reinserted in the queue for retry : ${error}`,
);
}
} else {
diff --git a/packages/api/src/@core/@core-services/webhooks/panora-webhooks/webhook.service.ts b/packages/api/src/@core/@core-services/webhooks/panora-webhooks/webhook.service.ts
index 323e074d4..e025ef298 100644
--- a/packages/api/src/@core/@core-services/webhooks/panora-webhooks/webhook.service.ts
+++ b/packages/api/src/@core/@core-services/webhooks/panora-webhooks/webhook.service.ts
@@ -20,7 +20,6 @@ export class WebhookService {
generateSignature(payload: any, secret: string): string {
try {
- this.logger.log('PAYLOAD IS ' + JSON.stringify(payload));
return createHmac('sha256', secret)
.update(JSON.stringify(payload))
.digest('hex');
@@ -295,12 +294,6 @@ export class WebhookService {
secret: string,
) {
try {
- this.logger.log(
- '(verify) PAYLOAD IS ' +
- JSON.stringify(payload) +
- ' data from payload is ' +
- JSON.stringify(payload.data),
- );
const expected = this.generateSignature(payload.data, secret);
if (expected !== signature) {
throw new WebhooksError({
diff --git a/packages/api/src/@core/connections/ats/services/ashby/ashby.service.ts b/packages/api/src/@core/connections/ats/services/ashby/ashby.service.ts
index 77ec8a559..8fa6a0b80 100644
--- a/packages/api/src/@core/connections/ats/services/ashby/ashby.service.ts
+++ b/packages/api/src/@core/connections/ats/services/ashby/ashby.service.ts
@@ -93,7 +93,7 @@ export class AshbyConnectionService extends AbstractBaseConnectionService {
id_connection: isNotUnique.id_connection,
},
data: {
- access_token: this.cryptoService.encrypt(body.username),
+ access_token: this.cryptoService.encrypt(body.api_key),
account_url: CONNECTORS_METADATA['ats']['ashby'].urls
.apiUrl as string,
status: 'valid',
@@ -110,7 +110,7 @@ export class AshbyConnectionService extends AbstractBaseConnectionService {
token_type: 'basic',
account_url: CONNECTORS_METADATA['ats']['ashby'].urls
.apiUrl as string,
- access_token: this.cryptoService.encrypt(body.username),
+ access_token: this.cryptoService.encrypt(body.api_key),
status: 'valid',
created_at: new Date(),
projects: {
diff --git a/packages/api/src/@core/utils/dtos/openapi.respone.dto.ts b/packages/api/src/@core/utils/dtos/openapi.respone.dto.ts
index ef4b0103e..49a604708 100644
--- a/packages/api/src/@core/utils/dtos/openapi.respone.dto.ts
+++ b/packages/api/src/@core/utils/dtos/openapi.respone.dto.ts
@@ -46,7 +46,7 @@ export const ApiPostCustomResponse = >(
export const ApiPostGenericJson = (description: string) => {
return applyDecorators(
- ApiOkResponse({
+ ApiCreatedResponse({
schema: {
properties: {
data: {
diff --git a/packages/api/src/crm/@lib/@utils/index.ts b/packages/api/src/crm/@lib/@utils/index.ts
index 7f7444c9e..383083625 100644
--- a/packages/api/src/crm/@lib/@utils/index.ts
+++ b/packages/api/src/crm/@lib/@utils/index.ts
@@ -14,6 +14,7 @@ export class Utils {
if (email_addresses) {
normalizedEmails = email_addresses.map((email) => ({
...email,
+ email_address: email.email_address ?? '',
owner_type: email.owner_type ? email.owner_type : '',
created_at: new Date(),
modified_at: new Date(),
diff --git a/packages/api/src/crm/company/services/hubspot/index.ts b/packages/api/src/crm/company/services/hubspot/index.ts
index 4ff80ba66..e5feb1919 100644
--- a/packages/api/src/crm/company/services/hubspot/index.ts
+++ b/packages/api/src/crm/company/services/hubspot/index.ts
@@ -44,7 +44,7 @@ export class HubspotService implements ICompanyService {
properties: companyData,
};
const resp = await axios.post(
- `${connection.account_url}/crm/v3/objects/companies`,
+ `${connection.account_url}/v3/objects/companies`,
JSON.stringify(dataBody),
{
headers: {
diff --git a/packages/api/src/crm/contact/services/hubspot/index.ts b/packages/api/src/crm/contact/services/hubspot/index.ts
index a0c32a178..02fdcbbe6 100644
--- a/packages/api/src/crm/contact/services/hubspot/index.ts
+++ b/packages/api/src/crm/contact/services/hubspot/index.ts
@@ -45,7 +45,7 @@ export class HubspotService implements IContactService {
properties: contactData,
};
const resp = await axios.post(
- `${connection.account_url}/crm/v3/objects/contacts`,
+ `${connection.account_url}/v3/objects/contacts`,
JSON.stringify(dataBody),
{
headers: {
diff --git a/packages/api/src/crm/contact/sync/sync.service.ts b/packages/api/src/crm/contact/sync/sync.service.ts
index a64e78ef3..0f388df28 100644
--- a/packages/api/src/crm/contact/sync/sync.service.ts
+++ b/packages/api/src/crm/contact/sync/sync.service.ts
@@ -1,24 +1,22 @@
-import { FieldMappingService } from '@@core/field-mapping/field-mapping.service';
import { LoggerService } from '@@core/@core-services/logger/logger.service';
import { PrismaService } from '@@core/@core-services/prisma/prisma.service';
-import { ApiResponse } from '@@core/utils/types';
+import { BullQueueService } from '@@core/@core-services/queues/shared.service';
+import { CoreSyncRegistry } from '@@core/@core-services/registries/core-sync.registry';
+import { CoreUnification } from '@@core/@core-services/unification/core-unification.service';
+import { IngestDataService } from '@@core/@core-services/unification/ingest-data.service';
import { WebhookService } from '@@core/@core-services/webhooks/panora-webhooks/webhook.service';
+import { FieldMappingService } from '@@core/field-mapping/field-mapping.service';
+import { IBaseSync, SyncLinkedUserType } from '@@core/utils/types/interface';
+import { OriginalContactOutput } from '@@core/utils/types/original/original.crm';
+import { Utils } from '@crm/@lib/@utils';
import { UnifiedCrmContactOutput } from '@crm/contact/types/model.unified';
-import { CrmObject } from '@crm/@lib/@types';
import { Injectable, OnModuleInit } from '@nestjs/common';
import { Cron } from '@nestjs/schedule';
-import { v4 as uuidv4 } from 'uuid';
+import { CRM_PROVIDERS } from '@panora/shared';
import { crm_contacts as CrmContact } from '@prisma/client';
-import { IContactService } from '../types';
-import { OriginalContactOutput } from '@@core/utils/types/original/original.crm';
+import { v4 as uuidv4 } from 'uuid';
import { ServiceRegistry } from '../services/registry.service';
-import { CRM_PROVIDERS } from '@panora/shared';
-import { Utils } from '@crm/@lib/@utils';
-import { CoreSyncRegistry } from '@@core/@core-services/registries/core-sync.registry';
-import { CoreUnification } from '@@core/@core-services/unification/core-unification.service';
-import { BullQueueService } from '@@core/@core-services/queues/shared.service';
-import { IBaseSync, SyncLinkedUserType } from '@@core/utils/types/interface';
-import { IngestDataService } from '@@core/@core-services/unification/ingest-data.service';
+import { IContactService } from '../types';
@Injectable()
export class SyncService implements OnModuleInit, IBaseSync {
@@ -58,12 +56,12 @@ export class SyncService implements OnModuleInit, IBaseSync {
const users = user_id
? [
- await this.prisma.users.findUnique({
- where: {
- id_user: user_id,
- },
- }),
- ]
+ await this.prisma.users.findUnique({
+ where: {
+ id_user: user_id,
+ },
+ }),
+ ]
: await this.prisma.users.findMany();
if (users && users.length > 0) {
for (const user of users) {
@@ -113,7 +111,9 @@ export class SyncService implements OnModuleInit, IBaseSync {
const service: IContactService =
this.serviceRegistry.getService(integrationId);
if (!service) {
- this.logger.log(`No service found in {vertical:crm, commonObject: contact} for integration ID: ${integrationId}`);
+ this.logger.log(
+ `No service found in {vertical:crm, commonObject: contact} for integration ID: ${integrationId}`,
+ );
return;
}
diff --git a/packages/api/src/crm/deal/services/hubspot/index.ts b/packages/api/src/crm/deal/services/hubspot/index.ts
index 5f2ba38ee..237c15b6f 100644
--- a/packages/api/src/crm/deal/services/hubspot/index.ts
+++ b/packages/api/src/crm/deal/services/hubspot/index.ts
@@ -82,7 +82,7 @@ export class HubspotService implements IDealService {
const commonPropertyNames = Object.keys(commonDealHubspotProperties);
const allProperties = [...commonPropertyNames, ...custom_properties];
- const baseURL = `${connection.account_url}/crm/v3/objects/deals`;
+ const baseURL = `${connection.account_url}/v3/objects/deals`;
const queryString = allProperties
.map((prop) => `properties=${encodeURIComponent(prop)}`)
diff --git a/packages/api/src/crm/deal/sync/sync.service.ts b/packages/api/src/crm/deal/sync/sync.service.ts
index 24a2c8550..95e80032f 100644
--- a/packages/api/src/crm/deal/sync/sync.service.ts
+++ b/packages/api/src/crm/deal/sync/sync.service.ts
@@ -1,20 +1,19 @@
-import { Injectable, OnModuleInit } from '@nestjs/common';
import { LoggerService } from '@@core/@core-services/logger/logger.service';
import { PrismaService } from '@@core/@core-services/prisma/prisma.service';
+import { BullQueueService } from '@@core/@core-services/queues/shared.service';
+import { CoreSyncRegistry } from '@@core/@core-services/registries/core-sync.registry';
+import { IngestDataService } from '@@core/@core-services/unification/ingest-data.service';
+import { FieldMappingService } from '@@core/field-mapping/field-mapping.service';
+import { IBaseSync, SyncLinkedUserType } from '@@core/utils/types/interface';
+import { OriginalDealOutput } from '@@core/utils/types/original/original.crm';
+import { Injectable, OnModuleInit } from '@nestjs/common';
import { Cron } from '@nestjs/schedule';
-import { ApiResponse } from '@@core/utils/types';
+import { CRM_PROVIDERS } from '@panora/shared';
+import { crm_deals as CrmDeal } from '@prisma/client';
import { v4 as uuidv4 } from 'uuid';
-import { FieldMappingService } from '@@core/field-mapping/field-mapping.service';
import { ServiceRegistry } from '../services/registry.service';
-import { UnifiedCrmDealOutput } from '../types/model.unified';
import { IDealService } from '../types';
-import { OriginalDealOutput } from '@@core/utils/types/original/original.crm';
-import { crm_deals as CrmDeal } from '@prisma/client';
-import { CRM_PROVIDERS } from '@panora/shared';
-import { CoreSyncRegistry } from '@@core/@core-services/registries/core-sync.registry';
-import { BullQueueService } from '@@core/@core-services/queues/shared.service';
-import { IBaseSync, SyncLinkedUserType } from '@@core/utils/types/interface';
-import { IngestDataService } from '@@core/@core-services/unification/ingest-data.service';
+import { UnifiedCrmDealOutput } from '../types/model.unified';
@Injectable()
export class SyncService implements OnModuleInit, IBaseSync {
@@ -48,12 +47,12 @@ export class SyncService implements OnModuleInit, IBaseSync {
this.logger.log(`Syncing deals....`);
const users = user_id
? [
- await this.prisma.users.findUnique({
- where: {
- id_user: user_id,
- },
- }),
- ]
+ await this.prisma.users.findUnique({
+ where: {
+ id_user: user_id,
+ },
+ }),
+ ]
: await this.prisma.users.findMany();
if (users && users.length > 0) {
for (const user of users) {
@@ -103,7 +102,9 @@ export class SyncService implements OnModuleInit, IBaseSync {
const service: IDealService =
this.serviceRegistry.getService(integrationId);
if (!service) {
- this.logger.log(`No service found in {vertical:crm, commonObject: deal} for integration ID: ${integrationId}`);
+ this.logger.log(
+ `No service found in {vertical:crm, commonObject: deal} for integration ID: ${integrationId}`,
+ );
return;
}
@@ -141,7 +142,7 @@ export class SyncService implements OnModuleInit, IBaseSync {
const baseData: any = {
name: deal.name ?? null,
description: deal.description ?? null,
- amount: deal.amount ?? null,
+ amount: deal.amount ?? 0,
id_crm_user: deal.user_id ?? null,
id_crm_deals_stage: deal.stage_id ?? null,
id_crm_company: deal.company_id ?? null,
diff --git a/packages/api/src/crm/engagement/services/hubspot/index.ts b/packages/api/src/crm/engagement/services/hubspot/index.ts
index 5673e86db..91aa6bff4 100644
--- a/packages/api/src/crm/engagement/services/hubspot/index.ts
+++ b/packages/api/src/crm/engagement/services/hubspot/index.ts
@@ -81,7 +81,7 @@ export class HubspotService implements IEngagementService {
properties: engagementData,
};
const resp = await axios.post(
- `${connection.account_url}/crm/v3/objects/calls`,
+ `${connection.account_url}/v3/objects/calls`,
JSON.stringify(dataBody),
{
headers: {
@@ -118,7 +118,7 @@ export class HubspotService implements IEngagementService {
properties: engagementData,
};
const resp = await axios.post(
- `${connection.account_url}/crm/v3/objects/meetings`,
+ `${connection.account_url}/v3/objects/meetings`,
JSON.stringify(dataBody),
{
headers: {
@@ -155,7 +155,7 @@ export class HubspotService implements IEngagementService {
properties: engagementData,
};
const resp = await axios.post(
- `${connection.account_url}/crm/v3/objects/emails`,
+ `${connection.account_url}/v3/objects/emails`,
JSON.stringify(dataBody),
{
headers: {
diff --git a/packages/api/src/crm/note/services/hubspot/index.ts b/packages/api/src/crm/note/services/hubspot/index.ts
index 71e3e332a..3028e4e2a 100644
--- a/packages/api/src/crm/note/services/hubspot/index.ts
+++ b/packages/api/src/crm/note/services/hubspot/index.ts
@@ -53,7 +53,7 @@ export class HubspotService implements INoteService {
);
const final_resp = await axios.get(
- `${connection.account_url}/objects/notes/${resp.data.id}?properties=hs_note_body&associations=deal,contact,company`,
+ `${connection.account_url}/v3/objects/notes/${resp.data.id}?properties=hs_note_body&associations=deal,contact,company`,
{
headers: {
'Content-Type': 'application/json',
@@ -87,7 +87,7 @@ export class HubspotService implements INoteService {
const commonPropertyNames = Object.keys(commonNoteHubspotProperties);
const allProperties = [...commonPropertyNames, ...custom_properties];
- const baseURL = `${connection.account_url}/objects/notes`;
+ const baseURL = `${connection.account_url}/v3/objects/notes`;
const queryString = allProperties
.map((prop) => `properties=${encodeURIComponent(prop)}`)
diff --git a/packages/api/src/crm/task/services/hubspot/index.ts b/packages/api/src/crm/task/services/hubspot/index.ts
index 4b8cad070..88b8fcb18 100644
--- a/packages/api/src/crm/task/services/hubspot/index.ts
+++ b/packages/api/src/crm/task/services/hubspot/index.ts
@@ -1,19 +1,18 @@
-import { Injectable } from '@nestjs/common';
-import { ITaskService } from '@crm/task/types';
+import { EncryptionService } from '@@core/@core-services/encryption/encryption.service';
+import { LoggerService } from '@@core/@core-services/logger/logger.service';
+import { PrismaService } from '@@core/@core-services/prisma/prisma.service';
+import { ApiResponse } from '@@core/utils/types';
+import { SyncParam } from '@@core/utils/types/interface';
import { CrmObject } from '@crm/@lib/@types';
+import { ITaskService } from '@crm/task/types';
+import { Injectable } from '@nestjs/common';
+import axios from 'axios';
+import { ServiceRegistry } from '../registry.service';
import {
HubspotTaskInput,
HubspotTaskOutput,
commonTaskHubspotProperties,
} from './types';
-import axios from 'axios';
-import { PrismaService } from '@@core/@core-services/prisma/prisma.service';
-import { LoggerService } from '@@core/@core-services/logger/logger.service';
-import { ActionType, handle3rdPartyServiceError } from '@@core/utils/errors';
-import { EncryptionService } from '@@core/@core-services/encryption/encryption.service';
-import { ApiResponse } from '@@core/utils/types';
-import { ServiceRegistry } from '../registry.service';
-import { SyncParam } from '@@core/utils/types/interface';
@Injectable()
export class HubspotService implements ITaskService {
diff --git a/packages/api/src/crm/user/services/hubspot/index.ts b/packages/api/src/crm/user/services/hubspot/index.ts
index a86a7ec20..0e35a4f77 100644
--- a/packages/api/src/crm/user/services/hubspot/index.ts
+++ b/packages/api/src/crm/user/services/hubspot/index.ts
@@ -1,15 +1,14 @@
-import { Injectable } from '@nestjs/common';
-import { IUserService } from '@crm/user/types';
-import { CrmObject } from '@crm/@lib/@types';
-import { HubspotUserOutput, commonUserHubspotProperties } from './types';
-import axios from 'axios';
-import { PrismaService } from '@@core/@core-services/prisma/prisma.service';
-import { LoggerService } from '@@core/@core-services/logger/logger.service';
-import { ActionType, handle3rdPartyServiceError } from '@@core/utils/errors';
import { EncryptionService } from '@@core/@core-services/encryption/encryption.service';
+import { LoggerService } from '@@core/@core-services/logger/logger.service';
+import { PrismaService } from '@@core/@core-services/prisma/prisma.service';
import { ApiResponse } from '@@core/utils/types';
-import { ServiceRegistry } from '../registry.service';
import { SyncParam } from '@@core/utils/types/interface';
+import { CrmObject } from '@crm/@lib/@types';
+import { IUserService } from '@crm/user/types';
+import { Injectable } from '@nestjs/common';
+import axios from 'axios';
+import { ServiceRegistry } from '../registry.service';
+import { HubspotUserOutput, commonUserHubspotProperties } from './types';
@Injectable()
export class HubspotService implements IUserService {
diff --git a/packages/api/swagger/swagger-spec.yaml b/packages/api/swagger/swagger-spec.yaml
index 17b806d81..722e6de24 100644
--- a/packages/api/swagger/swagger-spec.yaml
+++ b/packages/api/swagger/swagger-spec.yaml
@@ -151,7 +151,7 @@ paths:
schema:
$ref: '#/components/schemas/SignatureVerificationDto'
responses:
- '200':
+ '201':
description: ''
content:
application/json:
@@ -161,8 +161,6 @@ paths:
type: object
additionalProperties: true
description: Dynamic event payload
- '201':
- description: ''
tags: *ref_0
x-speakeasy-group: webhooks
/ticketing/tickets:
diff --git a/packages/shared/src/authUrl.ts b/packages/shared/src/authUrl.ts
index 5a7ae7d8a..cc719e90c 100644
--- a/packages/shared/src/authUrl.ts
+++ b/packages/shared/src/authUrl.ts
@@ -48,7 +48,7 @@ export const constructAuthUrl = async ({
let baseRedirectURL = apiUrl;
if (config.options?.local_redirect_uri_in_https && redirectUriIngress?.status) {
baseRedirectURL = redirectUriIngress.value!;
- }
+ }
const encodedRedirectUrl = encodeURIComponent(`${baseRedirectURL}/connections/oauth/callback`);
let state = encodeURIComponent(JSON.stringify({ projectId, linkedUserId, providerName, vertical, returnUrl }));
diff --git a/packages/shared/src/connectors/metadata.ts b/packages/shared/src/connectors/metadata.ts
index 873590f9c..b5baeafac 100644
--- a/packages/shared/src/connectors/metadata.ts
+++ b/packages/shared/src/connectors/metadata.ts
@@ -1259,7 +1259,7 @@ export const CONNECTORS_METADATA: ProvidersConfig = {
primaryColor: '#4a3ead',
authStrategy: {
strategy: AuthStrategy.basic,
- properties: ['username']
+ properties: ['api_key']
}
},
'bamboohr': {
From d2e3cc3de695c6a27c4a8e2762c328c9db624ed0 Mon Sep 17 00:00:00 2001
From: nael
Date: Tue, 27 Aug 2024 01:26:38 +0200
Subject: [PATCH 21/49] :sparkles: Update verifyEvent return response
---
.../webhooks/panora-webhooks/webhook.controller.ts | 4 +---
.../api/src/@core/utils/dtos/openapi.respone.dto.ts | 10 +++-------
packages/api/swagger/swagger-spec.yaml | 8 +++-----
3 files changed, 7 insertions(+), 15 deletions(-)
diff --git a/packages/api/src/@core/@core-services/webhooks/panora-webhooks/webhook.controller.ts b/packages/api/src/@core/@core-services/webhooks/panora-webhooks/webhook.controller.ts
index 5cd8b1857..1cabce443 100644
--- a/packages/api/src/@core/@core-services/webhooks/panora-webhooks/webhook.controller.ts
+++ b/packages/api/src/@core/@core-services/webhooks/panora-webhooks/webhook.controller.ts
@@ -181,8 +181,6 @@ export class WebhookController {
signature,
secret,
);
- return {
- data: resp,
- };
+ return resp;
}
}
diff --git a/packages/api/src/@core/utils/dtos/openapi.respone.dto.ts b/packages/api/src/@core/utils/dtos/openapi.respone.dto.ts
index 49a604708..bc3151d25 100644
--- a/packages/api/src/@core/utils/dtos/openapi.respone.dto.ts
+++ b/packages/api/src/@core/utils/dtos/openapi.respone.dto.ts
@@ -48,13 +48,9 @@ export const ApiPostGenericJson = (description: string) => {
return applyDecorators(
ApiCreatedResponse({
schema: {
- properties: {
- data: {
- type: 'object',
- additionalProperties: true,
- description: description,
- },
- },
+ type: 'object',
+ additionalProperties: true,
+ description: description,
},
}),
);
diff --git a/packages/api/swagger/swagger-spec.yaml b/packages/api/swagger/swagger-spec.yaml
index 722e6de24..8abc627f7 100644
--- a/packages/api/swagger/swagger-spec.yaml
+++ b/packages/api/swagger/swagger-spec.yaml
@@ -156,11 +156,9 @@ paths:
content:
application/json:
schema:
- properties:
- data:
- type: object
- additionalProperties: true
- description: Dynamic event payload
+ type: object
+ additionalProperties: true
+ description: Dynamic event payload
tags: *ref_0
x-speakeasy-group: webhooks
/ticketing/tickets:
From 1b143b0a8b98a53c103a424612efd1910baca487 Mon Sep 17 00:00:00 2001
From: nael
Date: Tue, 27 Aug 2024 08:46:10 +0200
Subject: [PATCH 22/49] :bug: Fix limit query type value
---
.../api/src/@core/utils/dtos/query.dto.ts | 3 +-
.../accounting/account/types/model.unified.ts | 2 +-
.../balancesheet/types/model.unified.ts | 2 +-
.../cashflowstatement/types/model.unified.ts | 2 +-
.../companyinfo/types/model.unified.ts | 2 +-
.../accounting/contact/types/model.unified.ts | 2 +-
.../creditnote/types/model.unified.ts | 2 +-
.../accounting/expense/types/model.unified.ts | 4 +-
.../incomestatement/types/model.unified.ts | 2 +-
.../accounting/invoice/types/model.unified.ts | 4 +-
.../journalentry/types/model.unified.ts | 4 +-
.../accounting/payment/types/model.unified.ts | 2 +-
.../purchaseorder/types/model.unified.ts | 4 +-
.../transaction/types/model.unified.ts | 4 +-
.../vendorcredit/types/model.unified.ts | 2 +-
packages/api/src/ats/@lib/@types/index.ts | 8 +-
.../src/ats/activity/types/model.unified.ts | 13 +-
.../src/ats/attachment/types/model.unified.ts | 4 +-
.../api/src/ats/eeocs/types/model.unified.ts | 28 +-
.../src/ats/interview/types/model.unified.ts | 4 +-
.../api/src/ats/job/types/model.unified.ts | 8 +-
.../jobinterviewstage/types/model.unified.ts | 2 +-
.../api/src/ats/offer/types/model.unified.ts | 8 +-
.../src/ats/scorecard/types/model.unified.ts | 4 +-
.../api/src/ats/user/types/model.unified.ts | 8 +-
packages/api/src/crm/@lib/@types/index.ts | 10 +-
.../src/crm/company/types/model.unified.ts | 2 +-
.../api/src/crm/contact/contact.controller.ts | 6 +-
.../crm/contact/services/hubspot/mappers.ts | 4 +-
.../crm/contact/services/zendesk/mappers.ts | 6 +-
.../src/crm/contact/services/zoho/mappers.ts | 4 +-
.../src/crm/engagement/types/model.unified.ts | 12 +-
.../api/src/crm/task/types/model.unified.ts | 6 +-
.../api/src/ecommerce/@lib/@types/index.ts | 4 +-
.../ecommerce/order/types/model.unified.ts | 22 +-
.../ecommerce/product/types/model.unified.ts | 4 +-
.../permission/types/model.unified.ts | 6 +-
.../src/hris/bankinfo/types/model.unified.ts | 2 +-
.../src/hris/dependent/types/model.unified.ts | 4 +-
.../src/hris/employee/types/model.unified.ts | 12 +-
.../employerbenefit/types/model.unified.ts | 2 +-
.../hris/employment/types/model.unified.ts | 14 +-
.../api/src/hris/group/types/model.unified.ts | 2 +-
.../src/hris/location/types/model.unified.ts | 4 +-
.../hris/payrollrun/types/model.unified.ts | 6 +-
.../src/hris/timeoff/types/model.unified.ts | 8 +-
.../timeoffbalance/types/model.unified.ts | 4 +-
.../collection/types/model.unified.ts | 6 +-
.../ticketing/comment/types/model.unified.ts | 6 +-
.../ticketing/ticket/types/model.unified.ts | 18 +-
packages/api/swagger/swagger-spec.yaml | 3320 +----------------
51 files changed, 295 insertions(+), 3327 deletions(-)
diff --git a/packages/api/src/@core/utils/dtos/query.dto.ts b/packages/api/src/@core/utils/dtos/query.dto.ts
index 6a0385e97..2f49e0d5e 100644
--- a/packages/api/src/@core/utils/dtos/query.dto.ts
+++ b/packages/api/src/@core/utils/dtos/query.dto.ts
@@ -30,7 +30,6 @@ export class QueryDto {
@Type(() => Number)
@IsOptional()
@IsNumber()
- @Transform((value) => Number(value))
limit: number = DEFAULT_PAGE_SIZE;
@ApiProperty({
@@ -41,7 +40,7 @@ export class QueryDto {
description: 'Set to get the number of records after this cursor.',
})
@IsOptional()
- @Transform((p) => Buffer.from(p.value, 'base64').toString())
+ //@Transform((p) => Buffer.from(p.value, 'base64').toString())
@IsUUID()
cursor: string;
}
diff --git a/packages/api/src/accounting/account/types/model.unified.ts b/packages/api/src/accounting/account/types/model.unified.ts
index 25a221d9d..b7a1317b6 100644
--- a/packages/api/src/accounting/account/types/model.unified.ts
+++ b/packages/api/src/accounting/account/types/model.unified.ts
@@ -72,7 +72,7 @@ export class UnifiedAccountingAccountInput {
@ApiPropertyOptional({
type: String,
example: 'USD',
- enum: CurrencyCode,
+ // enum: CurrencyCode,
nullable: true,
description: 'The currency of the account',
})
diff --git a/packages/api/src/accounting/balancesheet/types/model.unified.ts b/packages/api/src/accounting/balancesheet/types/model.unified.ts
index ba4cf4439..72d99be9d 100644
--- a/packages/api/src/accounting/balancesheet/types/model.unified.ts
+++ b/packages/api/src/accounting/balancesheet/types/model.unified.ts
@@ -25,7 +25,7 @@ export class UnifiedAccountingBalancesheetInput {
@ApiPropertyOptional({
type: String,
example: 'USD',
- enum: CurrencyCode,
+ // enum: CurrencyCode,
nullable: true,
description: 'The currency used in the balance sheet',
})
diff --git a/packages/api/src/accounting/cashflowstatement/types/model.unified.ts b/packages/api/src/accounting/cashflowstatement/types/model.unified.ts
index 9bfedd309..c020c1a3b 100644
--- a/packages/api/src/accounting/cashflowstatement/types/model.unified.ts
+++ b/packages/api/src/accounting/cashflowstatement/types/model.unified.ts
@@ -114,7 +114,7 @@ export class UnifiedAccountingCashflowstatementInput {
@ApiPropertyOptional({
type: String,
example: 'USD',
- enum: CurrencyCode,
+ // enum: CurrencyCode,
nullable: true,
description: 'The currency used in the cash flow statement',
})
diff --git a/packages/api/src/accounting/companyinfo/types/model.unified.ts b/packages/api/src/accounting/companyinfo/types/model.unified.ts
index 1474454b5..c4e5cc95f 100644
--- a/packages/api/src/accounting/companyinfo/types/model.unified.ts
+++ b/packages/api/src/accounting/companyinfo/types/model.unified.ts
@@ -70,7 +70,7 @@ export class UnifiedAccountingCompanyinfoInput {
@ApiPropertyOptional({
type: String,
example: 'USD',
- enum: CurrencyCode,
+ // enum: CurrencyCode,
nullable: true,
description: 'The currency used by the company',
})
diff --git a/packages/api/src/accounting/contact/types/model.unified.ts b/packages/api/src/accounting/contact/types/model.unified.ts
index 6bce88f18..1a1ecd169 100644
--- a/packages/api/src/accounting/contact/types/model.unified.ts
+++ b/packages/api/src/accounting/contact/types/model.unified.ts
@@ -74,7 +74,7 @@ export class UnifiedAccountingContactInput {
type: String,
example: 'USD',
nullable: true,
- enum: CurrencyCode,
+ // enum: CurrencyCode,
description: 'The currency associated with the contact',
})
@IsString()
diff --git a/packages/api/src/accounting/creditnote/types/model.unified.ts b/packages/api/src/accounting/creditnote/types/model.unified.ts
index 12a03f82b..df2cb2f70 100644
--- a/packages/api/src/accounting/creditnote/types/model.unified.ts
+++ b/packages/api/src/accounting/creditnote/types/model.unified.ts
@@ -105,7 +105,7 @@ export class UnifiedAccountingCreditnoteInput {
@ApiPropertyOptional({
type: String,
example: 'USD',
- enum: CurrencyCode,
+ // enum: CurrencyCode,
nullable: true,
description: 'The currency of the credit note',
})
diff --git a/packages/api/src/accounting/expense/types/model.unified.ts b/packages/api/src/accounting/expense/types/model.unified.ts
index 9d1537f3c..09bc6e091 100644
--- a/packages/api/src/accounting/expense/types/model.unified.ts
+++ b/packages/api/src/accounting/expense/types/model.unified.ts
@@ -23,7 +23,7 @@ export class LineItem {
@ApiPropertyOptional({
type: String,
example: 'USD',
- enum: CurrencyCode,
+ // enum: CurrencyCode,
nullable: true,
description: 'The currency of the line item',
})
@@ -123,7 +123,7 @@ export class UnifiedAccountingExpenseInput {
@ApiPropertyOptional({
type: String,
example: 'USD',
- enum: CurrencyCode,
+ // enum: CurrencyCode,
nullable: true,
description: 'The currency of the expense',
})
diff --git a/packages/api/src/accounting/incomestatement/types/model.unified.ts b/packages/api/src/accounting/incomestatement/types/model.unified.ts
index 18123d79d..ecb1edbe3 100644
--- a/packages/api/src/accounting/incomestatement/types/model.unified.ts
+++ b/packages/api/src/accounting/incomestatement/types/model.unified.ts
@@ -22,7 +22,7 @@ export class UnifiedAccountingIncomestatementInput {
@ApiPropertyOptional({
type: String,
example: 'USD',
- enum: CurrencyCode,
+ // enum: CurrencyCode,
nullable: true,
description: 'The currency used in the income statement',
})
diff --git a/packages/api/src/accounting/invoice/types/model.unified.ts b/packages/api/src/accounting/invoice/types/model.unified.ts
index ce0625651..3fbe810dc 100644
--- a/packages/api/src/accounting/invoice/types/model.unified.ts
+++ b/packages/api/src/accounting/invoice/types/model.unified.ts
@@ -53,7 +53,7 @@ export class LineItem {
@ApiPropertyOptional({
type: String,
example: 'USD',
- enum: CurrencyCode,
+ // enum: CurrencyCode,
nullable: true,
description: 'The currency of the line item',
})
@@ -186,7 +186,7 @@ export class UnifiedAccountingInvoiceInput {
@ApiPropertyOptional({
type: String,
example: 'USD',
- enum: CurrencyCode,
+ // enum: CurrencyCode,
nullable: true,
description: 'The currency of the invoice',
})
diff --git a/packages/api/src/accounting/journalentry/types/model.unified.ts b/packages/api/src/accounting/journalentry/types/model.unified.ts
index 36a1bdb06..792b2fe2c 100644
--- a/packages/api/src/accounting/journalentry/types/model.unified.ts
+++ b/packages/api/src/accounting/journalentry/types/model.unified.ts
@@ -35,7 +35,7 @@ export class LineItem {
@ApiPropertyOptional({
type: String,
example: 'USD',
- enum: CurrencyCode,
+ // enum: CurrencyCode,
nullable: true,
description: 'The currency of the line item',
})
@@ -158,7 +158,7 @@ export class UnifiedAccountingJournalentryInput {
@ApiPropertyOptional({
type: String,
example: 'USD',
- enum: CurrencyCode,
+ // enum: CurrencyCode,
nullable: true,
description: 'The currency of the journal entry',
})
diff --git a/packages/api/src/accounting/payment/types/model.unified.ts b/packages/api/src/accounting/payment/types/model.unified.ts
index aa85513dd..2b7af2c62 100644
--- a/packages/api/src/accounting/payment/types/model.unified.ts
+++ b/packages/api/src/accounting/payment/types/model.unified.ts
@@ -123,7 +123,7 @@ export class UnifiedAccountingPaymentInput {
@ApiPropertyOptional({
type: String,
example: 'USD',
- enum: CurrencyCode,
+ // enum: CurrencyCode,
nullable: true,
description: 'The currency of the payment',
})
diff --git a/packages/api/src/accounting/purchaseorder/types/model.unified.ts b/packages/api/src/accounting/purchaseorder/types/model.unified.ts
index 8d7de7efd..5e7edcd88 100644
--- a/packages/api/src/accounting/purchaseorder/types/model.unified.ts
+++ b/packages/api/src/accounting/purchaseorder/types/model.unified.ts
@@ -76,7 +76,7 @@ export class LineItem {
type: String,
example: 'USD',
nullable: true,
- enum: CurrencyCode,
+ // enum: CurrencyCode,
description: 'The currency of the line item',
})
@IsString()
@@ -246,7 +246,7 @@ export class UnifiedAccountingPurchaseorderInput {
@ApiPropertyOptional({
type: String,
example: 'USD',
- enum: CurrencyCode,
+ // enum: CurrencyCode,
nullable: true,
description: 'The currency of the purchase order',
})
diff --git a/packages/api/src/accounting/transaction/types/model.unified.ts b/packages/api/src/accounting/transaction/types/model.unified.ts
index 27e5aae97..9246cd35d 100644
--- a/packages/api/src/accounting/transaction/types/model.unified.ts
+++ b/packages/api/src/accounting/transaction/types/model.unified.ts
@@ -63,7 +63,7 @@ export class LineItem {
@ApiPropertyOptional({
type: String,
example: 'USD',
- enum: CurrencyCode,
+ // enum: CurrencyCode,
nullable: true,
description: 'The currency of the line item',
})
@@ -214,7 +214,7 @@ export class UnifiedAccountingTransactionInput {
@ApiPropertyOptional({
type: String,
example: 'USD',
- enum: CurrencyCode,
+ // enum: CurrencyCode,
nullable: true,
description: 'The currency of the transaction',
})
diff --git a/packages/api/src/accounting/vendorcredit/types/model.unified.ts b/packages/api/src/accounting/vendorcredit/types/model.unified.ts
index 980918563..270705f67 100644
--- a/packages/api/src/accounting/vendorcredit/types/model.unified.ts
+++ b/packages/api/src/accounting/vendorcredit/types/model.unified.ts
@@ -154,7 +154,7 @@ export class UnifiedAccountingVendorcreditInput {
type: String,
example: 'USD',
nullable: true,
- enum: CurrencyCode,
+ // enum: CurrencyCode,
description: 'The currency of the vendor credit',
})
@IsString()
diff --git a/packages/api/src/ats/@lib/@types/index.ts b/packages/api/src/ats/@lib/@types/index.ts
index 37259f98c..2d2df5f49 100644
--- a/packages/api/src/ats/@lib/@types/index.ts
+++ b/packages/api/src/ats/@lib/@types/index.ts
@@ -154,12 +154,12 @@ export class Email {
@ApiProperty({
type: String,
- enum: ['PERSONAL', 'WORK'],
+ //enum: ['PERSONAL', 'WORK'],
nullable: true,
description:
'The email address type. Authorized values are either PERSONAL or WORK.',
})
- @IsIn(['PERSONAL', 'WORK'])
+ ////@IsIn(['PERSONAL', 'WORK'])
@IsString()
email_address_type: string;
}
@@ -176,11 +176,11 @@ export class Phone {
@ApiProperty({
type: String,
- enum: ['MOBILE', 'WORK'],
+ //enum: ['MOBILE', 'WORK'],
nullable: true,
description: 'The phone type. Authorized values are either MOBILE or WORK',
})
- @IsIn(['MOBILE', 'WORK'])
+ ////@IsIn(['MOBILE', 'WORK'])
@IsString()
phone_type: string;
}
diff --git a/packages/api/src/ats/activity/types/model.unified.ts b/packages/api/src/ats/activity/types/model.unified.ts
index 6ea43b475..2d21f0bf4 100644
--- a/packages/api/src/ats/activity/types/model.unified.ts
+++ b/packages/api/src/ats/activity/types/model.unified.ts
@@ -13,12 +13,12 @@ export type ActivityVisibility = 'ADMIN_ONLY' | 'PUBLIC' | 'PRIVATE';
export class UnifiedAtsActivityInput {
@ApiPropertyOptional({
type: String,
- enum: ['NOTE', 'EMAIL', 'OTHER'],
+ //// enum: ['NOTE', 'EMAIL', 'OTHER'],
example: 'NOTE',
nullable: true,
- description: 'The type of activity',
+ description: 'The type of activity. NOTE, EMAIL or OTHER',
})
- @IsIn(['NOTE', 'EMAIL', 'OTHER'])
+ ////@IsIn(['NOTE', 'EMAIL', 'OTHER'])
@IsOptional()
activity_type?: ActivityType | string;
@@ -44,12 +44,13 @@ export class UnifiedAtsActivityInput {
@ApiPropertyOptional({
type: String,
- enum: ['ADMIN_ONLY', 'PUBLIC', 'PRIVATE'],
+ // enum: ['ADMIN_ONLY', 'PUBLIC', 'PRIVATE'],
example: 'PUBLIC',
nullable: true,
- description: 'The visibility of the activity',
+ description:
+ 'The visibility of the activity. ADMIN_ONLY, PUBLIC or PRIVATE',
})
- @IsIn(['ADMIN_ONLY', 'PUBLIC', 'PRIVATE'])
+ ////@IsIn(['ADMIN_ONLY', 'PUBLIC', 'PRIVATE'])
@IsOptional()
visibility?: ActivityVisibility | string;
diff --git a/packages/api/src/ats/attachment/types/model.unified.ts b/packages/api/src/ats/attachment/types/model.unified.ts
index 52bfe9d58..3843665c6 100644
--- a/packages/api/src/ats/attachment/types/model.unified.ts
+++ b/packages/api/src/ats/attachment/types/model.unified.ts
@@ -36,11 +36,11 @@ export class UnifiedAtsAttachmentInput {
@ApiPropertyOptional({
type: String,
example: 'RESUME',
- enum: ['RESUME', 'COVER_LETTER', 'OFFER_LETTER', 'OTHER'],
+ //// enum: ['RESUME', 'COVER_LETTER', 'OFFER_LETTER', 'OTHER'],
nullable: true,
description: 'The type of the file',
})
- @IsIn(['RESUME', 'COVER_LETTER', 'OFFER_LETTER', 'OTHER'])
+ ////@IsIn(['RESUME', 'COVER_LETTER', 'OFFER_LETTER', 'OTHER'])
@IsOptional()
attachment_type?: AttachmentType | string;
diff --git a/packages/api/src/ats/eeocs/types/model.unified.ts b/packages/api/src/ats/eeocs/types/model.unified.ts
index 6c3b16a86..1dbb9f15a 100644
--- a/packages/api/src/ats/eeocs/types/model.unified.ts
+++ b/packages/api/src/ats/eeocs/types/model.unified.ts
@@ -58,7 +58,7 @@ export class UnifiedAtsEeocsInput {
@ApiPropertyOptional({
type: String,
- enum: [
+ /* enum: [
'AMERICAN_INDIAN_OR_ALASKAN_NATIVE',
'ASIAN',
'BLACK_OR_AFRICAN_AMERICAN',
@@ -67,12 +67,12 @@ export class UnifiedAtsEeocsInput {
'NATIVE_HAWAIIAN_OR_OTHER_PACIFIC_ISLANDER',
'TWO_OR_MORE_RACES',
'DECLINE_TO_SELF_IDENTIFY',
- ],
+ ],*/
example: 'AMERICAN_INDIAN_OR_ALASKAN_NATIVE',
nullable: true,
description: 'The race of the candidate',
})
- @IsIn([
+ /*@IsIn([
'AMERICAN_INDIAN_OR_ALASKAN_NATIVE',
'ASIAN',
'BLACK_OR_AFRICAN_AMERICAN',
@@ -81,56 +81,56 @@ export class UnifiedAtsEeocsInput {
'NATIVE_HAWAIIAN_OR_OTHER_PACIFIC_ISLANDER',
'TWO_OR_MORE_RACES',
'DECLINE_TO_SELF_IDENTIFY',
- ])
+ ])*/
@IsOptional()
race?: EeocsRace | string;
@ApiPropertyOptional({
type: String,
example: 'MALE',
- enum: ['MALE', 'FEMALE', 'NON_BINARY', 'OTHER', 'DECLINE_TO_SELF_IDENTIFY'],
+ // enum: ['MALE', 'FEMALE', 'NON_BINARY', 'OTHER', 'DECLINE_TO_SELF_IDENTIFY'],
nullable: true,
description: 'The gender of the candidate',
})
- @IsIn(['MALE', 'FEMALE', 'NON_BINARY', 'OTHER', 'DECLINE_TO_SELF_IDENTIFY'])
+ //@IsIn(['MALE', 'FEMALE', 'NON_BINARY', 'OTHER', 'DECLINE_TO_SELF_IDENTIFY'])
@IsOptional()
gender?: EeocsGender | string;
@ApiPropertyOptional({
type: String,
example: 'I_AM_NOT_A_PROTECTED_VETERAN',
- enum: [
+ /* enum: [
'I_AM_NOT_A_PROTECTED_VETERAN',
'I_IDENTIFY_AS_ONE_OR_MORE_OF_THE_CLASSIFICATIONS_OF_A_PROTECTED_VETERAN',
'I_DONT_WISH_TO_ANSWER',
- ],
+ ],*/
nullable: true,
description: 'The veteran status of the candidate',
})
- @IsIn([
+ /*@IsIn([
'I_AM_NOT_A_PROTECTED_VETERAN',
'I_IDENTIFY_AS_ONE_OR_MORE_OF_THE_CLASSIFICATIONS_OF_A_PROTECTED_VETERAN',
'I_DONT_WISH_TO_ANSWER',
- ])
+ ])*/
@IsOptional()
veteran_status?: EeocsVeteranStatus | string;
@ApiPropertyOptional({
type: String,
- enum: [
+ /* enum: [
'YES_I_HAVE_A_DISABILITY_OR_PREVIOUSLY_HAD_A_DISABILITY',
'NO_I_DONT_HAVE_A_DISABILITY',
'I_DONT_WISH_TO_ANSWER',
- ],
+ ],*/
example: 'YES_I_HAVE_A_DISABILITY_OR_PREVIOUSLY_HAD_A_DISABILITY',
nullable: true,
description: 'The disability status of the candidate',
})
- @IsIn([
+ /*@IsIn([
'YES_I_HAVE_A_DISABILITY_OR_PREVIOUSLY_HAD_A_DISABILITY',
'NO_I_DONT_HAVE_A_DISABILITY',
'I_DONT_WISH_TO_ANSWER',
- ])
+ ])*/
@IsOptional()
disability_status?: EeocsDisabilityStatus | string;
diff --git a/packages/api/src/ats/interview/types/model.unified.ts b/packages/api/src/ats/interview/types/model.unified.ts
index 8b4ebe31d..3a1e6e272 100644
--- a/packages/api/src/ats/interview/types/model.unified.ts
+++ b/packages/api/src/ats/interview/types/model.unified.ts
@@ -13,12 +13,12 @@ export type InterviewStatus = 'SCHEDULED' | 'AWAITING_FEEDBACK' | 'COMPLETED';
export class UnifiedAtsInterviewInput {
@ApiPropertyOptional({
type: String,
- enum: ['SCHEDULED', 'AWAITING_FEEDBACK', 'COMPLETED'],
+ // enum: ['SCHEDULED', 'AWAITING_FEEDBACK', 'COMPLETED'],
example: 'SCHEDULED',
nullable: true,
description: 'The status of the interview',
})
- @IsIn(['SCHEDULED', 'AWAITING_FEEDBACK', 'COMPLETED'])
+ //@IsIn(['SCHEDULED', 'AWAITING_FEEDBACK', 'COMPLETED'])
@IsOptional()
status?: InterviewStatus | string;
diff --git a/packages/api/src/ats/job/types/model.unified.ts b/packages/api/src/ats/job/types/model.unified.ts
index dde4d6842..6b44bc300 100644
--- a/packages/api/src/ats/job/types/model.unified.ts
+++ b/packages/api/src/ats/job/types/model.unified.ts
@@ -45,23 +45,23 @@ export class UnifiedAtsJobInput {
@ApiPropertyOptional({
type: String,
- enum: ['OPEN', 'CLOSED', 'DRAFT', 'ARCHIVED', 'PENDING'],
+ // enum: ['OPEN', 'CLOSED', 'DRAFT', 'ARCHIVED', 'PENDING'],
example: 'OPEN',
nullable: true,
description: 'The status of the job',
})
- @IsIn(['OPEN', 'CLOSED', 'DRAFT', 'ARCHIVED', 'PENDING'])
+ //@IsIn(['OPEN', 'CLOSED', 'DRAFT', 'ARCHIVED', 'PENDING'])
@IsOptional()
status?: JobStatus | string;
@ApiPropertyOptional({
type: String,
example: 'POSTING',
- enum: ['POSTING', 'REQUISITION', 'PROFILE'],
+ // enum: ['POSTING', 'REQUISITION', 'PROFILE'],
nullable: true,
description: 'The type of the job',
})
- @IsIn(['POSTING', 'REQUISITION', 'PROFILE'])
+ //@IsIn(['POSTING', 'REQUISITION', 'PROFILE'])
@IsOptional()
type?: JobType | string;
diff --git a/packages/api/src/ats/jobinterviewstage/types/model.unified.ts b/packages/api/src/ats/jobinterviewstage/types/model.unified.ts
index c963e3a9f..9f3e86188 100644
--- a/packages/api/src/ats/jobinterviewstage/types/model.unified.ts
+++ b/packages/api/src/ats/jobinterviewstage/types/model.unified.ts
@@ -24,7 +24,7 @@ export class UnifiedAtsJobinterviewstageInput {
nullable: true,
description: 'The order of the stage',
})
- @IsInt()
+ //@IsInt()
@IsOptional()
stage_order?: number;
diff --git a/packages/api/src/ats/offer/types/model.unified.ts b/packages/api/src/ats/offer/types/model.unified.ts
index 9d8636d47..704e84c32 100644
--- a/packages/api/src/ats/offer/types/model.unified.ts
+++ b/packages/api/src/ats/offer/types/model.unified.ts
@@ -71,7 +71,7 @@ export class UnifiedAtsOfferInput {
@ApiPropertyOptional({
type: String,
example: 'DRAFT',
- enum: [
+ /* enum: [
'DRAFT',
'APPROVAL_SENT',
'APPROVED',
@@ -81,11 +81,11 @@ export class UnifiedAtsOfferInput {
'DENIED',
'SIGNED',
'DEPRECATED',
- ],
+ ],*/
description: 'The status of the offer',
nullable: true,
})
- @IsIn([
+ /*@IsIn([
'DRAFT',
'APPROVAL_SENT',
'APPROVED',
@@ -95,7 +95,7 @@ export class UnifiedAtsOfferInput {
'DENIED',
'SIGNED',
'DEPRECATED',
- ])
+ ])*/
@IsOptional()
status?: OfferStatus | string;
diff --git a/packages/api/src/ats/scorecard/types/model.unified.ts b/packages/api/src/ats/scorecard/types/model.unified.ts
index 226d8e758..e75a05c45 100644
--- a/packages/api/src/ats/scorecard/types/model.unified.ts
+++ b/packages/api/src/ats/scorecard/types/model.unified.ts
@@ -17,12 +17,12 @@ export type ScoreCardRecommendation =
export class UnifiedAtsScorecardInput {
@ApiPropertyOptional({
type: String,
- enum: ['DEFINITELY_NO', 'NO', 'YES', 'STRONG_YES', 'NO_DECISION'],
+ // enum: ['DEFINITELY_NO', 'NO', 'YES', 'STRONG_YES', 'NO_DECISION'],
example: 'YES',
nullable: true,
description: 'The overall recommendation',
})
- @IsIn(['DEFINITELY_NO', 'NO', 'YES', 'STRONG_YES', 'NO_DECISION'])
+ //@IsIn(['DEFINITELY_NO', 'NO', 'YES', 'STRONG_YES', 'NO_DECISION'])
@IsOptional()
overall_recommendation?: ScoreCardRecommendation | string;
diff --git a/packages/api/src/ats/user/types/model.unified.ts b/packages/api/src/ats/user/types/model.unified.ts
index 7fc8e09fa..6b7f06c0e 100644
--- a/packages/api/src/ats/user/types/model.unified.ts
+++ b/packages/api/src/ats/user/types/model.unified.ts
@@ -59,23 +59,23 @@ export class UnifiedAtsUserInput {
@ApiPropertyOptional({
type: String,
example: 'ADMIN',
- enum: [
+ /* enum: [
'SUPER_ADMIN',
'ADMIN',
'TEAM_MEMBER',
'LIMITED_TEAM_MEMBER',
'INTERVIEWER',
- ],
+ ],*/
description: 'The access role of the user',
nullable: true,
})
- @IsIn([
+ /*@IsIn([
'SUPER_ADMIN',
'ADMIN',
'TEAM_MEMBER',
'LIMITED_TEAM_MEMBER',
'INTERVIEWER',
- ])
+ ])*/
@IsOptional()
access_role?: UserAccessRole | string;
diff --git a/packages/api/src/crm/@lib/@types/index.ts b/packages/api/src/crm/@lib/@types/index.ts
index 5def9dbd5..899868ba3 100644
--- a/packages/api/src/crm/@lib/@types/index.ts
+++ b/packages/api/src/crm/@lib/@types/index.ts
@@ -314,12 +314,12 @@ export class Email {
@ApiProperty({
type: String,
- enum: ['PERSONAL', 'WORK'],
+ //enum: ['PERSONAL', 'WORK'],
nullable: true,
description:
'The email address type. Authorized values are either PERSONAL or WORK.',
})
- @IsIn(['PERSONAL', 'WORK'])
+ ////@IsIn(['PERSONAL', 'WORK'])
@IsString()
email_address_type: string;
@@ -331,7 +331,7 @@ export class Email {
})
@IsString()
@IsOptional()
- @IsIn(['COMPANY', 'CONTACT'])
+ //@IsIn(['COMPANY', 'CONTACT'])
owner_type?: string;
}
@@ -347,11 +347,9 @@ export class Phone {
@ApiProperty({
type: String,
- enum: ['MOBILE', 'WORK'],
nullable: true,
description: 'The phone type. Authorized values are either MOBILE or WORK',
})
- @IsIn(['MOBILE', 'WORK'])
@IsString()
phone_type: string;
@@ -422,13 +420,11 @@ export class Address {
@ApiProperty({
type: String,
- enum: ['PERSONAL', 'WORK'],
nullable: true,
example: 'PERSONAL',
description:
'The address type. Authorized values are either PERSONAL or WORK.',
})
- @IsIn(['PERSONAL', 'WORK'])
@IsOptional()
@IsString()
address_type?: string;
diff --git a/packages/api/src/crm/company/types/model.unified.ts b/packages/api/src/crm/company/types/model.unified.ts
index 15b767fb2..be755551a 100644
--- a/packages/api/src/crm/company/types/model.unified.ts
+++ b/packages/api/src/crm/company/types/model.unified.ts
@@ -21,7 +21,7 @@ export class UnifiedCrmCompanyInput {
@ApiPropertyOptional({
type: String,
example: 'ACCOUNTING',
- enum: Industry,
+ // enum: Industry,
description:
'The industry of the company. Authorized values can be found in the Industry enum.',
nullable: true,
diff --git a/packages/api/src/crm/contact/contact.controller.ts b/packages/api/src/crm/contact/contact.controller.ts
index 18fc6e3b8..ecb025767 100644
--- a/packages/api/src/crm/contact/contact.controller.ts
+++ b/packages/api/src/crm/contact/contact.controller.ts
@@ -62,12 +62,16 @@ export class ContactController {
@ApiPaginatedResponse(UnifiedCrmContactOutput)
@UseGuards(ApiKeyAuthGuard)
@Get()
- @UsePipes(new ValidationPipe({ transform: true, disableErrorMessages: true }))
+ @UsePipes(
+ new ValidationPipe({ transform: true, disableErrorMessages: false }),
+ )
async getContacts(
@Headers('x-connection-token') connection_token: string,
@Query() query: QueryDto,
) {
try {
+ console.log('Received connection_token:', connection_token);
+ console.log('Received query:', JSON.stringify(query));
const { linkedUserId, remoteSource, connectionId, projectId } =
await this.connectionUtils.getConnectionMetadataFromConnectionToken(
connection_token,
diff --git a/packages/api/src/crm/contact/services/hubspot/mappers.ts b/packages/api/src/crm/contact/services/hubspot/mappers.ts
index 95a2649d8..14d75d496 100644
--- a/packages/api/src/crm/contact/services/hubspot/mappers.ts
+++ b/packages/api/src/crm/contact/services/hubspot/mappers.ts
@@ -143,14 +143,14 @@ export class HubspotContactMapper implements IContactMapper {
email_addresses: [
{
email_address: contact.properties.email,
- email_address_type: 'primary',
+ email_address_type: 'PERSONAL',
owner_type: 'contact',
},
],
phone_numbers: [
{
phone_number: contact.properties.phone,
- phone_type: 'primary',
+ phone_type: 'PERSONAL',
owner_type: 'contact',
},
],
diff --git a/packages/api/src/crm/contact/services/zendesk/mappers.ts b/packages/api/src/crm/contact/services/zendesk/mappers.ts
index 83fad6e19..832d5d3a5 100644
--- a/packages/api/src/crm/contact/services/zendesk/mappers.ts
+++ b/packages/api/src/crm/contact/services/zendesk/mappers.ts
@@ -113,17 +113,17 @@ export class ZendeskContactMapper implements IContactMapper {
}
// Constructing the email and phone details
const email_addresses = contact.email
- ? [{ email_address: contact.email, email_address_type: 'primary' }]
+ ? [{ email_address: contact.email, email_address_type: 'PERSONAL' }]
: [];
const phone_numbers = [];
if (contact.phone) {
- phone_numbers.push({ phone_number: contact.phone, phone_type: 'work' });
+ phone_numbers.push({ phone_number: contact.phone, phone_type: 'WORK' });
}
if (contact.mobile) {
phone_numbers.push({
phone_number: contact.mobile,
- phone_type: 'mobile',
+ phone_type: 'MOBILE',
});
}
diff --git a/packages/api/src/crm/contact/services/zoho/mappers.ts b/packages/api/src/crm/contact/services/zoho/mappers.ts
index 81ca7ca5b..8f22d0ef5 100644
--- a/packages/api/src/crm/contact/services/zoho/mappers.ts
+++ b/packages/api/src/crm/contact/services/zoho/mappers.ts
@@ -124,13 +124,13 @@ export class ZohoContactMapper implements IContactMapper {
if (contact && contact.Fax) {
phone_numbers.push({
phone_number: contact.Fax,
- phone_type: 'fax',
+ phone_type: 'FAX',
});
}
if (contact && contact.Home_Phone) {
phone_numbers.push({
phone_number: contact.Home_Phone,
- phone_type: 'home',
+ phone_type: 'HOME',
});
}
diff --git a/packages/api/src/crm/engagement/types/model.unified.ts b/packages/api/src/crm/engagement/types/model.unified.ts
index 2c1581c88..528e30ec7 100644
--- a/packages/api/src/crm/engagement/types/model.unified.ts
+++ b/packages/api/src/crm/engagement/types/model.unified.ts
@@ -19,13 +19,13 @@ export class UnifiedCrmEngagementInput {
type: String,
nullable: true,
example: 'INBOUND',
- enum: ['INBOUND', 'OUTBOUND'],
+ // enum: ['INBOUND', 'OUTBOUND'],
description:
'The direction of the engagement. Authorized values are INBOUND or OUTBOUND',
})
- @IsIn(['INBOUND', 'OUTBOUND'], {
+ /*@IsIn(['INBOUND', 'OUTBOUND'], {
message: 'Direction must be either INBOUND or OUTBOUND',
- })
+ })*/
@IsOptional()
direction?: EngagementDirection | string;
@@ -61,13 +61,13 @@ export class UnifiedCrmEngagementInput {
type: String,
nullable: true,
example: 'MEETING',
- enum: ['EMAIL', 'CALL', 'MEETING'],
+ // enum: ['EMAIL', 'CALL', 'MEETING'],
description:
'The type of the engagement. Authorized values are EMAIL, CALL or MEETING',
})
- @IsIn(['EMAIL', 'CALL', 'MEETING'], {
+ /*@IsIn(['EMAIL', 'CALL', 'MEETING'], {
message: 'Type must be either EMAIL, CALL or MEETING',
- })
+ })*/
type?: EngagementType | string;
@ApiPropertyOptional({
diff --git a/packages/api/src/crm/task/types/model.unified.ts b/packages/api/src/crm/task/types/model.unified.ts
index 78f4c280c..57be7f4cf 100644
--- a/packages/api/src/crm/task/types/model.unified.ts
+++ b/packages/api/src/crm/task/types/model.unified.ts
@@ -24,14 +24,14 @@ export class UnifiedCrmTaskInput {
@ApiProperty({
type: String,
example: 'PENDING',
- enum: ['PENDING', 'COMPLETED'],
+ // enum: ['PENDING', 'COMPLETED'],
description:
'The status of the task. Authorized values are PENDING, COMPLETED.',
nullable: true,
})
- @IsIn(['PENDING', 'COMPLETED'], {
+ /*@IsIn(['PENDING', 'COMPLETED'], {
message: 'Type must be either PENDING or COMPLETED',
- })
+ })*/
status: TaskStatus | string;
@ApiPropertyOptional({
diff --git a/packages/api/src/ecommerce/@lib/@types/index.ts b/packages/api/src/ecommerce/@lib/@types/index.ts
index c0261f61d..ad393e730 100644
--- a/packages/api/src/ecommerce/@lib/@types/index.ts
+++ b/packages/api/src/ecommerce/@lib/@types/index.ts
@@ -108,13 +108,13 @@ export class Address {
@ApiProperty({
type: String,
- enum: ['SHIPPING', 'BILLING'],
+ //enum: ['SHIPPING', 'BILLING'],
example: 'SHIPPING',
nullable: true,
description:
'The address type. Authorized values are either SHIPPING or BILLING.',
})
- @IsIn(['SHIPPING', 'BILLING'])
+ ////@IsIn(['SHIPPING', 'BILLING'])
@IsOptional()
@IsString()
address_type?: 'SHIPPING' | 'BILLING' | string;
diff --git a/packages/api/src/ecommerce/order/types/model.unified.ts b/packages/api/src/ecommerce/order/types/model.unified.ts
index fa98aef8e..bc9bd95b6 100644
--- a/packages/api/src/ecommerce/order/types/model.unified.ts
+++ b/packages/api/src/ecommerce/order/types/model.unified.ts
@@ -44,11 +44,11 @@ export class UnifiedEcommerceOrderInput {
@ApiPropertyOptional({
type: String,
example: 'UNSHIPPED',
- enum: ['PENDING', 'UNSHIPPED', 'SHIPPED', 'CANCELED'],
+ // enum: ['PENDING', 'UNSHIPPED', 'SHIPPED', 'CANCELED'],
nullable: true,
description: 'The status of the order',
})
- @IsIn(['PENDING', 'UNSHIPPED', 'SHIPPED', 'CANCELED'])
+ //@IsIn(['PENDING', 'UNSHIPPED', 'SHIPPED', 'CANCELED'])
@IsOptional()
order_status?: OrderStatus | string;
@@ -65,11 +65,11 @@ export class UnifiedEcommerceOrderInput {
@ApiPropertyOptional({
type: String,
example: 'SUCCESS',
- enum: ['SUCCESS', 'FAIL'],
+ // enum: ['SUCCESS', 'FAIL'],
nullable: true,
description: 'The payment status of the order',
})
- @IsIn(['SUCCESS', 'FAIL'])
+ //@IsIn(['SUCCESS', 'FAIL'])
@IsOptional()
payment_status?: 'SUCCESS' | 'FAIL' | string;
@@ -77,7 +77,7 @@ export class UnifiedEcommerceOrderInput {
type: String,
nullable: true,
example: 'AUD',
- enum: CurrencyCode,
+ // enum: CurrencyCode,
description:
'The currency of the order. Authorized value must be of type CurrencyCode (ISO 4217)',
})
@@ -91,7 +91,7 @@ export class UnifiedEcommerceOrderInput {
nullable: true,
description: 'The total price of the order',
})
- @IsInt()
+ //@IsInt()
@IsOptional()
total_price?: number;
@@ -101,7 +101,7 @@ export class UnifiedEcommerceOrderInput {
nullable: true,
description: 'The total discount on the order',
})
- @IsInt()
+ //@IsInt()
@IsOptional()
total_discount?: number;
@@ -111,7 +111,7 @@ export class UnifiedEcommerceOrderInput {
nullable: true,
description: 'The total shipping cost of the order',
})
- @IsInt()
+ //@IsInt()
@IsOptional()
total_shipping?: number;
@@ -121,7 +121,7 @@ export class UnifiedEcommerceOrderInput {
nullable: true,
description: 'The total tax on the order',
})
- @IsInt()
+ //@IsInt()
@IsOptional()
total_tax?: number;
@@ -129,10 +129,10 @@ export class UnifiedEcommerceOrderInput {
type: String,
nullable: true,
example: 'PENDING',
- enum: ['PENDING', 'FULFILLED', 'CANCELED'],
+ // enum: ['PENDING', 'FULFILLED', 'CANCELED'],
description: 'The fulfillment status of the order',
})
- @IsIn(['PENDING', 'FULFILLED', 'CANCELED'])
+ //@IsIn(['PENDING', 'FULFILLED', 'CANCELED'])
@IsOptional()
fulfillment_status?: FulfillmentStatus | string;
diff --git a/packages/api/src/ecommerce/product/types/model.unified.ts b/packages/api/src/ecommerce/product/types/model.unified.ts
index 3dce5514f..f2e36216a 100644
--- a/packages/api/src/ecommerce/product/types/model.unified.ts
+++ b/packages/api/src/ecommerce/product/types/model.unified.ts
@@ -41,10 +41,10 @@ export class UnifiedEcommerceProductInput {
type: String,
example: 'ACTIVE',
nullable: true,
- enum: ['ARCHIVED', 'ACTIVE', 'DRAFT'],
+ // enum: ['ARCHIVED', 'ACTIVE', 'DRAFT'],
description: 'The status of the product. Either ACTIVE, DRAFT OR ARCHIVED.',
})
- @IsIn(['ARCHIVED', 'ACTIVE', 'DRAFT'])
+ //@IsIn(['ARCHIVED', 'ACTIVE', 'DRAFT'])
@IsOptional()
product_status?: string;
diff --git a/packages/api/src/filestorage/permission/types/model.unified.ts b/packages/api/src/filestorage/permission/types/model.unified.ts
index 6cc360379..33dd0741b 100644
--- a/packages/api/src/filestorage/permission/types/model.unified.ts
+++ b/packages/api/src/filestorage/permission/types/model.unified.ts
@@ -8,7 +8,7 @@ export class UnifiedFilestoragePermissionInput {
@ApiProperty({
type: [String],
example: ['READ'],
- enum: ['READ', 'WRITE', 'OWNER'],
+ // enum: ['READ', 'WRITE', 'OWNER'],
nullable: true,
description: 'The roles of the permission',
})
@@ -17,12 +17,12 @@ export class UnifiedFilestoragePermissionInput {
@ApiProperty({
type: String,
- enum: ['USER', 'GROUP', 'COMPANY', 'ANYONE'],
+ // enum: ['USER', 'GROUP', 'COMPANY', 'ANYONE'],
example: 'USER',
nullable: true,
description: 'The type of the permission',
})
- @IsIn(['USER', 'GROUP', 'COMPANY', 'ANYONE'])
+ //@IsIn(['USER', 'GROUP', 'COMPANY', 'ANYONE'])
@IsString()
type: PermissionType | string;
diff --git a/packages/api/src/hris/bankinfo/types/model.unified.ts b/packages/api/src/hris/bankinfo/types/model.unified.ts
index e3a7cbe3b..750acc65a 100644
--- a/packages/api/src/hris/bankinfo/types/model.unified.ts
+++ b/packages/api/src/hris/bankinfo/types/model.unified.ts
@@ -13,7 +13,7 @@ export class UnifiedHrisBankinfoInput {
@ApiPropertyOptional({
type: String,
example: 'CHECKING',
- enum: ['SAVINGS', 'CHECKING'],
+ // enum: ['SAVINGS', 'CHECKING'],
nullable: true,
description: 'The type of the bank account',
})
diff --git a/packages/api/src/hris/dependent/types/model.unified.ts b/packages/api/src/hris/dependent/types/model.unified.ts
index 70eedd34e..c1e2add3f 100644
--- a/packages/api/src/hris/dependent/types/model.unified.ts
+++ b/packages/api/src/hris/dependent/types/model.unified.ts
@@ -50,7 +50,7 @@ export class UnifiedHrisDependentInput {
@ApiPropertyOptional({
type: String,
example: 'CHILD',
- enum: ['CHILD', 'SPOUSE', 'DOMESTIC_PARTNER'],
+ // enum: ['CHILD', 'SPOUSE', 'DOMESTIC_PARTNER'],
nullable: true,
description: 'The relationship of the dependent to the employee',
})
@@ -71,7 +71,7 @@ export class UnifiedHrisDependentInput {
@ApiPropertyOptional({
type: String,
example: 'MALE',
- enum: ['MALE', 'FEMALE', 'NON-BINARY', 'OTHER', 'PREFER_NOT_TO_DISCLOSE'],
+ // enum: ['MALE', 'FEMALE', 'NON-BINARY', 'OTHER', 'PREFER_NOT_TO_DISCLOSE'],
nullable: true,
description: 'The gender of the dependent',
})
diff --git a/packages/api/src/hris/employee/types/model.unified.ts b/packages/api/src/hris/employee/types/model.unified.ts
index a7c6e8239..335e2ba49 100644
--- a/packages/api/src/hris/employee/types/model.unified.ts
+++ b/packages/api/src/hris/employee/types/model.unified.ts
@@ -184,7 +184,7 @@ export class UnifiedHrisEmployeeInput {
@ApiPropertyOptional({
type: String,
example: 'MALE',
- enum: ['MALE', 'FEMALE', 'NON-BINARY', 'OTHER', 'PREFER_NOT_TO_DISCLOSE'],
+ // enum: ['MALE', 'FEMALE', 'NON-BINARY', 'OTHER', 'PREFER_NOT_TO_DISCLOSE'],
nullable: true,
description: 'The gender of the employee',
})
@@ -195,7 +195,7 @@ export class UnifiedHrisEmployeeInput {
@ApiPropertyOptional({
type: String,
example: 'AMERICAN_INDIAN_OR_ALASKA_NATIVE',
- enum: [
+ /* enum: [
'AMERICAN_INDIAN_OR_ALASKA_NATIVE',
'ASIAN_OR_INDIAN_SUBCONTINENT',
'BLACK_OR_AFRICAN_AMERICAN',
@@ -204,7 +204,7 @@ export class UnifiedHrisEmployeeInput {
'TWO_OR_MORE_RACES',
'WHITE',
'PREFER_NOT_TO_DISCLOSE',
- ],
+ ],*/
nullable: true,
description: 'The ethnicity of the employee',
})
@@ -215,13 +215,13 @@ export class UnifiedHrisEmployeeInput {
@ApiPropertyOptional({
type: String,
example: 'Married',
- enum: [
+ /* enum: [
'SINGLE',
'MARRIED_FILING_JOINTLY',
'MARRIED_FILING_SEPARATELY',
'HEAD_OF_HOUSEHOLD',
'QUALIFYING_WIDOW_OR_WIDOWER_WITH_DEPENDENT_CHILD',
- ],
+ ],*/
nullable: true,
description: 'The marital status of the employee',
})
@@ -252,7 +252,7 @@ export class UnifiedHrisEmployeeInput {
@ApiPropertyOptional({
type: String,
example: 'ACTIVE',
- enum: ['ACTIVE', 'PENDING', 'INACTIVE'],
+ // enum: ['ACTIVE', 'PENDING', 'INACTIVE'],
nullable: true,
description: 'The employment status of the employee',
})
diff --git a/packages/api/src/hris/employerbenefit/types/model.unified.ts b/packages/api/src/hris/employerbenefit/types/model.unified.ts
index 3f280edb6..46852f391 100644
--- a/packages/api/src/hris/employerbenefit/types/model.unified.ts
+++ b/packages/api/src/hris/employerbenefit/types/model.unified.ts
@@ -17,7 +17,7 @@ export class UnifiedHrisEmployerbenefitInput {
@ApiPropertyOptional({
type: String,
example: 'Health Insurance',
- enum: ['MEDICAL', 'HEALTH_SAVINGS', 'INSURANCE', 'RETIREMENT', 'OTHER'],
+ // enum: ['MEDICAL', 'HEALTH_SAVINGS', 'INSURANCE', 'RETIREMENT', 'OTHER'],
nullable: true,
description: 'The type of the benefit plan',
})
diff --git a/packages/api/src/hris/employment/types/model.unified.ts b/packages/api/src/hris/employment/types/model.unified.ts
index aef4d7031..857744110 100644
--- a/packages/api/src/hris/employment/types/model.unified.ts
+++ b/packages/api/src/hris/employment/types/model.unified.ts
@@ -68,7 +68,7 @@ export class UnifiedHrisEmploymentInput {
@ApiPropertyOptional({
type: String,
example: 'MONTHLY',
- enum: [
+ /* enum: [
'HOUR',
'DAY',
'WEEK',
@@ -78,7 +78,7 @@ export class UnifiedHrisEmploymentInput {
'QUARTER',
'EVERY_SIX_MONTHS',
'YEAR',
- ],
+ ],*/
nullable: true,
description: 'The pay period of the employment',
})
@@ -89,7 +89,7 @@ export class UnifiedHrisEmploymentInput {
@ApiPropertyOptional({
type: String,
example: 'WEEKLY',
- enum: [
+ /* enum: [
'WEEKLY',
'BIWEEKLY',
'MONTHLY',
@@ -99,7 +99,7 @@ export class UnifiedHrisEmploymentInput {
'THIRTEEN-MONTHLY',
'PRO_RATA',
'SEMIMONTHLY',
- ],
+ ],*/
nullable: true,
description: 'The pay frequency of the employment',
})
@@ -110,7 +110,7 @@ export class UnifiedHrisEmploymentInput {
@ApiPropertyOptional({
type: String,
example: 'USD',
- enum: CurrencyCode,
+ // enum: CurrencyCode,
nullable: true,
description: 'The currency of the pay',
})
@@ -121,7 +121,7 @@ export class UnifiedHrisEmploymentInput {
@ApiPropertyOptional({
type: String,
example: 'EXEMPT',
- enum: ['EXEMPT', 'SALARIED_NONEXEMPT', 'NONEXEMPT', 'OWNER'],
+ // enum: ['EXEMPT', 'SALARIED_NONEXEMPT', 'NONEXEMPT', 'OWNER'],
nullable: true,
description: 'The FLSA status of the employment',
})
@@ -142,7 +142,7 @@ export class UnifiedHrisEmploymentInput {
@ApiPropertyOptional({
type: String,
example: 'FULL_TIME',
- enum: ['FULL_TIME', 'PART_TIME', 'INTERN', 'CONTRACTOR', 'FREELANCE'],
+ // enum: ['FULL_TIME', 'PART_TIME', 'INTERN', 'CONTRACTOR', 'FREELANCE'],
nullable: true,
description: 'The type of employment',
})
diff --git a/packages/api/src/hris/group/types/model.unified.ts b/packages/api/src/hris/group/types/model.unified.ts
index 6ce238ae6..7ecb4085b 100644
--- a/packages/api/src/hris/group/types/model.unified.ts
+++ b/packages/api/src/hris/group/types/model.unified.ts
@@ -37,7 +37,7 @@ export class UnifiedHrisGroupInput {
@ApiPropertyOptional({
type: String,
example: 'DEPARTMENT',
- enum: ['TEAM', 'DEPARTMENT', 'COST_CENTER', 'BUSINESS_UNIT', 'GROUP'],
+ // enum: ['TEAM', 'DEPARTMENT', 'COST_CENTER', 'BUSINESS_UNIT', 'GROUP'],
nullable: true,
description: 'The type of the group',
})
diff --git a/packages/api/src/hris/location/types/model.unified.ts b/packages/api/src/hris/location/types/model.unified.ts
index 7c2fa11da..5bf6593cb 100644
--- a/packages/api/src/hris/location/types/model.unified.ts
+++ b/packages/api/src/hris/location/types/model.unified.ts
@@ -93,12 +93,12 @@ export class UnifiedHrisLocationInput {
@ApiPropertyOptional({
type: String,
example: 'WORK',
- enum: ['WORK', 'HOME'],
+ // enum: ['WORK', 'HOME'],
nullable: true,
description: 'The type of the location',
})
@IsString()
- @IsIn(['WORK', 'HOME'])
+ //@IsIn(['WORK', 'HOME'])
@IsOptional()
location_type?: LocationType | string;
diff --git a/packages/api/src/hris/payrollrun/types/model.unified.ts b/packages/api/src/hris/payrollrun/types/model.unified.ts
index 29a95f9fd..23e77e40f 100644
--- a/packages/api/src/hris/payrollrun/types/model.unified.ts
+++ b/packages/api/src/hris/payrollrun/types/model.unified.ts
@@ -18,7 +18,7 @@ export class UnifiedHrisPayrollrunInput {
@ApiPropertyOptional({
type: String,
example: 'PAID',
- enum: ['PAID', 'DRAFT', 'APPROVED', 'FAILED', 'CLOSE'],
+ // enum: ['PAID', 'DRAFT', 'APPROVED', 'FAILED', 'CLOSE'],
nullable: true,
description: 'The state of the payroll run',
})
@@ -29,13 +29,13 @@ export class UnifiedHrisPayrollrunInput {
@ApiPropertyOptional({
type: String,
example: 'REGULAR',
- enum: [
+ /* enum: [
'REGULAR',
'OFF_CYCLE',
'CORRECTION',
'TERMINATION',
'SIGN_ON_BONUS',
- ],
+ ],*/
nullable: true,
description: 'The type of the payroll run',
})
diff --git a/packages/api/src/hris/timeoff/types/model.unified.ts b/packages/api/src/hris/timeoff/types/model.unified.ts
index ab9a25343..8af5a3284 100644
--- a/packages/api/src/hris/timeoff/types/model.unified.ts
+++ b/packages/api/src/hris/timeoff/types/model.unified.ts
@@ -46,7 +46,7 @@ export class UnifiedHrisTimeoffInput {
@ApiPropertyOptional({
type: String,
example: 'REQUESTED',
- enum: ['REQUESTED', 'APPROVED', 'DECLINED', 'CANCELLED', 'DELETED'],
+ // enum: ['REQUESTED', 'APPROVED', 'DECLINED', 'CANCELLED', 'DELETED'],
nullable: true,
description: 'The status of the time off request',
})
@@ -67,7 +67,7 @@ export class UnifiedHrisTimeoffInput {
@ApiPropertyOptional({
type: String,
example: 'DAYS',
- enum: ['HOURS', 'DAYS'],
+ // enum: ['HOURS', 'DAYS'],
nullable: true,
description: 'The units used for the time off (e.g., Days, Hours)',
})
@@ -88,14 +88,14 @@ export class UnifiedHrisTimeoffInput {
@ApiPropertyOptional({
type: String,
example: 'VACATION',
- enum: [
+ /* enum: [
'VACATION',
'SICK',
'PERSONAL',
'JURY_DUTY',
'VOLUNTEER',
'BEREAVEMENT',
- ],
+ ],*/
nullable: true,
description: 'The type of time off request',
})
diff --git a/packages/api/src/hris/timeoffbalance/types/model.unified.ts b/packages/api/src/hris/timeoffbalance/types/model.unified.ts
index ae45a58ae..941825f82 100644
--- a/packages/api/src/hris/timeoffbalance/types/model.unified.ts
+++ b/packages/api/src/hris/timeoffbalance/types/model.unified.ts
@@ -50,14 +50,14 @@ export class UnifiedHrisTimeoffbalanceInput {
@ApiPropertyOptional({
type: String,
example: 'VACATION',
- enum: [
+ /*enum: [
'VACATION',
'SICK',
'PERSONAL',
'JURY_DUTY',
'VOLUNTEER',
'BEREAVEMENT',
- ],
+ ],*/
nullable: true,
description: 'The type of time off policy',
})
diff --git a/packages/api/src/ticketing/collection/types/model.unified.ts b/packages/api/src/ticketing/collection/types/model.unified.ts
index 41a321f29..9662d414f 100644
--- a/packages/api/src/ticketing/collection/types/model.unified.ts
+++ b/packages/api/src/ticketing/collection/types/model.unified.ts
@@ -26,14 +26,14 @@ export class UnifiedTicketingCollectionInput {
@ApiPropertyOptional({
type: String,
example: 'PROJECT',
- enum: ['PROJECT', 'LIST'],
+ // enum: ['PROJECT', 'LIST'],
nullable: true,
description:
'The type of the collection. Authorized values are either PROJECT or LIST ',
})
- @IsIn(['PROJECT', 'LIST'], {
+ /*@IsIn(['PROJECT', 'LIST'], {
message: 'Type must be either PROJECT or LIST',
- })
+ })*/
@IsOptional()
collection_type?: CollectionType | string;
}
diff --git a/packages/api/src/ticketing/comment/types/model.unified.ts b/packages/api/src/ticketing/comment/types/model.unified.ts
index 753c6e1b2..aa7ead01d 100644
--- a/packages/api/src/ticketing/comment/types/model.unified.ts
+++ b/packages/api/src/ticketing/comment/types/model.unified.ts
@@ -42,13 +42,13 @@ export class UnifiedTicketingCommentInput {
type: String,
nullable: true,
example: 'USER',
- enum: ['USER', 'CONTACT'],
+ // enum: ['USER', 'CONTACT'],
description:
'The creator type of the comment. Authorized values are either USER or CONTACT',
})
- @IsIn(['USER', 'CONTACT'], {
+ /*@IsIn(['USER', 'CONTACT'], {
message: 'Type must be either USER or CONTACT',
- })
+ })*/
@IsOptional()
creator_type?: CommentCreatorType | string;
diff --git a/packages/api/src/ticketing/ticket/types/model.unified.ts b/packages/api/src/ticketing/ticket/types/model.unified.ts
index 80da04fa3..8c0de3734 100644
--- a/packages/api/src/ticketing/ticket/types/model.unified.ts
+++ b/packages/api/src/ticketing/ticket/types/model.unified.ts
@@ -26,14 +26,14 @@ export class UnifiedTicketingTicketInput {
@ApiPropertyOptional({
type: String,
example: 'OPEN',
- enum: ['OPEN', 'CLOSED'],
+ // enum: ['OPEN', 'CLOSED'],
nullable: true,
description:
'The status of the ticket. Authorized values are OPEN or CLOSED.',
})
- @IsIn(['OPEN', 'CLOSED'], {
+ /*@IsIn(['OPEN', 'CLOSED'], {
message: 'Type must be either OPEN or CLOSED',
- })
+ })*/
@IsOptional()
status?: TicketStatus | string;
@@ -58,14 +58,14 @@ export class UnifiedTicketingTicketInput {
@ApiPropertyOptional({
type: String,
example: 'BUG',
- enum: ['BUG', 'SUBTASK', 'TASK', 'TO-DO'],
+ // enum: ['BUG', 'SUBTASK', 'TASK', 'TO-DO'],
nullable: true,
description:
'The type of the ticket. Authorized values are PROBLEM, QUESTION, or TASK',
})
- @IsIn(['BUG', 'SUBTASK', 'TASK', 'TO-DO'], {
+ /*@IsIn(['BUG', 'SUBTASK', 'TASK', 'TO-DO'], {
message: 'Type must be either BUG, SUBTASK, TASK or TO-DO',
- })
+ })*/
@IsOptional()
type?: TicketType | string;
@@ -122,14 +122,14 @@ export class UnifiedTicketingTicketInput {
@ApiPropertyOptional({
type: String,
example: 'HIGH',
- enum: ['HIGH', 'MEDIUM', 'LOW'],
+ // enum: ['HIGH', 'MEDIUM', 'LOW'],
nullable: true,
description:
'The priority of the ticket. Authorized values are HIGH, MEDIUM or LOW.',
})
- @IsIn(['HIGH', 'MEDIUM', 'LOW'], {
+ /*@IsIn(['HIGH', 'MEDIUM', 'LOW'], {
message: 'Type must be either HIGH, MEDIUM or LOW',
- })
+ })*/
@IsOptional()
priority?: TicketPriority | string;
diff --git a/packages/api/swagger/swagger-spec.yaml b/packages/api/swagger/swagger-spec.yaml
index 8abc627f7..6a58b8106 100644
--- a/packages/api/swagger/swagger-spec.yaml
+++ b/packages/api/swagger/swagger-spec.yaml
@@ -9872,9 +9872,6 @@ components:
type: string
nullable: true
example: USER
- enum: &ref_121
- - USER
- - CONTACT
description: >-
The creator type of the comment. Authorized values are either USER
or CONTACT
@@ -9899,12 +9896,12 @@ components:
specified)
attachments:
type: array
- items: &ref_122
+ items: &ref_114
oneOf:
- type: string
- $ref: '#/components/schemas/UnifiedTicketingAttachmentOutput'
nullable: true
- example: &ref_123
+ example: &ref_115
- 801f9ede-c698-4e66-a7fc-48d19eebaa4f
description: The attachements UUIDs tied to the comment
required:
@@ -9920,9 +9917,6 @@ components:
status:
type: string
example: OPEN
- enum: &ref_92
- - OPEN
- - CLOSED
nullable: true
description: The status of the ticket. Authorized values are OPEN or CLOSED.
description:
@@ -9939,11 +9933,6 @@ components:
type:
type: string
example: BUG
- enum: &ref_93
- - BUG
- - SUBTASK
- - TASK
- - TO-DO
nullable: true
description: >-
The type of the ticket. Authorized values are PROBLEM, QUESTION, or
@@ -9955,21 +9944,21 @@ components:
description: The UUID of the parent ticket
collections:
type: array
- items: &ref_94
+ items: &ref_92
oneOf:
- type: string
- $ref: '#/components/schemas/UnifiedTicketingCollectionOutput'
- example: &ref_95
+ example: &ref_93
- 801f9ede-c698-4e66-a7fc-48d19eebaa4f
nullable: true
description: The collection UUIDs the ticket belongs to
tags:
type: array
- items: &ref_96
+ items: &ref_94
oneOf:
- type: string
- $ref: '#/components/schemas/UnifiedTicketingTagOutput'
- example: &ref_97
+ example: &ref_95
- my_tag
- urgent_tag
nullable: true
@@ -9983,16 +9972,12 @@ components:
priority:
type: string
example: HIGH
- enum: &ref_98
- - HIGH
- - MEDIUM
- - LOW
nullable: true
description: >-
The priority of the ticket. Authorized values are HIGH, MEDIUM or
LOW.
assigned_to:
- example: &ref_99
+ example: &ref_96
- 801f9ede-c698-4e66-a7fc-48d19eebaa4f
nullable: true
description: The users UUIDs the ticket is assigned to
@@ -10000,7 +9985,7 @@ components:
items:
type: string
comment:
- example: &ref_100
+ example: &ref_97
content: Assigned the issue !
nullable: true
description: The comment of the ticket
@@ -10018,17 +10003,17 @@ components:
description: The UUID of the contact which the ticket belongs to
attachments:
type: array
- items: &ref_101
+ items: &ref_98
oneOf:
- type: string
- $ref: '#/components/schemas/UnifiedTicketingAttachmentInput'
- example: &ref_102
+ example: &ref_99
- 801f9ede-c698-4e66-a7fc-48d19eebaa4f
description: The attachements UUIDs tied to the ticket
nullable: true
field_mappings:
type: object
- example: &ref_103
+ example: &ref_100
fav_dish: broccoli
fav_color: red
nullable: true
@@ -10081,7 +10066,6 @@ components:
status:
type: string
example: OPEN
- enum: *ref_92
nullable: true
description: The status of the ticket. Authorized values are OPEN or CLOSED.
description:
@@ -10098,7 +10082,6 @@ components:
type:
type: string
example: BUG
- enum: *ref_93
nullable: true
description: >-
The type of the ticket. Authorized values are PROBLEM, QUESTION, or
@@ -10110,14 +10093,14 @@ components:
description: The UUID of the parent ticket
collections:
type: array
- items: *ref_94
- example: *ref_95
+ items: *ref_92
+ example: *ref_93
nullable: true
description: The collection UUIDs the ticket belongs to
tags:
type: array
- items: *ref_96
- example: *ref_97
+ items: *ref_94
+ example: *ref_95
nullable: true
description: The tags names of the ticket
completed_at:
@@ -10129,20 +10112,19 @@ components:
priority:
type: string
example: HIGH
- enum: *ref_98
nullable: true
description: >-
The priority of the ticket. Authorized values are HIGH, MEDIUM or
LOW.
assigned_to:
- example: *ref_99
+ example: *ref_96
nullable: true
description: The users UUIDs the ticket is assigned to
type: array
items:
type: string
comment:
- example: *ref_100
+ example: *ref_97
nullable: true
description: The comment of the ticket
allOf:
@@ -10159,13 +10141,13 @@ components:
description: The UUID of the contact which the ticket belongs to
attachments:
type: array
- items: *ref_101
- example: *ref_102
+ items: *ref_98
+ example: *ref_99
description: The attachements UUIDs tied to the ticket
nullable: true
field_mappings:
type: object
- example: *ref_103
+ example: *ref_100
nullable: true
description: >-
The custom field mappings of the ticket between the remote 3rd party
@@ -10415,9 +10397,6 @@ components:
description: The email address
email_address_type:
type: string
- enum:
- - PERSONAL
- - WORK
nullable: true
description: >-
The email address type. Authorized values are either PERSONAL or
@@ -10467,9 +10446,6 @@ components:
description: The country
address_type:
type: string
- enum:
- - PERSONAL
- - WORK
nullable: true
example: PERSONAL
description: The address type. Authorized values are either PERSONAL or WORK.
@@ -10497,9 +10473,6 @@ components:
code (e.g +336676778890 for France)
phone_type:
type: string
- enum:
- - MOBILE
- - WORK
nullable: true
description: The phone type. Authorized values are either MOBILE or WORK
owner_type:
@@ -10520,154 +10493,6 @@ components:
industry:
type: string
example: ACCOUNTING
- enum: &ref_104
- - ACCOUNTING
- - AIRLINES_AVIATION
- - ALTERNATIVE_DISPUTE_RESOLUTION
- - ALTERNATIVE_MEDICINE
- - ANIMATION
- - APPAREL_FASHION
- - ARCHITECTURE_PLANNING
- - ARTS_AND_CRAFTS
- - AUTOMOTIVE
- - AVIATION_AEROSPACE
- - BANKING
- - BIOTECHNOLOGY
- - BROADCAST_MEDIA
- - BUILDING_MATERIALS
- - BUSINESS_SUPPLIES_AND_EQUIPMENT
- - CAPITAL_MARKETS
- - CHEMICALS
- - CIVIC_SOCIAL_ORGANIZATION
- - CIVIL_ENGINEERING
- - COMMERCIAL_REAL_ESTATE
- - COMPUTER_NETWORK_SECURITY
- - COMPUTER_GAMES
- - COMPUTER_HARDWARE
- - COMPUTER_NETWORKING
- - COMPUTER_SOFTWARE
- - INTERNET
- - CONSTRUCTION
- - CONSUMER_ELECTRONICS
- - CONSUMER_GOODS
- - CONSUMER_SERVICES
- - COSMETICS
- - DAIRY
- - DEFENSE_SPACE
- - DESIGN
- - EDUCATION_MANAGEMENT
- - E_LEARNING
- - ELECTRICAL_ELECTRONIC_MANUFACTURING
- - ENTERTAINMENT
- - ENVIRONMENTAL_SERVICES
- - EVENTS_SERVICES
- - EXECUTIVE_OFFICE
- - FACILITIES_SERVICES
- - FARMING
- - FINANCIAL_SERVICES
- - FINE_ART
- - FISHERY
- - FOOD_BEVERAGES
- - FOOD_PRODUCTION
- - FUND_RAISING
- - FURNITURE
- - GAMBLING_CASINOS
- - GLASS_CERAMICS_CONCRETE
- - GOVERNMENT_ADMINISTRATION
- - GOVERNMENT_RELATIONS
- - GRAPHIC_DESIGN
- - HEALTH_WELLNESS_AND_FITNESS
- - HIGHER_EDUCATION
- - HOSPITAL_HEALTH_CARE
- - HOSPITALITY
- - HUMAN_RESOURCES
- - IMPORT_AND_EXPORT
- - INDIVIDUAL_FAMILY_SERVICES
- - INDUSTRIAL_AUTOMATION
- - INFORMATION_SERVICES
- - INFORMATION_TECHNOLOGY_AND_SERVICES
- - INSURANCE
- - INTERNATIONAL_AFFAIRS
- - INTERNATIONAL_TRADE_AND_DEVELOPMENT
- - INVESTMENT_BANKING
- - INVESTMENT_MANAGEMENT
- - JUDICIARY
- - LAW_ENFORCEMENT
- - LAW_PRACTICE
- - LEGAL_SERVICES
- - LEGISLATIVE_OFFICE
- - LEISURE_TRAVEL_TOURISM
- - LIBRARIES
- - LOGISTICS_AND_SUPPLY_CHAIN
- - LUXURY_GOODS_JEWELRY
- - MACHINERY
- - MANAGEMENT_CONSULTING
- - MARITIME
- - MARKET_RESEARCH
- - MARKETING_AND_ADVERTISING
- - MECHANICAL_OR_INDUSTRIAL_ENGINEERING
- - MEDIA_PRODUCTION
- - MEDICAL_DEVICES
- - MEDICAL_PRACTICE
- - MENTAL_HEALTH_CARE
- - MILITARY
- - MINING_METALS
- - MOTION_PICTURES_AND_FILM
- - MUSEUMS_AND_INSTITUTIONS
- - MUSIC
- - NANOTECHNOLOGY
- - NEWSPAPERS
- - NON_PROFIT_ORGANIZATION_MANAGEMENT
- - OIL_ENERGY
- - ONLINE_MEDIA
- - OUTSOURCING_OFFSHORING
- - PACKAGE_FREIGHT_DELIVERY
- - PACKAGING_AND_CONTAINERS
- - PAPER_FOREST_PRODUCTS
- - PERFORMING_ARTS
- - PHARMACEUTICALS
- - PHILANTHROPY
- - PHOTOGRAPHY
- - PLASTICS
- - POLITICAL_ORGANIZATION
- - PRIMARY_SECONDARY_EDUCATION
- - PRINTING
- - PROFESSIONAL_TRAINING_COACHING
- - PROGRAM_DEVELOPMENT
- - PUBLIC_POLICY
- - PUBLIC_RELATIONS_AND_COMMUNICATIONS
- - PUBLIC_SAFETY
- - PUBLISHING
- - RAILROAD_MANUFACTURE
- - RANCHING
- - REAL_ESTATE
- - RECREATIONAL_FACILITIES_AND_SERVICES
- - RELIGIOUS_INSTITUTIONS
- - RENEWABLES_ENVIRONMENT
- - RESEARCH
- - RESTAURANTS
- - RETAIL
- - SECURITY_AND_INVESTIGATIONS
- - SEMICONDUCTORS
- - SHIPBUILDING
- - SPORTING_GOODS
- - SPORTS
- - STAFFING_AND_RECRUITING
- - SUPERMARKETS
- - TELECOMMUNICATIONS
- - TEXTILES
- - THINK_TANKS
- - TOBACCO
- - TRANSLATION_AND_LOCALIZATION
- - TRANSPORTATION_TRUCKING_RAILROAD
- - UTILITIES
- - VENTURE_CAPITAL_PRIVATE_EQUITY
- - VETERINARY
- - WAREHOUSING
- - WHOLESALE
- - WINE_AND_SPIRITS
- - WIRELESS
- - WRITING_AND_EDITING
description: >-
The industry of the company. Authorized values can be found in the
Industry enum.
@@ -10684,7 +10509,7 @@ components:
nullable: true
email_addresses:
description: The email addresses of the company
- example: &ref_105
+ example: &ref_101
- email_address: acme@gmail.com
email_address_type: WORK
nullable: true
@@ -10693,7 +10518,7 @@ components:
$ref: '#/components/schemas/Email'
addresses:
description: The addresses of the company
- example: &ref_106
+ example: &ref_102
- street_1: 5th Avenue
city: New York
state: NY
@@ -10705,7 +10530,7 @@ components:
$ref: '#/components/schemas/Address'
phone_numbers:
description: The phone numbers of the company
- example: &ref_107
+ example: &ref_103
- phone_number: '+33660606067'
phone_type: WORK
nullable: true
@@ -10714,7 +10539,7 @@ components:
$ref: '#/components/schemas/Phone'
field_mappings:
type: object
- example: &ref_108
+ example: &ref_104
fav_dish: broccoli
fav_color: red
description: >-
@@ -10763,7 +10588,6 @@ components:
industry:
type: string
example: ACCOUNTING
- enum: *ref_104
description: >-
The industry of the company. Authorized values can be found in the
Industry enum.
@@ -10780,28 +10604,28 @@ components:
nullable: true
email_addresses:
description: The email addresses of the company
- example: *ref_105
+ example: *ref_101
nullable: true
type: array
items:
$ref: '#/components/schemas/Email'
addresses:
description: The addresses of the company
- example: *ref_106
+ example: *ref_102
nullable: true
type: array
items:
$ref: '#/components/schemas/Address'
phone_numbers:
description: The phone numbers of the company
- example: *ref_107
+ example: *ref_103
nullable: true
type: array
items:
$ref: '#/components/schemas/Phone'
field_mappings:
type: object
- example: *ref_108
+ example: *ref_104
description: >-
The custom field mappings of the company between the remote 3rd
party & Panora
@@ -10825,7 +10649,7 @@ components:
email_addresses:
nullable: true
description: The email addresses of the contact
- example: &ref_109
+ example: &ref_105
- email: john.doe@example.com
type: WORK
type: array
@@ -10834,7 +10658,7 @@ components:
phone_numbers:
nullable: true
description: The phone numbers of the contact
- example: &ref_110
+ example: &ref_106
- phone: '1234567890'
type: WORK
type: array
@@ -10843,7 +10667,7 @@ components:
addresses:
nullable: true
description: The addresses of the contact
- example: &ref_111
+ example: &ref_107
- street: 123 Main St
city: Anytown
state: CA
@@ -10860,7 +10684,7 @@ components:
example: 801f9ede-c698-4e66-a7fc-48d19eebaa4f
field_mappings:
type: object
- example: &ref_112
+ example: &ref_108
fav_dish: broccoli
fav_color: red
nullable: true
@@ -10917,21 +10741,21 @@ components:
email_addresses:
nullable: true
description: The email addresses of the contact
- example: *ref_109
+ example: *ref_105
type: array
items:
$ref: '#/components/schemas/Email'
phone_numbers:
nullable: true
description: The phone numbers of the contact
- example: *ref_110
+ example: *ref_106
type: array
items:
$ref: '#/components/schemas/Phone'
addresses:
nullable: true
description: The addresses of the contact
- example: *ref_111
+ example: *ref_107
type: array
items:
$ref: '#/components/schemas/Address'
@@ -10942,7 +10766,7 @@ components:
example: 801f9ede-c698-4e66-a7fc-48d19eebaa4f
field_mappings:
type: object
- example: *ref_112
+ example: *ref_108
nullable: true
description: >-
The custom field mappings of the contact between the remote 3rd
@@ -10987,7 +10811,7 @@ components:
field_mappings:
type: object
nullable: true
- example: &ref_113
+ example: &ref_109
fav_dish: broccoli
fav_color: red
description: >-
@@ -11064,7 +10888,7 @@ components:
field_mappings:
type: object
nullable: true
- example: *ref_113
+ example: *ref_109
description: >-
The custom field mappings of the company between the remote 3rd
party & Panora
@@ -11085,9 +10909,6 @@ components:
type: string
nullable: true
example: INBOUND
- enum: &ref_114
- - INBOUND
- - OUTBOUND
description: >-
The direction of the engagement. Authorized values are INBOUND or
OUTBOUND
@@ -11112,10 +10933,6 @@ components:
type: string
nullable: true
example: MEETING
- enum: &ref_115
- - EMAIL
- - CALL
- - MEETING
description: >-
The type of the engagement. Authorized values are EMAIL, CALL or
MEETING
@@ -11131,7 +10948,7 @@ components:
description: The UUID of the company tied to the engagement
contacts:
nullable: true
- example: &ref_116
+ example: &ref_110
- 801f9ede-c698-4e66-a7fc-48d19eebaa4f
description: The UUIDs of contacts tied to the engagement object
type: array
@@ -11140,7 +10957,7 @@ components:
field_mappings:
type: object
nullable: true
- example: &ref_117
+ example: &ref_111
fav_dish: broccoli
fav_color: red
description: >-
@@ -11193,7 +11010,6 @@ components:
type: string
nullable: true
example: INBOUND
- enum: *ref_114
description: >-
The direction of the engagement. Authorized values are INBOUND or
OUTBOUND
@@ -11218,7 +11034,6 @@ components:
type: string
nullable: true
example: MEETING
- enum: *ref_115
description: >-
The type of the engagement. Authorized values are EMAIL, CALL or
MEETING
@@ -11234,7 +11049,7 @@ components:
description: The UUID of the company tied to the engagement
contacts:
nullable: true
- example: *ref_116
+ example: *ref_110
description: The UUIDs of contacts tied to the engagement object
type: array
items:
@@ -11242,7 +11057,7 @@ components:
field_mappings:
type: object
nullable: true
- example: *ref_117
+ example: *ref_111
description: >-
The custom field mappings of the engagement between the remote 3rd
party & Panora
@@ -11279,7 +11094,7 @@ components:
description: The UUID of the deal tied to the note
field_mappings:
type: object
- example: &ref_118
+ example: &ref_112
fav_dish: broccoli
fav_color: red
nullable: true
@@ -11349,7 +11164,7 @@ components:
description: The UUID of the deal tied to the note
field_mappings:
type: object
- example: *ref_118
+ example: *ref_112
nullable: true
description: >-
The custom field mappings of the note between the remote 3rd party &
@@ -11421,9 +11236,6 @@ components:
status:
type: string
example: PENDING
- enum: &ref_119
- - PENDING
- - COMPLETED
description: The status of the task. Authorized values are PENDING, COMPLETED.
nullable: true
due_date:
@@ -11453,7 +11265,7 @@ components:
nullable: true
field_mappings:
type: object
- example: &ref_120
+ example: &ref_113
fav_dish: broccoli
fav_color: red
description: >-
@@ -11512,7 +11324,6 @@ components:
status:
type: string
example: PENDING
- enum: *ref_119
description: The status of the task. Authorized values are PENDING, COMPLETED.
nullable: true
due_date:
@@ -11542,7 +11353,7 @@ components:
nullable: true
field_mappings:
type: object
- example: *ref_120
+ example: *ref_113
description: >-
The custom field mappings of the task between the remote 3rd party &
Panora
@@ -11624,9 +11435,6 @@ components:
collection_type:
type: string
example: PROJECT
- enum:
- - PROJECT
- - LIST
nullable: true
description: >-
The type of the collection. Authorized values are either PROJECT or
@@ -11685,7 +11493,6 @@ components:
type: string
nullable: true
example: USER
- enum: *ref_121
description: >-
The creator type of the comment. Authorized values are either USER
or CONTACT
@@ -11710,9 +11517,9 @@ components:
specified)
attachments:
type: array
- items: *ref_122
+ items: *ref_114
nullable: true
- example: *ref_123
+ example: *ref_115
description: The attachements UUIDs tied to the comment
id:
type: string
@@ -12345,9 +12152,6 @@ components:
account_type:
type: string
example: CHECKING
- enum:
- - SAVINGS
- - CHECKING
nullable: true
description: The type of the bank account
bank_name:
@@ -12613,10 +12417,6 @@ components:
relationship:
type: string
example: CHILD
- enum:
- - CHILD
- - SPOUSE
- - DOMESTIC_PARTNER
nullable: true
description: The relationship of the dependent to the employee
date_of_birth:
@@ -12628,12 +12428,6 @@ components:
gender:
type: string
example: MALE
- enum:
- - MALE
- - FEMALE
- - NON-BINARY
- - OTHER
- - PREFER_NOT_TO_DISCLOSE
nullable: true
description: The gender of the dependent
phone_number:
@@ -12879,7 +12673,7 @@ components:
type: object
properties:
groups:
- example: &ref_124
+ example: &ref_116
- Group1
- Group2
nullable: true
@@ -12888,7 +12682,7 @@ components:
items:
type: string
locations:
- example: &ref_125
+ example: &ref_117
- 801f9ede-c698-4e66-a7fc-48d19eebaa4f
nullable: true
description: UUIDs of the of the Location associated with the company
@@ -12946,7 +12740,7 @@ components:
nullable: true
description: The mobile phone number of the employee
employments:
- example: &ref_126
+ example: &ref_118
- 801f9ede-c698-4e66-a7fc-48d19eebaa4f
- 801f9ede-c698-4e66-a7fc-48d19eebaa4f
nullable: true
@@ -12962,37 +12756,16 @@ components:
gender:
type: string
example: MALE
- enum: &ref_127
- - MALE
- - FEMALE
- - NON-BINARY
- - OTHER
- - PREFER_NOT_TO_DISCLOSE
nullable: true
description: The gender of the employee
ethnicity:
type: string
example: AMERICAN_INDIAN_OR_ALASKA_NATIVE
- enum: &ref_128
- - AMERICAN_INDIAN_OR_ALASKA_NATIVE
- - ASIAN_OR_INDIAN_SUBCONTINENT
- - BLACK_OR_AFRICAN_AMERICAN
- - HISPANIC_OR_LATINO
- - NATIVE_HAWAIIAN_OR_OTHER_PACIFIC_ISLANDER
- - TWO_OR_MORE_RACES
- - WHITE
- - PREFER_NOT_TO_DISCLOSE
nullable: true
description: The ethnicity of the employee
marital_status:
type: string
example: Married
- enum: &ref_129
- - SINGLE
- - MARRIED_FILING_JOINTLY
- - MARRIED_FILING_SEPARATELY
- - HEAD_OF_HOUSEHOLD
- - QUALIFYING_WIDOW_OR_WIDOWER_WITH_DEPENDENT_CHILD
nullable: true
description: The marital status of the employee
date_of_birth:
@@ -13010,10 +12783,6 @@ components:
employment_status:
type: string
example: ACTIVE
- enum: &ref_130
- - ACTIVE
- - PENDING
- - INACTIVE
nullable: true
description: The employment status of the employee
termination_date:
@@ -13034,7 +12803,7 @@ components:
description: UUID of the manager (employee) of the employee
field_mappings:
type: object
- example: &ref_131
+ example: &ref_119
custom_field_1: value1
custom_field_2: value2
nullable: true
@@ -13085,14 +12854,14 @@ components:
type: object
properties:
groups:
- example: *ref_124
+ example: *ref_116
nullable: true
description: The groups the employee belongs to
type: array
items:
type: string
locations:
- example: *ref_125
+ example: *ref_117
nullable: true
description: UUIDs of the of the Location associated with the company
type: array
@@ -13149,7 +12918,7 @@ components:
nullable: true
description: The mobile phone number of the employee
employments:
- example: *ref_126
+ example: *ref_118
nullable: true
description: The employments of the employee
type: array
@@ -13163,19 +12932,16 @@ components:
gender:
type: string
example: MALE
- enum: *ref_127
nullable: true
description: The gender of the employee
ethnicity:
type: string
example: AMERICAN_INDIAN_OR_ALASKA_NATIVE
- enum: *ref_128
nullable: true
description: The ethnicity of the employee
marital_status:
type: string
example: Married
- enum: *ref_129
nullable: true
description: The marital status of the employee
date_of_birth:
@@ -13193,7 +12959,6 @@ components:
employment_status:
type: string
example: ACTIVE
- enum: *ref_130
nullable: true
description: The employment status of the employee
termination_date:
@@ -13214,7 +12979,7 @@ components:
description: UUID of the manager (employee) of the employee
field_mappings:
type: object
- example: *ref_131
+ example: *ref_119
nullable: true
description: >-
The custom field mappings of the object between the remote 3rd party
@@ -13225,12 +12990,6 @@ components:
benefit_plan_type:
type: string
example: Health Insurance
- enum:
- - MEDICAL
- - HEALTH_SAVINGS
- - INSURANCE
- - RETIREMENT
- - OTHER
nullable: true
description: The type of the benefit plan
name:
@@ -13319,209 +13078,21 @@ components:
pay_period:
type: string
example: MONTHLY
- enum:
- - HOUR
- - DAY
- - WEEK
- - EVERY_TWO_WEEKS
- - SEMIMONTHLY
- - MONTH
- - QUARTER
- - EVERY_SIX_MONTHS
- - YEAR
nullable: true
description: The pay period of the employment
pay_frequency:
type: string
example: WEEKLY
- enum:
- - WEEKLY
- - BIWEEKLY
- - MONTHLY
- - QUARTERLY
- - SEMIANNUALLY
- - ANNUALLY
- - THIRTEEN-MONTHLY
- - PRO_RATA
- - SEMIMONTHLY
nullable: true
description: The pay frequency of the employment
pay_currency:
type: string
example: USD
- enum:
- - AED
- - AFN
- - ALL
- - AMD
- - ANG
- - AOA
- - ARS
- - AUD
- - AWG
- - AZN
- - BAM
- - BBD
- - BDT
- - BGN
- - BHD
- - BIF
- - BMD
- - BND
- - BOB
- - BRL
- - BSD
- - BTN
- - BWP
- - BYN
- - BZD
- - CAD
- - CDF
- - CHF
- - CLP
- - CNY
- - COP
- - CRC
- - CUP
- - CVE
- - CZK
- - DJF
- - DKK
- - DOP
- - DZD
- - EGP
- - ERN
- - ETB
- - EUR
- - FJD
- - FKP
- - FOK
- - GBP
- - GEL
- - GGP
- - GHS
- - GIP
- - GMD
- - GNF
- - GTQ
- - GYD
- - HKD
- - HNL
- - HRK
- - HTG
- - HUF
- - IDR
- - ILS
- - IMP
- - INR
- - IQD
- - IRR
- - ISK
- - JEP
- - JMD
- - JOD
- - JPY
- - KES
- - KGS
- - KHR
- - KID
- - KMF
- - KRW
- - KWD
- - KYD
- - KZT
- - LAK
- - LBP
- - LKR
- - LRD
- - LSL
- - LYD
- - MAD
- - MDL
- - MGA
- - MKD
- - MMK
- - MNT
- - MOP
- - MRU
- - MUR
- - MVR
- - MWK
- - MXN
- - MYR
- - MZN
- - NAD
- - NGN
- - NIO
- - NOK
- - NPR
- - NZD
- - OMR
- - PAB
- - PEN
- - PGK
- - PHP
- - PKR
- - PLN
- - PYG
- - QAR
- - RON
- - RSD
- - RUB
- - RWF
- - SAR
- - SBD
- - SCR
- - SDG
- - SEK
- - SGD
- - SHP
- - SLE
- - SLL
- - SOS
- - SRD
- - SSP
- - STN
- - SYP
- - SZL
- - THB
- - TJS
- - TMT
- - TND
- - TOP
- - TRY
- - TTD
- - TVD
- - TWD
- - TZS
- - UAH
- - UGX
- - USD
- - UYU
- - UZS
- - VES
- - VND
- - VUV
- - WST
- - XAF
- - XCD
- - XDR
- - XOF
- - XPF
- - YER
- - ZAR
- - ZMW
- - ZWL
nullable: true
description: The currency of the pay
flsa_status:
type: string
example: EXEMPT
- enum:
- - EXEMPT
- - SALARIED_NONEXEMPT
- - NONEXEMPT
- - OWNER
nullable: true
description: The FLSA status of the employment
effective_date:
@@ -13533,12 +13104,6 @@ components:
employment_type:
type: string
example: FULL_TIME
- enum:
- - FULL_TIME
- - PART_TIME
- - INTERN
- - CONTRACTOR
- - FREELANCE
nullable: true
description: The type of employment
pay_group_id:
@@ -13616,12 +13181,6 @@ components:
type:
type: string
example: DEPARTMENT
- enum:
- - TEAM
- - DEPARTMENT
- - COST_CENTER
- - BUSINESS_UNIT
- - GROUP
nullable: true
description: The type of the group
field_mappings:
@@ -13719,9 +13278,6 @@ components:
location_type:
type: string
example: WORK
- enum:
- - WORK
- - HOME
nullable: true
description: The type of the location
company_id:
@@ -13846,23 +13402,11 @@ components:
run_state:
type: string
example: PAID
- enum:
- - PAID
- - DRAFT
- - APPROVED
- - FAILED
- - CLOSE
nullable: true
description: The state of the payroll run
run_type:
type: string
example: REGULAR
- enum:
- - REGULAR
- - OFF_CYCLE
- - CORRECTION
- - TERMINATION
- - SIGN_ON_BONUS
nullable: true
description: The type of the payroll run
start_date:
@@ -13958,12 +13502,6 @@ components:
status:
type: string
example: REQUESTED
- enum: &ref_132
- - REQUESTED
- - APPROVED
- - DECLINED
- - CANCELLED
- - DELETED
nullable: true
description: The status of the time off request
employee_note:
@@ -13974,9 +13512,6 @@ components:
units:
type: string
example: DAYS
- enum: &ref_133
- - HOURS
- - DAYS
nullable: true
description: The units used for the time off (e.g., Days, Hours)
amount:
@@ -13987,13 +13522,6 @@ components:
request_type:
type: string
example: VACATION
- enum: &ref_134
- - VACATION
- - SICK
- - PERSONAL
- - JURY_DUTY
- - VOLUNTEER
- - BEREAVEMENT
nullable: true
description: The type of time off request
start_time:
@@ -14010,7 +13538,7 @@ components:
description: The end time of the time off
field_mappings:
type: object
- example: &ref_135
+ example: &ref_120
custom_field_1: value1
custom_field_2: value2
nullable: true
@@ -14073,7 +13601,6 @@ components:
status:
type: string
example: REQUESTED
- enum: *ref_132
nullable: true
description: The status of the time off request
employee_note:
@@ -14084,7 +13611,6 @@ components:
units:
type: string
example: DAYS
- enum: *ref_133
nullable: true
description: The units used for the time off (e.g., Days, Hours)
amount:
@@ -14095,7 +13621,6 @@ components:
request_type:
type: string
example: VACATION
- enum: *ref_134
nullable: true
description: The type of time off request
start_time:
@@ -14112,7 +13637,7 @@ components:
description: The end time of the time off
field_mappings:
type: object
- example: *ref_135
+ example: *ref_120
nullable: true
description: >-
The custom field mappings of the object between the remote 3rd party
@@ -14138,13 +13663,6 @@ components:
policy_type:
type: string
example: VACATION
- enum:
- - VACATION
- - SICK
- - PERSONAL
- - JURY_DUTY
- - VOLUNTEER
- - BEREAVEMENT
nullable: true
description: The type of time off policy
field_mappings:
@@ -14230,7 +13748,7 @@ components:
description: Indicates if the timesheet entry was deleted in the remote system
field_mappings:
type: object
- example: &ref_136
+ example: &ref_121
custom_field_1: value1
custom_field_2: value2
nullable: true
@@ -14303,7 +13821,7 @@ components:
description: Indicates if the timesheet entry was deleted in the remote system
field_mappings:
type: object
- example: *ref_136
+ example: *ref_121
nullable: true
description: >-
The custom field mappings of the object between the remote 3rd party
@@ -14361,13 +13879,9 @@ components:
properties:
activity_type:
type: string
- enum: &ref_137
- - NOTE
- - EMAIL
- - OTHER
example: NOTE
nullable: true
- description: The type of activity
+ description: The type of activity. NOTE, EMAIL or OTHER
subject:
type: string
example: Email subject
@@ -14380,13 +13894,9 @@ components:
description: The body of the activity
visibility:
type: string
- enum: &ref_138
- - ADMIN_ONLY
- - PUBLIC
- - PRIVATE
example: PUBLIC
nullable: true
- description: The visibility of the activity
+ description: The visibility of the activity. ADMIN_ONLY, PUBLIC or PRIVATE
candidate_id:
type: string
example: 801f9ede-c698-4e66-a7fc-48d19eebaa4f
@@ -14400,7 +13910,7 @@ components:
description: The remote creation date of the activity
field_mappings:
type: object
- example: &ref_139
+ example: &ref_122
fav_dish: broccoli
fav_color: red
additionalProperties: true
@@ -14443,10 +13953,9 @@ components:
properties:
activity_type:
type: string
- enum: *ref_137
example: NOTE
nullable: true
- description: The type of activity
+ description: The type of activity. NOTE, EMAIL or OTHER
subject:
type: string
example: Email subject
@@ -14459,10 +13968,9 @@ components:
description: The body of the activity
visibility:
type: string
- enum: *ref_138
example: PUBLIC
nullable: true
- description: The visibility of the activity
+ description: The visibility of the activity. ADMIN_ONLY, PUBLIC or PRIVATE
candidate_id:
type: string
example: 801f9ede-c698-4e66-a7fc-48d19eebaa4f
@@ -14476,7 +13984,7 @@ components:
description: The remote creation date of the activity
field_mappings:
type: object
- example: *ref_139
+ example: *ref_122
additionalProperties: true
nullable: true
description: >-
@@ -14500,7 +14008,7 @@ components:
offers:
nullable: true
description: The offers UUIDs for the application
- example: &ref_140
+ example: &ref_123
- 801f9ede-c698-4e66-a7fc-48d19eebaa4f
- 12345678-1234-1234-1234-123456789012
type: array
@@ -14537,7 +14045,7 @@ components:
example: 801f9ede-c698-4e66-a7fc-48d19eebaa4f
field_mappings:
type: object
- example: &ref_141
+ example: &ref_124
fav_dish: broccoli
fav_color: red
additionalProperties: true
@@ -14603,7 +14111,7 @@ components:
offers:
nullable: true
description: The offers UUIDs for the application
- example: *ref_140
+ example: *ref_123
type: array
items:
type: string
@@ -14638,7 +14146,7 @@ components:
example: 801f9ede-c698-4e66-a7fc-48d19eebaa4f
field_mappings:
type: object
- example: *ref_141
+ example: *ref_124
additionalProperties: true
nullable: true
description: >-
@@ -14660,11 +14168,6 @@ components:
attachment_type:
type: string
example: RESUME
- enum: &ref_142
- - RESUME
- - COVER_LETTER
- - OFFER_LETTER
- - OTHER
nullable: true
description: The type of the file
remote_created_at:
@@ -14686,7 +14189,7 @@ components:
description: The UUID of the candidate
field_mappings:
type: object
- example: &ref_143
+ example: &ref_125
fav_dish: broccoli
fav_color: red
additionalProperties: true
@@ -14740,7 +14243,6 @@ components:
attachment_type:
type: string
example: RESUME
- enum: *ref_142
nullable: true
description: The type of the file
remote_created_at:
@@ -14762,7 +14264,7 @@ components:
description: The UUID of the candidate
field_mappings:
type: object
- example: *ref_143
+ example: *ref_125
additionalProperties: true
nullable: true
description: >-
@@ -14840,37 +14342,37 @@ components:
description: The last interaction date with the candidate
attachments:
type: array
- items: &ref_144
+ items: &ref_126
oneOf:
- type: string
- $ref: '#/components/schemas/UnifiedAtsAttachmentOutput'
- example: &ref_145
+ example: &ref_127
- 801f9ede-c698-4e66-a7fc-48d19eebaa4f
nullable: true
description: The attachments UUIDs of the candidate
applications:
type: array
- items: &ref_146
+ items: &ref_128
oneOf:
- type: string
- $ref: '#/components/schemas/UnifiedAtsApplicationOutput'
- example: &ref_147
+ example: &ref_129
- 801f9ede-c698-4e66-a7fc-48d19eebaa4f
nullable: true
description: The applications UUIDs of the candidate
tags:
type: array
- items: &ref_148
+ items: &ref_130
oneOf:
- type: string
- $ref: '#/components/schemas/UnifiedAtsTagOutput'
- example: &ref_149
+ example: &ref_131
- tag_1
- tag_2
nullable: true
description: The tags of the candidate
urls:
- example: &ref_150
+ example: &ref_132
- url: mywebsite.com
url_type: WEBSITE
nullable: true
@@ -14881,7 +14383,7 @@ components:
items:
$ref: '#/components/schemas/Url'
phone_numbers:
- example: &ref_151
+ example: &ref_133
- phone_number: '+33660688899'
phone_type: WORK
nullable: true
@@ -14890,7 +14392,7 @@ components:
items:
$ref: '#/components/schemas/Phone'
email_addresses:
- example: &ref_152
+ example: &ref_134
- email_address: joedoe@gmail.com
email_address_type: WORK
nullable: true
@@ -14900,7 +14402,7 @@ components:
$ref: '#/components/schemas/Email'
field_mappings:
type: object
- example: &ref_153
+ example: &ref_135
fav_dish: broccoli
fav_color: red
additionalProperties: true
@@ -14996,24 +14498,24 @@ components:
description: The last interaction date with the candidate
attachments:
type: array
- items: *ref_144
- example: *ref_145
+ items: *ref_126
+ example: *ref_127
nullable: true
description: The attachments UUIDs of the candidate
applications:
type: array
- items: *ref_146
- example: *ref_147
+ items: *ref_128
+ example: *ref_129
nullable: true
description: The applications UUIDs of the candidate
tags:
type: array
- items: *ref_148
- example: *ref_149
+ items: *ref_130
+ example: *ref_131
nullable: true
description: The tags of the candidate
urls:
- example: *ref_150
+ example: *ref_132
nullable: true
description: >-
The urls of the candidate, possible values for Url type are WEBSITE,
@@ -15022,14 +14524,14 @@ components:
items:
$ref: '#/components/schemas/Url'
phone_numbers:
- example: *ref_151
+ example: *ref_133
nullable: true
description: The phone numbers of the candidate
type: array
items:
$ref: '#/components/schemas/Phone'
email_addresses:
- example: *ref_152
+ example: *ref_134
nullable: true
description: The email addresses of the candidate
type: array
@@ -15037,7 +14539,7 @@ components:
$ref: '#/components/schemas/Email'
field_mappings:
type: object
- example: *ref_153
+ example: *ref_135
additionalProperties: true
nullable: true
description: >-
@@ -15097,10 +14599,6 @@ components:
properties:
status:
type: string
- enum: &ref_154
- - SCHEDULED
- - AWAITING_FEEDBACK
- - COMPLETED
example: SCHEDULED
nullable: true
description: The status of the interview
@@ -15120,7 +14618,7 @@ components:
nullable: true
description: The UUID of the organizer
interviewers:
- example: &ref_155
+ example: &ref_136
- 801f9ede-c698-4e66-a7fc-48d19eebaa4f
nullable: true
description: The UUIDs of the interviewers
@@ -15158,7 +14656,7 @@ components:
description: The remote modification date of the interview
field_mappings:
type: object
- example: &ref_156
+ example: &ref_137
fav_dish: broccoli
fav_color: red
additionalProperties: true
@@ -15201,7 +14699,6 @@ components:
properties:
status:
type: string
- enum: *ref_154
example: SCHEDULED
nullable: true
description: The status of the interview
@@ -15221,7 +14718,7 @@ components:
nullable: true
description: The UUID of the organizer
interviewers:
- example: *ref_155
+ example: *ref_136
nullable: true
description: The UUIDs of the interviewers
type: array
@@ -15258,7 +14755,7 @@ components:
description: The remote modification date of the interview
field_mappings:
type: object
- example: *ref_156
+ example: *ref_137
additionalProperties: true
nullable: true
description: >-
@@ -15346,22 +14843,12 @@ components:
description: The code of the job
status:
type: string
- enum:
- - OPEN
- - CLOSED
- - DRAFT
- - ARCHIVED
- - PENDING
example: OPEN
nullable: true
description: The status of the job
type:
type: string
example: POSTING
- enum:
- - POSTING
- - REQUISITION
- - PROFILE
nullable: true
description: The type of the job
confidential:
@@ -15489,16 +14976,6 @@ components:
status:
type: string
example: DRAFT
- enum:
- - DRAFT
- - APPROVAL_SENT
- - APPROVED
- - SENT
- - SENT_MANUALLY
- - OPENED
- - DENIED
- - SIGNED
- - DEPRECATED
description: The status of the offer
nullable: true
application_id:
@@ -15649,12 +15126,6 @@ components:
properties:
overall_recommendation:
type: string
- enum:
- - DEFINITELY_NO
- - 'NO'
- - 'YES'
- - STRONG_YES
- - NO_DECISION
example: 'YES'
nullable: true
description: The overall recommendation
@@ -15798,12 +15269,6 @@ components:
access_role:
type: string
example: ADMIN
- enum:
- - SUPER_ADMIN
- - ADMIN
- - TEAM_MEMBER
- - LIMITED_TEAM_MEMBER
- - INTERVIEWER
description: The access role of the user
nullable: true
remote_created_at:
@@ -15874,45 +15339,21 @@ components:
description: The submission date of the EEOC
race:
type: string
- enum:
- - 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
example: AMERICAN_INDIAN_OR_ALASKAN_NATIVE
nullable: true
description: The race of the candidate
gender:
type: string
example: MALE
- enum:
- - MALE
- - FEMALE
- - NON_BINARY
- - OTHER
- - DECLINE_TO_SELF_IDENTIFY
nullable: true
description: The gender of the candidate
veteran_status:
type: string
example: I_AM_NOT_A_PROTECTED_VETERAN
- enum:
- - I_AM_NOT_A_PROTECTED_VETERAN
- - >-
- I_IDENTIFY_AS_ONE_OR_MORE_OF_THE_CLASSIFICATIONS_OF_A_PROTECTED_VETERAN
- - I_DONT_WISH_TO_ANSWER
nullable: true
description: The veteran status of the candidate
disability_status:
type: string
- enum:
- - YES_I_HAVE_A_DISABILITY_OR_PREVIOUSLY_HAD_A_DISABILITY
- - NO_I_DONT_HAVE_A_DISABILITY
- - I_DONT_WISH_TO_ANSWER
example: YES_I_HAVE_A_DISABILITY_OR_PREVIOUSLY_HAD_A_DISABILITY
nullable: true
description: The disability status of the candidate
@@ -15992,169 +15433,6 @@ components:
currency:
type: string
example: USD
- enum: &ref_157
- - AED
- - AFN
- - ALL
- - AMD
- - ANG
- - AOA
- - ARS
- - AUD
- - AWG
- - AZN
- - BAM
- - BBD
- - BDT
- - BGN
- - BHD
- - BIF
- - BMD
- - BND
- - BOB
- - BRL
- - BSD
- - BTN
- - BWP
- - BYN
- - BZD
- - CAD
- - CDF
- - CHF
- - CLP
- - CNY
- - COP
- - CRC
- - CUP
- - CVE
- - CZK
- - DJF
- - DKK
- - DOP
- - DZD
- - EGP
- - ERN
- - ETB
- - EUR
- - FJD
- - FKP
- - FOK
- - GBP
- - GEL
- - GGP
- - GHS
- - GIP
- - GMD
- - GNF
- - GTQ
- - GYD
- - HKD
- - HNL
- - HRK
- - HTG
- - HUF
- - IDR
- - ILS
- - IMP
- - INR
- - IQD
- - IRR
- - ISK
- - JEP
- - JMD
- - JOD
- - JPY
- - KES
- - KGS
- - KHR
- - KID
- - KMF
- - KRW
- - KWD
- - KYD
- - KZT
- - LAK
- - LBP
- - LKR
- - LRD
- - LSL
- - LYD
- - MAD
- - MDL
- - MGA
- - MKD
- - MMK
- - MNT
- - MOP
- - MRU
- - MUR
- - MVR
- - MWK
- - MXN
- - MYR
- - MZN
- - NAD
- - NGN
- - NIO
- - NOK
- - NPR
- - NZD
- - OMR
- - PAB
- - PEN
- - PGK
- - PHP
- - PKR
- - PLN
- - PYG
- - QAR
- - RON
- - RSD
- - RUB
- - RWF
- - SAR
- - SBD
- - SCR
- - SDG
- - SEK
- - SGD
- - SHP
- - SLE
- - SLL
- - SOS
- - SRD
- - SSP
- - STN
- - SYP
- - SZL
- - THB
- - TJS
- - TMT
- - TND
- - TOP
- - TRY
- - TTD
- - TVD
- - TWD
- - TZS
- - UAH
- - UGX
- - USD
- - UYU
- - UZS
- - VES
- - VND
- - VUV
- - WST
- - XAF
- - XCD
- - XDR
- - XOF
- - XPF
- - YER
- - ZAR
- - ZMW
- - ZWL
nullable: true
description: The currency of the account
account_number:
@@ -16174,7 +15452,7 @@ components:
description: The UUID of the associated company info
field_mappings:
type: object
- example: &ref_158
+ example: &ref_138
custom_field_1: value1
custom_field_2: value2
nullable: true
@@ -16246,7 +15524,6 @@ components:
currency:
type: string
example: USD
- enum: *ref_157
nullable: true
description: The currency of the account
account_number:
@@ -16266,7 +15543,7 @@ components:
description: The UUID of the associated company info
field_mappings:
type: object
- example: *ref_158
+ example: *ref_138
nullable: true
description: >-
The custom field mappings of the object between the remote 3rd party
@@ -16382,7 +15659,7 @@ components:
description: The UUID of the associated account
field_mappings:
type: object
- example: &ref_159
+ example: &ref_139
custom_field_1: value1
custom_field_2: value2
nullable: true
@@ -16438,7 +15715,7 @@ components:
description: The UUID of the associated account
field_mappings:
type: object
- example: *ref_159
+ example: *ref_139
nullable: true
description: >-
The custom field mappings of the object between the remote 3rd party
@@ -16503,169 +15780,6 @@ components:
currency:
type: string
example: USD
- enum:
- - AED
- - AFN
- - ALL
- - AMD
- - ANG
- - AOA
- - ARS
- - AUD
- - AWG
- - AZN
- - BAM
- - BBD
- - BDT
- - BGN
- - BHD
- - BIF
- - BMD
- - BND
- - BOB
- - BRL
- - BSD
- - BTN
- - BWP
- - BYN
- - BZD
- - CAD
- - CDF
- - CHF
- - CLP
- - CNY
- - COP
- - CRC
- - CUP
- - CVE
- - CZK
- - DJF
- - DKK
- - DOP
- - DZD
- - EGP
- - ERN
- - ETB
- - EUR
- - FJD
- - FKP
- - FOK
- - GBP
- - GEL
- - GGP
- - GHS
- - GIP
- - GMD
- - GNF
- - GTQ
- - GYD
- - HKD
- - HNL
- - HRK
- - HTG
- - HUF
- - IDR
- - ILS
- - IMP
- - INR
- - IQD
- - IRR
- - ISK
- - JEP
- - JMD
- - JOD
- - JPY
- - KES
- - KGS
- - KHR
- - KID
- - KMF
- - KRW
- - KWD
- - KYD
- - KZT
- - LAK
- - LBP
- - LKR
- - LRD
- - LSL
- - LYD
- - MAD
- - MDL
- - MGA
- - MKD
- - MMK
- - MNT
- - MOP
- - MRU
- - MUR
- - MVR
- - MWK
- - MXN
- - MYR
- - MZN
- - NAD
- - NGN
- - NIO
- - NOK
- - NPR
- - NZD
- - OMR
- - PAB
- - PEN
- - PGK
- - PHP
- - PKR
- - PLN
- - PYG
- - QAR
- - RON
- - RSD
- - RUB
- - RWF
- - SAR
- - SBD
- - SCR
- - SDG
- - SEK
- - SGD
- - SHP
- - SLE
- - SLL
- - SOS
- - SRD
- - SSP
- - STN
- - SYP
- - SZL
- - THB
- - TJS
- - TMT
- - TND
- - TOP
- - TRY
- - TTD
- - TVD
- - TWD
- - TZS
- - UAH
- - UGX
- - USD
- - UYU
- - UZS
- - VES
- - VND
- - VUV
- - WST
- - XAF
- - XCD
- - XDR
- - XOF
- - XPF
- - YER
- - ZAR
- - ZMW
- - ZWL
nullable: true
description: The currency used in the balance sheet
company_info_id:
@@ -16772,169 +15886,6 @@ components:
currency:
type: string
example: USD
- enum:
- - AED
- - AFN
- - ALL
- - AMD
- - ANG
- - AOA
- - ARS
- - AUD
- - AWG
- - AZN
- - BAM
- - BBD
- - BDT
- - BGN
- - BHD
- - BIF
- - BMD
- - BND
- - BOB
- - BRL
- - BSD
- - BTN
- - BWP
- - BYN
- - BZD
- - CAD
- - CDF
- - CHF
- - CLP
- - CNY
- - COP
- - CRC
- - CUP
- - CVE
- - CZK
- - DJF
- - DKK
- - DOP
- - DZD
- - EGP
- - ERN
- - ETB
- - EUR
- - FJD
- - FKP
- - FOK
- - GBP
- - GEL
- - GGP
- - GHS
- - GIP
- - GMD
- - GNF
- - GTQ
- - GYD
- - HKD
- - HNL
- - HRK
- - HTG
- - HUF
- - IDR
- - ILS
- - IMP
- - INR
- - IQD
- - IRR
- - ISK
- - JEP
- - JMD
- - JOD
- - JPY
- - KES
- - KGS
- - KHR
- - KID
- - KMF
- - KRW
- - KWD
- - KYD
- - KZT
- - LAK
- - LBP
- - LKR
- - LRD
- - LSL
- - LYD
- - MAD
- - MDL
- - MGA
- - MKD
- - MMK
- - MNT
- - MOP
- - MRU
- - MUR
- - MVR
- - MWK
- - MXN
- - MYR
- - MZN
- - NAD
- - NGN
- - NIO
- - NOK
- - NPR
- - NZD
- - OMR
- - PAB
- - PEN
- - PGK
- - PHP
- - PKR
- - PLN
- - PYG
- - QAR
- - RON
- - RSD
- - RUB
- - RWF
- - SAR
- - SBD
- - SCR
- - SDG
- - SEK
- - SGD
- - SHP
- - SLE
- - SLL
- - SOS
- - SRD
- - SSP
- - STN
- - SYP
- - SZL
- - THB
- - TJS
- - TMT
- - TND
- - TOP
- - TRY
- - TTD
- - TVD
- - TWD
- - TZS
- - UAH
- - UGX
- - USD
- - UYU
- - UZS
- - VES
- - VND
- - VUV
- - WST
- - XAF
- - XCD
- - XDR
- - XOF
- - XPF
- - YER
- - ZAR
- - ZMW
- - ZWL
nullable: true
description: The currency used in the cash flow statement
company_id:
@@ -17050,169 +16001,6 @@ components:
currency:
type: string
example: USD
- enum:
- - AED
- - AFN
- - ALL
- - AMD
- - ANG
- - AOA
- - ARS
- - AUD
- - AWG
- - AZN
- - BAM
- - BBD
- - BDT
- - BGN
- - BHD
- - BIF
- - BMD
- - BND
- - BOB
- - BRL
- - BSD
- - BTN
- - BWP
- - BYN
- - BZD
- - CAD
- - CDF
- - CHF
- - CLP
- - CNY
- - COP
- - CRC
- - CUP
- - CVE
- - CZK
- - DJF
- - DKK
- - DOP
- - DZD
- - EGP
- - ERN
- - ETB
- - EUR
- - FJD
- - FKP
- - FOK
- - GBP
- - GEL
- - GGP
- - GHS
- - GIP
- - GMD
- - GNF
- - GTQ
- - GYD
- - HKD
- - HNL
- - HRK
- - HTG
- - HUF
- - IDR
- - ILS
- - IMP
- - INR
- - IQD
- - IRR
- - ISK
- - JEP
- - JMD
- - JOD
- - JPY
- - KES
- - KGS
- - KHR
- - KID
- - KMF
- - KRW
- - KWD
- - KYD
- - KZT
- - LAK
- - LBP
- - LKR
- - LRD
- - LSL
- - LYD
- - MAD
- - MDL
- - MGA
- - MKD
- - MMK
- - MNT
- - MOP
- - MRU
- - MUR
- - MVR
- - MWK
- - MXN
- - MYR
- - MZN
- - NAD
- - NGN
- - NIO
- - NOK
- - NPR
- - NZD
- - OMR
- - PAB
- - PEN
- - PGK
- - PHP
- - PKR
- - PLN
- - PYG
- - QAR
- - RON
- - RSD
- - RUB
- - RWF
- - SAR
- - SBD
- - SCR
- - SDG
- - SEK
- - SGD
- - SHP
- - SLE
- - SLL
- - SOS
- - SRD
- - SSP
- - STN
- - SYP
- - SZL
- - THB
- - TJS
- - TMT
- - TND
- - TOP
- - TRY
- - TTD
- - TVD
- - TWD
- - TZS
- - UAH
- - UGX
- - USD
- - UYU
- - UZS
- - VES
- - VND
- - VUV
- - WST
- - XAF
- - XCD
- - XDR
- - XOF
- - XPF
- - YER
- - ZAR
- - ZMW
- - ZWL
nullable: true
description: The currency used by the company
urls:
@@ -17314,169 +16102,6 @@ components:
type: string
example: USD
nullable: true
- enum: &ref_160
- - AED
- - AFN
- - ALL
- - AMD
- - ANG
- - AOA
- - ARS
- - AUD
- - AWG
- - AZN
- - BAM
- - BBD
- - BDT
- - BGN
- - BHD
- - BIF
- - BMD
- - BND
- - BOB
- - BRL
- - BSD
- - BTN
- - BWP
- - BYN
- - BZD
- - CAD
- - CDF
- - CHF
- - CLP
- - CNY
- - COP
- - CRC
- - CUP
- - CVE
- - CZK
- - DJF
- - DKK
- - DOP
- - DZD
- - EGP
- - ERN
- - ETB
- - EUR
- - FJD
- - FKP
- - FOK
- - GBP
- - GEL
- - GGP
- - GHS
- - GIP
- - GMD
- - GNF
- - GTQ
- - GYD
- - HKD
- - HNL
- - HRK
- - HTG
- - HUF
- - IDR
- - ILS
- - IMP
- - INR
- - IQD
- - IRR
- - ISK
- - JEP
- - JMD
- - JOD
- - JPY
- - KES
- - KGS
- - KHR
- - KID
- - KMF
- - KRW
- - KWD
- - KYD
- - KZT
- - LAK
- - LBP
- - LKR
- - LRD
- - LSL
- - LYD
- - MAD
- - MDL
- - MGA
- - MKD
- - MMK
- - MNT
- - MOP
- - MRU
- - MUR
- - MVR
- - MWK
- - MXN
- - MYR
- - MZN
- - NAD
- - NGN
- - NIO
- - NOK
- - NPR
- - NZD
- - OMR
- - PAB
- - PEN
- - PGK
- - PHP
- - PKR
- - PLN
- - PYG
- - QAR
- - RON
- - RSD
- - RUB
- - RWF
- - SAR
- - SBD
- - SCR
- - SDG
- - SEK
- - SGD
- - SHP
- - SLE
- - SLL
- - SOS
- - SRD
- - SSP
- - STN
- - SYP
- - SZL
- - THB
- - TJS
- - TMT
- - TND
- - TOP
- - TRY
- - TTD
- - TVD
- - TWD
- - TZS
- - UAH
- - UGX
- - USD
- - UYU
- - UZS
- - VES
- - VND
- - VUV
- - WST
- - XAF
- - XCD
- - XDR
- - XOF
- - XPF
- - YER
- - ZAR
- - ZMW
- - ZWL
description: The currency associated with the contact
remote_updated_at:
type: string
@@ -17490,7 +16115,7 @@ components:
description: The UUID of the associated company info
field_mappings:
type: object
- example: &ref_161
+ example: &ref_140
custom_field_1: value1
custom_field_2: value2
nullable: true
@@ -17563,7 +16188,6 @@ components:
type: string
example: USD
nullable: true
- enum: *ref_160
description: The currency associated with the contact
remote_updated_at:
type: string
@@ -17577,7 +16201,7 @@ components:
description: The UUID of the associated company info
field_mappings:
type: object
- example: *ref_161
+ example: *ref_140
nullable: true
description: >-
The custom field mappings of the object between the remote 3rd party
@@ -17637,169 +16261,6 @@ components:
currency:
type: string
example: USD
- enum:
- - AED
- - AFN
- - ALL
- - AMD
- - ANG
- - AOA
- - ARS
- - AUD
- - AWG
- - AZN
- - BAM
- - BBD
- - BDT
- - BGN
- - BHD
- - BIF
- - BMD
- - BND
- - BOB
- - BRL
- - BSD
- - BTN
- - BWP
- - BYN
- - BZD
- - CAD
- - CDF
- - CHF
- - CLP
- - CNY
- - COP
- - CRC
- - CUP
- - CVE
- - CZK
- - DJF
- - DKK
- - DOP
- - DZD
- - EGP
- - ERN
- - ETB
- - EUR
- - FJD
- - FKP
- - FOK
- - GBP
- - GEL
- - GGP
- - GHS
- - GIP
- - GMD
- - GNF
- - GTQ
- - GYD
- - HKD
- - HNL
- - HRK
- - HTG
- - HUF
- - IDR
- - ILS
- - IMP
- - INR
- - IQD
- - IRR
- - ISK
- - JEP
- - JMD
- - JOD
- - JPY
- - KES
- - KGS
- - KHR
- - KID
- - KMF
- - KRW
- - KWD
- - KYD
- - KZT
- - LAK
- - LBP
- - LKR
- - LRD
- - LSL
- - LYD
- - MAD
- - MDL
- - MGA
- - MKD
- - MMK
- - MNT
- - MOP
- - MRU
- - MUR
- - MVR
- - MWK
- - MXN
- - MYR
- - MZN
- - NAD
- - NGN
- - NIO
- - NOK
- - NPR
- - NZD
- - OMR
- - PAB
- - PEN
- - PGK
- - PHP
- - PKR
- - PLN
- - PYG
- - QAR
- - RON
- - RSD
- - RUB
- - RWF
- - SAR
- - SBD
- - SCR
- - SDG
- - SEK
- - SGD
- - SHP
- - SLE
- - SLL
- - SOS
- - SRD
- - SSP
- - STN
- - SYP
- - SZL
- - THB
- - TJS
- - TMT
- - TND
- - TOP
- - TRY
- - TTD
- - TVD
- - TWD
- - TZS
- - UAH
- - UGX
- - USD
- - UYU
- - UZS
- - VES
- - VND
- - VUV
- - WST
- - XAF
- - XCD
- - XDR
- - XOF
- - XPF
- - YER
- - ZAR
- - ZMW
- - ZWL
nullable: true
description: The currency of the credit note
payments:
@@ -17902,169 +16363,6 @@ components:
currency:
type: string
example: USD
- enum: &ref_162
- - AED
- - AFN
- - ALL
- - AMD
- - ANG
- - AOA
- - ARS
- - AUD
- - AWG
- - AZN
- - BAM
- - BBD
- - BDT
- - BGN
- - BHD
- - BIF
- - BMD
- - BND
- - BOB
- - BRL
- - BSD
- - BTN
- - BWP
- - BYN
- - BZD
- - CAD
- - CDF
- - CHF
- - CLP
- - CNY
- - COP
- - CRC
- - CUP
- - CVE
- - CZK
- - DJF
- - DKK
- - DOP
- - DZD
- - EGP
- - ERN
- - ETB
- - EUR
- - FJD
- - FKP
- - FOK
- - GBP
- - GEL
- - GGP
- - GHS
- - GIP
- - GMD
- - GNF
- - GTQ
- - GYD
- - HKD
- - HNL
- - HRK
- - HTG
- - HUF
- - IDR
- - ILS
- - IMP
- - INR
- - IQD
- - IRR
- - ISK
- - JEP
- - JMD
- - JOD
- - JPY
- - KES
- - KGS
- - KHR
- - KID
- - KMF
- - KRW
- - KWD
- - KYD
- - KZT
- - LAK
- - LBP
- - LKR
- - LRD
- - LSL
- - LYD
- - MAD
- - MDL
- - MGA
- - MKD
- - MMK
- - MNT
- - MOP
- - MRU
- - MUR
- - MVR
- - MWK
- - MXN
- - MYR
- - MZN
- - NAD
- - NGN
- - NIO
- - NOK
- - NPR
- - NZD
- - OMR
- - PAB
- - PEN
- - PGK
- - PHP
- - PKR
- - PLN
- - PYG
- - QAR
- - RON
- - RSD
- - RUB
- - RWF
- - SAR
- - SBD
- - SCR
- - SDG
- - SEK
- - SGD
- - SHP
- - SLE
- - SLL
- - SOS
- - SRD
- - SSP
- - STN
- - SYP
- - SZL
- - THB
- - TJS
- - TMT
- - TND
- - TOP
- - TRY
- - TTD
- - TVD
- - TWD
- - TZS
- - UAH
- - UGX
- - USD
- - UYU
- - UZS
- - VES
- - VND
- - VUV
- - WST
- - XAF
- - XCD
- - XDR
- - XOF
- - XPF
- - YER
- - ZAR
- - ZMW
- - ZWL
nullable: true
description: The currency of the expense
exchange_rate:
@@ -18093,7 +16391,7 @@ components:
nullable: true
description: The UUID of the associated company info
tracking_categories:
- example: &ref_163
+ example: &ref_141
- 801f9ede-c698-4e66-a7fc-48d19eebaa4f
nullable: true
description: The UUIDs of the tracking categories associated with the expense
@@ -18107,7 +16405,7 @@ components:
$ref: '#/components/schemas/LineItem'
field_mappings:
type: object
- example: &ref_164
+ example: &ref_142
custom_field_1: value1
custom_field_2: value2
nullable: true
@@ -18176,7 +16474,6 @@ components:
currency:
type: string
example: USD
- enum: *ref_162
nullable: true
description: The currency of the expense
exchange_rate:
@@ -18205,7 +16502,7 @@ components:
nullable: true
description: The UUID of the associated company info
tracking_categories:
- example: *ref_163
+ example: *ref_141
nullable: true
description: The UUIDs of the tracking categories associated with the expense
type: array
@@ -18218,7 +16515,7 @@ components:
$ref: '#/components/schemas/LineItem'
field_mappings:
type: object
- example: *ref_164
+ example: *ref_142
nullable: true
description: >-
The custom field mappings of the object between the remote 3rd party
@@ -18234,169 +16531,6 @@ components:
currency:
type: string
example: USD
- enum:
- - AED
- - AFN
- - ALL
- - AMD
- - ANG
- - AOA
- - ARS
- - AUD
- - AWG
- - AZN
- - BAM
- - BBD
- - BDT
- - BGN
- - BHD
- - BIF
- - BMD
- - BND
- - BOB
- - BRL
- - BSD
- - BTN
- - BWP
- - BYN
- - BZD
- - CAD
- - CDF
- - CHF
- - CLP
- - CNY
- - COP
- - CRC
- - CUP
- - CVE
- - CZK
- - DJF
- - DKK
- - DOP
- - DZD
- - EGP
- - ERN
- - ETB
- - EUR
- - FJD
- - FKP
- - FOK
- - GBP
- - GEL
- - GGP
- - GHS
- - GIP
- - GMD
- - GNF
- - GTQ
- - GYD
- - HKD
- - HNL
- - HRK
- - HTG
- - HUF
- - IDR
- - ILS
- - IMP
- - INR
- - IQD
- - IRR
- - ISK
- - JEP
- - JMD
- - JOD
- - JPY
- - KES
- - KGS
- - KHR
- - KID
- - KMF
- - KRW
- - KWD
- - KYD
- - KZT
- - LAK
- - LBP
- - LKR
- - LRD
- - LSL
- - LYD
- - MAD
- - MDL
- - MGA
- - MKD
- - MMK
- - MNT
- - MOP
- - MRU
- - MUR
- - MVR
- - MWK
- - MXN
- - MYR
- - MZN
- - NAD
- - NGN
- - NIO
- - NOK
- - NPR
- - NZD
- - OMR
- - PAB
- - PEN
- - PGK
- - PHP
- - PKR
- - PLN
- - PYG
- - QAR
- - RON
- - RSD
- - RUB
- - RWF
- - SAR
- - SBD
- - SCR
- - SDG
- - SEK
- - SGD
- - SHP
- - SLE
- - SLL
- - SOS
- - SRD
- - SSP
- - STN
- - SYP
- - SZL
- - THB
- - TJS
- - TMT
- - TND
- - TOP
- - TRY
- - TTD
- - TVD
- - TWD
- - TZS
- - UAH
- - UGX
- - USD
- - UYU
- - UZS
- - VES
- - VND
- - VUV
- - WST
- - XAF
- - XCD
- - XDR
- - XOF
- - XPF
- - YER
- - ZAR
- - ZMW
- - ZWL
nullable: true
description: The currency used in the income statement
start_period:
@@ -18507,169 +16641,6 @@ components:
currency:
type: string
example: USD
- enum: &ref_165
- - AED
- - AFN
- - ALL
- - AMD
- - ANG
- - AOA
- - ARS
- - AUD
- - AWG
- - AZN
- - BAM
- - BBD
- - BDT
- - BGN
- - BHD
- - BIF
- - BMD
- - BND
- - BOB
- - BRL
- - BSD
- - BTN
- - BWP
- - BYN
- - BZD
- - CAD
- - CDF
- - CHF
- - CLP
- - CNY
- - COP
- - CRC
- - CUP
- - CVE
- - CZK
- - DJF
- - DKK
- - DOP
- - DZD
- - EGP
- - ERN
- - ETB
- - EUR
- - FJD
- - FKP
- - FOK
- - GBP
- - GEL
- - GGP
- - GHS
- - GIP
- - GMD
- - GNF
- - GTQ
- - GYD
- - HKD
- - HNL
- - HRK
- - HTG
- - HUF
- - IDR
- - ILS
- - IMP
- - INR
- - IQD
- - IRR
- - ISK
- - JEP
- - JMD
- - JOD
- - JPY
- - KES
- - KGS
- - KHR
- - KID
- - KMF
- - KRW
- - KWD
- - KYD
- - KZT
- - LAK
- - LBP
- - LKR
- - LRD
- - LSL
- - LYD
- - MAD
- - MDL
- - MGA
- - MKD
- - MMK
- - MNT
- - MOP
- - MRU
- - MUR
- - MVR
- - MWK
- - MXN
- - MYR
- - MZN
- - NAD
- - NGN
- - NIO
- - NOK
- - NPR
- - NZD
- - OMR
- - PAB
- - PEN
- - PGK
- - PHP
- - PKR
- - PLN
- - PYG
- - QAR
- - RON
- - RSD
- - RUB
- - RWF
- - SAR
- - SBD
- - SCR
- - SDG
- - SEK
- - SGD
- - SHP
- - SLE
- - SLL
- - SOS
- - SRD
- - SSP
- - STN
- - SYP
- - SZL
- - THB
- - TJS
- - TMT
- - TND
- - TOP
- - TRY
- - TTD
- - TVD
- - TWD
- - TZS
- - UAH
- - UGX
- - USD
- - UYU
- - UZS
- - VES
- - VND
- - VUV
- - WST
- - XAF
- - XCD
- - XDR
- - XOF
- - XPF
- - YER
- - ZAR
- - ZMW
- - ZWL
nullable: true
description: The currency of the invoice
exchange_rate:
@@ -18718,7 +16689,7 @@ components:
nullable: true
description: The UUID of the associated accounting period
tracking_categories:
- example: &ref_166
+ example: &ref_143
- 801f9ede-c698-4e66-a7fc-48d19eebaa4f
- 801f9ede-c698-4e66-a7fc-48d19eebaa4f
nullable: true
@@ -18733,7 +16704,7 @@ components:
$ref: '#/components/schemas/LineItem'
field_mappings:
type: object
- example: &ref_167
+ example: &ref_144
custom_field_1: value1
custom_field_2: value2
nullable: true
@@ -18814,7 +16785,6 @@ components:
currency:
type: string
example: USD
- enum: *ref_165
nullable: true
description: The currency of the invoice
exchange_rate:
@@ -18863,7 +16833,7 @@ components:
nullable: true
description: The UUID of the associated accounting period
tracking_categories:
- example: *ref_166
+ example: *ref_143
nullable: true
description: The UUIDs of the tracking categories associated with the invoice
type: array
@@ -18876,7 +16846,7 @@ components:
$ref: '#/components/schemas/LineItem'
field_mappings:
type: object
- example: *ref_167
+ example: *ref_144
nullable: true
description: >-
The custom field mappings of the object between the remote 3rd party
@@ -18973,7 +16943,7 @@ components:
nullable: true
description: The date of the transaction
payments:
- example: &ref_168
+ example: &ref_145
- payment1
- payment2
nullable: true
@@ -18982,7 +16952,7 @@ components:
items:
type: string
applied_payments:
- example: &ref_169
+ example: &ref_146
- appliedPayment1
- appliedPayment2
nullable: true
@@ -18998,169 +16968,6 @@ components:
currency:
type: string
example: USD
- enum: &ref_170
- - AED
- - AFN
- - ALL
- - AMD
- - ANG
- - AOA
- - ARS
- - AUD
- - AWG
- - AZN
- - BAM
- - BBD
- - BDT
- - BGN
- - BHD
- - BIF
- - BMD
- - BND
- - BOB
- - BRL
- - BSD
- - BTN
- - BWP
- - BYN
- - BZD
- - CAD
- - CDF
- - CHF
- - CLP
- - CNY
- - COP
- - CRC
- - CUP
- - CVE
- - CZK
- - DJF
- - DKK
- - DOP
- - DZD
- - EGP
- - ERN
- - ETB
- - EUR
- - FJD
- - FKP
- - FOK
- - GBP
- - GEL
- - GGP
- - GHS
- - GIP
- - GMD
- - GNF
- - GTQ
- - GYD
- - HKD
- - HNL
- - HRK
- - HTG
- - HUF
- - IDR
- - ILS
- - IMP
- - INR
- - IQD
- - IRR
- - ISK
- - JEP
- - JMD
- - JOD
- - JPY
- - KES
- - KGS
- - KHR
- - KID
- - KMF
- - KRW
- - KWD
- - KYD
- - KZT
- - LAK
- - LBP
- - LKR
- - LRD
- - LSL
- - LYD
- - MAD
- - MDL
- - MGA
- - MKD
- - MMK
- - MNT
- - MOP
- - MRU
- - MUR
- - MVR
- - MWK
- - MXN
- - MYR
- - MZN
- - NAD
- - NGN
- - NIO
- - NOK
- - NPR
- - NZD
- - OMR
- - PAB
- - PEN
- - PGK
- - PHP
- - PKR
- - PLN
- - PYG
- - QAR
- - RON
- - RSD
- - RUB
- - RWF
- - SAR
- - SBD
- - SCR
- - SDG
- - SEK
- - SGD
- - SHP
- - SLE
- - SLL
- - SOS
- - SRD
- - SSP
- - STN
- - SYP
- - SZL
- - THB
- - TJS
- - TMT
- - TND
- - TOP
- - TRY
- - TTD
- - TVD
- - TWD
- - TZS
- - UAH
- - UGX
- - USD
- - UYU
- - UZS
- - VES
- - VND
- - VUV
- - WST
- - XAF
- - XCD
- - XDR
- - XOF
- - XPF
- - YER
- - ZAR
- - ZMW
- - ZWL
nullable: true
description: The currency of the journal entry
exchange_rate:
@@ -19179,7 +16986,7 @@ components:
nullable: true
description: The journal number
tracking_categories:
- example: &ref_171
+ example: &ref_147
- 801f9ede-c698-4e66-a7fc-48d19eebaa4f
nullable: true
description: >-
@@ -19205,7 +17012,7 @@ components:
$ref: '#/components/schemas/LineItem'
field_mappings:
type: object
- example: &ref_172
+ example: &ref_148
custom_field_1: value1
custom_field_2: value2
nullable: true
@@ -19265,14 +17072,14 @@ components:
nullable: true
description: The date of the transaction
payments:
- example: *ref_168
+ example: *ref_145
nullable: true
description: The payments associated with the journal entry
type: array
items:
type: string
applied_payments:
- example: *ref_169
+ example: *ref_146
nullable: true
description: The applied payments for the journal entry
type: array
@@ -19286,7 +17093,6 @@ components:
currency:
type: string
example: USD
- enum: *ref_170
nullable: true
description: The currency of the journal entry
exchange_rate:
@@ -19305,7 +17111,7 @@ components:
nullable: true
description: The journal number
tracking_categories:
- example: *ref_171
+ example: *ref_147
nullable: true
description: >-
The UUIDs of the tracking categories associated with the journal
@@ -19330,7 +17136,7 @@ components:
$ref: '#/components/schemas/LineItem'
field_mappings:
type: object
- example: *ref_172
+ example: *ref_148
nullable: true
description: >-
The custom field mappings of the object between the remote 3rd party
@@ -19362,169 +17168,6 @@ components:
currency:
type: string
example: USD
- enum: &ref_173
- - AED
- - AFN
- - ALL
- - AMD
- - ANG
- - AOA
- - ARS
- - AUD
- - AWG
- - AZN
- - BAM
- - BBD
- - BDT
- - BGN
- - BHD
- - BIF
- - BMD
- - BND
- - BOB
- - BRL
- - BSD
- - BTN
- - BWP
- - BYN
- - BZD
- - CAD
- - CDF
- - CHF
- - CLP
- - CNY
- - COP
- - CRC
- - CUP
- - CVE
- - CZK
- - DJF
- - DKK
- - DOP
- - DZD
- - EGP
- - ERN
- - ETB
- - EUR
- - FJD
- - FKP
- - FOK
- - GBP
- - GEL
- - GGP
- - GHS
- - GIP
- - GMD
- - GNF
- - GTQ
- - GYD
- - HKD
- - HNL
- - HRK
- - HTG
- - HUF
- - IDR
- - ILS
- - IMP
- - INR
- - IQD
- - IRR
- - ISK
- - JEP
- - JMD
- - JOD
- - JPY
- - KES
- - KGS
- - KHR
- - KID
- - KMF
- - KRW
- - KWD
- - KYD
- - KZT
- - LAK
- - LBP
- - LKR
- - LRD
- - LSL
- - LYD
- - MAD
- - MDL
- - MGA
- - MKD
- - MMK
- - MNT
- - MOP
- - MRU
- - MUR
- - MVR
- - MWK
- - MXN
- - MYR
- - MZN
- - NAD
- - NGN
- - NIO
- - NOK
- - NPR
- - NZD
- - OMR
- - PAB
- - PEN
- - PGK
- - PHP
- - PKR
- - PLN
- - PYG
- - QAR
- - RON
- - RSD
- - RUB
- - RWF
- - SAR
- - SBD
- - SCR
- - SDG
- - SEK
- - SGD
- - SHP
- - SLE
- - SLL
- - SOS
- - SRD
- - SSP
- - STN
- - SYP
- - SZL
- - THB
- - TJS
- - TMT
- - TND
- - TOP
- - TRY
- - TTD
- - TVD
- - TWD
- - TZS
- - UAH
- - UGX
- - USD
- - UYU
- - UZS
- - VES
- - VND
- - VUV
- - WST
- - XAF
- - XCD
- - XDR
- - XOF
- - XPF
- - YER
- - ZAR
- - ZMW
- - ZWL
nullable: true
description: The currency of the payment
exchange_rate:
@@ -19553,7 +17196,7 @@ components:
nullable: true
description: The UUID of the associated accounting period
tracking_categories:
- example: &ref_174
+ example: &ref_149
- 801f9ede-c698-4e66-a7fc-48d19eebaa4f
nullable: true
description: The UUIDs of the tracking categories associated with the payment
@@ -19567,7 +17210,7 @@ components:
$ref: '#/components/schemas/LineItem'
field_mappings:
type: object
- example: &ref_175
+ example: &ref_150
custom_field_1: value1
custom_field_2: value2
nullable: true
@@ -19636,7 +17279,6 @@ components:
currency:
type: string
example: USD
- enum: *ref_173
nullable: true
description: The currency of the payment
exchange_rate:
@@ -19665,7 +17307,7 @@ components:
nullable: true
description: The UUID of the associated accounting period
tracking_categories:
- example: *ref_174
+ example: *ref_149
nullable: true
description: The UUIDs of the tracking categories associated with the payment
type: array
@@ -19678,7 +17320,7 @@ components:
$ref: '#/components/schemas/LineItem'
field_mappings:
type: object
- example: *ref_175
+ example: *ref_150
nullable: true
description: >-
The custom field mappings of the object between the remote 3rd party
@@ -19802,169 +17444,6 @@ components:
currency:
type: string
example: USD
- enum: &ref_176
- - AED
- - AFN
- - ALL
- - AMD
- - ANG
- - AOA
- - ARS
- - AUD
- - AWG
- - AZN
- - BAM
- - BBD
- - BDT
- - BGN
- - BHD
- - BIF
- - BMD
- - BND
- - BOB
- - BRL
- - BSD
- - BTN
- - BWP
- - BYN
- - BZD
- - CAD
- - CDF
- - CHF
- - CLP
- - CNY
- - COP
- - CRC
- - CUP
- - CVE
- - CZK
- - DJF
- - DKK
- - DOP
- - DZD
- - EGP
- - ERN
- - ETB
- - EUR
- - FJD
- - FKP
- - FOK
- - GBP
- - GEL
- - GGP
- - GHS
- - GIP
- - GMD
- - GNF
- - GTQ
- - GYD
- - HKD
- - HNL
- - HRK
- - HTG
- - HUF
- - IDR
- - ILS
- - IMP
- - INR
- - IQD
- - IRR
- - ISK
- - JEP
- - JMD
- - JOD
- - JPY
- - KES
- - KGS
- - KHR
- - KID
- - KMF
- - KRW
- - KWD
- - KYD
- - KZT
- - LAK
- - LBP
- - LKR
- - LRD
- - LSL
- - LYD
- - MAD
- - MDL
- - MGA
- - MKD
- - MMK
- - MNT
- - MOP
- - MRU
- - MUR
- - MVR
- - MWK
- - MXN
- - MYR
- - MZN
- - NAD
- - NGN
- - NIO
- - NOK
- - NPR
- - NZD
- - OMR
- - PAB
- - PEN
- - PGK
- - PHP
- - PKR
- - PLN
- - PYG
- - QAR
- - RON
- - RSD
- - RUB
- - RWF
- - SAR
- - SBD
- - SCR
- - SDG
- - SEK
- - SGD
- - SHP
- - SLE
- - SLL
- - SOS
- - SRD
- - SSP
- - STN
- - SYP
- - SZL
- - THB
- - TJS
- - TMT
- - TND
- - TOP
- - TRY
- - TTD
- - TVD
- - TWD
- - TZS
- - UAH
- - UGX
- - USD
- - UYU
- - UZS
- - VES
- - VND
- - VUV
- - WST
- - XAF
- - XCD
- - XDR
- - XOF
- - XPF
- - YER
- - ZAR
- - ZMW
- - ZWL
nullable: true
description: The currency of the purchase order
exchange_rate:
@@ -19973,7 +17452,7 @@ components:
nullable: true
description: The exchange rate applied to the purchase order
tracking_categories:
- example: &ref_177
+ example: &ref_151
- 801f9ede-c698-4e66-a7fc-48d19eebaa4f
nullable: true
description: >-
@@ -19994,7 +17473,7 @@ components:
$ref: '#/components/schemas/LineItem'
field_mappings:
type: object
- example: &ref_178
+ example: &ref_152
custom_field_1: value1
custom_field_2: value2
nullable: true
@@ -20104,7 +17583,6 @@ components:
currency:
type: string
example: USD
- enum: *ref_176
nullable: true
description: The currency of the purchase order
exchange_rate:
@@ -20113,7 +17591,7 @@ components:
nullable: true
description: The exchange rate applied to the purchase order
tracking_categories:
- example: *ref_177
+ example: *ref_151
nullable: true
description: >-
The UUIDs of the tracking categories associated with the purchase
@@ -20133,7 +17611,7 @@ components:
$ref: '#/components/schemas/LineItem'
field_mappings:
type: object
- example: *ref_178
+ example: *ref_152
nullable: true
description: >-
The custom field mappings of the object between the remote 3rd party
@@ -20296,169 +17774,6 @@ components:
currency:
type: string
example: USD
- enum:
- - AED
- - AFN
- - ALL
- - AMD
- - ANG
- - AOA
- - ARS
- - AUD
- - AWG
- - AZN
- - BAM
- - BBD
- - BDT
- - BGN
- - BHD
- - BIF
- - BMD
- - BND
- - BOB
- - BRL
- - BSD
- - BTN
- - BWP
- - BYN
- - BZD
- - CAD
- - CDF
- - CHF
- - CLP
- - CNY
- - COP
- - CRC
- - CUP
- - CVE
- - CZK
- - DJF
- - DKK
- - DOP
- - DZD
- - EGP
- - ERN
- - ETB
- - EUR
- - FJD
- - FKP
- - FOK
- - GBP
- - GEL
- - GGP
- - GHS
- - GIP
- - GMD
- - GNF
- - GTQ
- - GYD
- - HKD
- - HNL
- - HRK
- - HTG
- - HUF
- - IDR
- - ILS
- - IMP
- - INR
- - IQD
- - IRR
- - ISK
- - JEP
- - JMD
- - JOD
- - JPY
- - KES
- - KGS
- - KHR
- - KID
- - KMF
- - KRW
- - KWD
- - KYD
- - KZT
- - LAK
- - LBP
- - LKR
- - LRD
- - LSL
- - LYD
- - MAD
- - MDL
- - MGA
- - MKD
- - MMK
- - MNT
- - MOP
- - MRU
- - MUR
- - MVR
- - MWK
- - MXN
- - MYR
- - MZN
- - NAD
- - NGN
- - NIO
- - NOK
- - NPR
- - NZD
- - OMR
- - PAB
- - PEN
- - PGK
- - PHP
- - PKR
- - PLN
- - PYG
- - QAR
- - RON
- - RSD
- - RUB
- - RWF
- - SAR
- - SBD
- - SCR
- - SDG
- - SEK
- - SGD
- - SHP
- - SLE
- - SLL
- - SOS
- - SRD
- - SSP
- - STN
- - SYP
- - SZL
- - THB
- - TJS
- - TMT
- - TND
- - TOP
- - TRY
- - TTD
- - TVD
- - TWD
- - TZS
- - UAH
- - UGX
- - USD
- - UYU
- - UZS
- - VES
- - VND
- - VUV
- - WST
- - XAF
- - XCD
- - XDR
- - XOF
- - XPF
- - YER
- - ZAR
- - ZMW
- - ZWL
nullable: true
description: The currency of the transaction
tracking_categories:
@@ -20568,169 +17883,6 @@ components:
type: string
example: USD
nullable: true
- enum:
- - AED
- - AFN
- - ALL
- - AMD
- - ANG
- - AOA
- - ARS
- - AUD
- - AWG
- - AZN
- - BAM
- - BBD
- - BDT
- - BGN
- - BHD
- - BIF
- - BMD
- - BND
- - BOB
- - BRL
- - BSD
- - BTN
- - BWP
- - BYN
- - BZD
- - CAD
- - CDF
- - CHF
- - CLP
- - CNY
- - COP
- - CRC
- - CUP
- - CVE
- - CZK
- - DJF
- - DKK
- - DOP
- - DZD
- - EGP
- - ERN
- - ETB
- - EUR
- - FJD
- - FKP
- - FOK
- - GBP
- - GEL
- - GGP
- - GHS
- - GIP
- - GMD
- - GNF
- - GTQ
- - GYD
- - HKD
- - HNL
- - HRK
- - HTG
- - HUF
- - IDR
- - ILS
- - IMP
- - INR
- - IQD
- - IRR
- - ISK
- - JEP
- - JMD
- - JOD
- - JPY
- - KES
- - KGS
- - KHR
- - KID
- - KMF
- - KRW
- - KWD
- - KYD
- - KZT
- - LAK
- - LBP
- - LKR
- - LRD
- - LSL
- - LYD
- - MAD
- - MDL
- - MGA
- - MKD
- - MMK
- - MNT
- - MOP
- - MRU
- - MUR
- - MVR
- - MWK
- - MXN
- - MYR
- - MZN
- - NAD
- - NGN
- - NIO
- - NOK
- - NPR
- - NZD
- - OMR
- - PAB
- - PEN
- - PGK
- - PHP
- - PKR
- - PLN
- - PYG
- - QAR
- - RON
- - RSD
- - RUB
- - RWF
- - SAR
- - SBD
- - SCR
- - SDG
- - SEK
- - SGD
- - SHP
- - SLE
- - SLL
- - SOS
- - SRD
- - SSP
- - STN
- - SYP
- - SZL
- - THB
- - TJS
- - TMT
- - TND
- - TOP
- - TRY
- - TTD
- - TVD
- - TWD
- - TZS
- - UAH
- - UGX
- - USD
- - UYU
- - UZS
- - VES
- - VND
- - VUV
- - WST
- - XAF
- - XCD
- - XDR
- - XOF
- - XPF
- - YER
- - ZAR
- - ZMW
- - ZWL
description: The currency of the vendor credit
exchange_rate:
type: string
@@ -20910,7 +18062,7 @@ components:
nullable: true
field_mappings:
type: object
- example: &ref_179
+ example: &ref_153
fav_dish: broccoli
fav_color: red
description: >-
@@ -20996,7 +18148,7 @@ components:
nullable: true
field_mappings:
type: object
- example: *ref_179
+ example: *ref_153
description: >-
The custom field mappings of the object between the remote 3rd party
& Panora
@@ -21054,7 +18206,7 @@ components:
description: The UUID of the permission tied to the folder
field_mappings:
type: object
- example: &ref_180
+ example: &ref_154
fav_dish: broccoli
fav_color: red
additionalProperties: true
@@ -21145,7 +18297,7 @@ components:
description: The UUID of the permission tied to the folder
field_mappings:
type: object
- example: *ref_180
+ example: *ref_154
additionalProperties: true
nullable: true
description: >-
@@ -21310,13 +18462,9 @@ components:
type: string
example: ACTIVE
nullable: true
- enum: &ref_181
- - ARCHIVED
- - ACTIVE
- - DRAFT
description: The status of the product. Either ACTIVE, DRAFT OR ARCHIVED.
images_urls:
- example: &ref_182
+ example: &ref_155
- https://myproduct/image
nullable: true
description: The URLs of the product images
@@ -21334,7 +18482,7 @@ components:
nullable: true
description: The vendor of the product
variants:
- example: &ref_183
+ example: &ref_156
- title: teeshirt
price: 20
sku: '3'
@@ -21346,7 +18494,7 @@ components:
items:
$ref: '#/components/schemas/Variant'
tags:
- example: &ref_184
+ example: &ref_157
- tag_1
nullable: true
description: The tags associated with the product
@@ -21355,7 +18503,7 @@ components:
type: string
field_mappings:
type: object
- example: &ref_185
+ example: &ref_158
fav_dish: broccoli
fav_color: red
nullable: true
@@ -21406,10 +18554,9 @@ components:
type: string
example: ACTIVE
nullable: true
- enum: *ref_181
description: The status of the product. Either ACTIVE, DRAFT OR ARCHIVED.
images_urls:
- example: *ref_182
+ example: *ref_155
nullable: true
description: The URLs of the product images
type: array
@@ -21426,13 +18573,13 @@ components:
nullable: true
description: The vendor of the product
variants:
- example: *ref_183
+ example: *ref_156
description: The variants of the product
type: array
items:
$ref: '#/components/schemas/Variant'
tags:
- example: *ref_184
+ example: *ref_157
nullable: true
description: The tags associated with the product
type: array
@@ -21440,7 +18587,7 @@ components:
type: string
field_mappings:
type: object
- example: *ref_185
+ example: *ref_158
nullable: true
description: >-
The custom field mappings of the object between the remote 3rd party
@@ -21451,11 +18598,6 @@ components:
order_status:
type: string
example: UNSHIPPED
- enum: &ref_186
- - PENDING
- - UNSHIPPED
- - SHIPPED
- - CANCELED
nullable: true
description: The status of the order
order_number:
@@ -21466,178 +18608,12 @@ components:
payment_status:
type: string
example: SUCCESS
- enum: &ref_187
- - SUCCESS
- - FAIL
nullable: true
description: The payment status of the order
currency:
type: string
nullable: true
example: AUD
- enum: &ref_188
- - AED
- - AFN
- - ALL
- - AMD
- - ANG
- - AOA
- - ARS
- - AUD
- - AWG
- - AZN
- - BAM
- - BBD
- - BDT
- - BGN
- - BHD
- - BIF
- - BMD
- - BND
- - BOB
- - BRL
- - BSD
- - BTN
- - BWP
- - BYN
- - BZD
- - CAD
- - CDF
- - CHF
- - CLP
- - CNY
- - COP
- - CRC
- - CUP
- - CVE
- - CZK
- - DJF
- - DKK
- - DOP
- - DZD
- - EGP
- - ERN
- - ETB
- - EUR
- - FJD
- - FKP
- - FOK
- - GBP
- - GEL
- - GGP
- - GHS
- - GIP
- - GMD
- - GNF
- - GTQ
- - GYD
- - HKD
- - HNL
- - HRK
- - HTG
- - HUF
- - IDR
- - ILS
- - IMP
- - INR
- - IQD
- - IRR
- - ISK
- - JEP
- - JMD
- - JOD
- - JPY
- - KES
- - KGS
- - KHR
- - KID
- - KMF
- - KRW
- - KWD
- - KYD
- - KZT
- - LAK
- - LBP
- - LKR
- - LRD
- - LSL
- - LYD
- - MAD
- - MDL
- - MGA
- - MKD
- - MMK
- - MNT
- - MOP
- - MRU
- - MUR
- - MVR
- - MWK
- - MXN
- - MYR
- - MZN
- - NAD
- - NGN
- - NIO
- - NOK
- - NPR
- - NZD
- - OMR
- - PAB
- - PEN
- - PGK
- - PHP
- - PKR
- - PLN
- - PYG
- - QAR
- - RON
- - RSD
- - RUB
- - RWF
- - SAR
- - SBD
- - SCR
- - SDG
- - SEK
- - SGD
- - SHP
- - SLE
- - SLL
- - SOS
- - SRD
- - SSP
- - STN
- - SYP
- - SZL
- - THB
- - TJS
- - TMT
- - TND
- - TOP
- - TRY
- - TTD
- - TVD
- - TWD
- - TZS
- - UAH
- - UGX
- - USD
- - UYU
- - UZS
- - VES
- - VND
- - VUV
- - WST
- - XAF
- - XCD
- - XDR
- - XOF
- - XPF
- - YER
- - ZAR
- - ZMW
- - ZWL
description: >-
The currency of the order. Authorized value must be of type
CurrencyCode (ISO 4217)
@@ -21665,10 +18641,6 @@ components:
type: string
nullable: true
example: PENDING
- enum: &ref_189
- - PENDING
- - FULFILLED
- - CANCELED
description: The fulfillment status of the order
customer_id:
type: string
@@ -21677,7 +18649,7 @@ components:
description: The UUID of the customer associated with the order
items:
nullable: true
- example: &ref_190
+ example: &ref_159
- remote_id: '12345'
product_id: prod_001
variant_id: var_001
@@ -21708,7 +18680,7 @@ components:
$ref: '#/components/schemas/LineItem'
field_mappings:
type: object
- example: &ref_191
+ example: &ref_160
fav_dish: broccoli
fav_color: red
nullable: true
@@ -21748,7 +18720,6 @@ components:
order_status:
type: string
example: UNSHIPPED
- enum: *ref_186
nullable: true
description: The status of the order
order_number:
@@ -21759,14 +18730,12 @@ components:
payment_status:
type: string
example: SUCCESS
- enum: *ref_187
nullable: true
description: The payment status of the order
currency:
type: string
nullable: true
example: AUD
- enum: *ref_188
description: >-
The currency of the order. Authorized value must be of type
CurrencyCode (ISO 4217)
@@ -21794,7 +18763,6 @@ components:
type: string
nullable: true
example: PENDING
- enum: *ref_189
description: The fulfillment status of the order
customer_id:
type: string
@@ -21803,14 +18771,14 @@ components:
description: The UUID of the customer associated with the order
items:
nullable: true
- example: *ref_190
+ example: *ref_159
description: The items in the order
type: array
items:
$ref: '#/components/schemas/LineItem'
field_mappings:
type: object
- example: *ref_191
+ example: *ref_160
nullable: true
description: >-
The custom field mappings of the object between the remote 3rd party
@@ -21987,7 +18955,7 @@ components:
field_mappings:
type: object
nullable: true
- example: &ref_192
+ example: &ref_161
fav_dish: broccoli
fav_color: red
description: >-
@@ -22059,7 +19027,7 @@ components:
field_mappings:
type: object
nullable: true
- example: *ref_192
+ example: *ref_161
description: >-
The custom field mappings of the attachment between the remote 3rd
party & Panora
From baf95fe27e971432f1816a41b05dfe2cc5bdca60 Mon Sep 17 00:00:00 2001
From: mit-27
Date: Wed, 28 Aug 2024 21:40:17 -0600
Subject: [PATCH 23/49] =?UTF-8?q?=E2=9C=A8=20Tested=20all=20objects=20and?=
=?UTF-8?q?=20fix=20bugs?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../services/microsoftdynamicssales/index.ts | 24 ++++++++++++----
.../services/microsoftdynamicssales/index.ts | 23 +++++++++++----
.../services/microsoftdynamicssales/index.ts | 28 +++++++++++++++----
.../microsoftdynamicssales/mappers.ts | 6 ++--
.../services/microsoftdynamicssales/index.ts | 20 +++++++++++--
.../services/microsoftdynamicssales/index.ts | 18 ++++++++++--
.../microsoftdynamicssales/mappers.ts | 4 +--
packages/shared/src/connectors/metadata.ts | 2 +-
8 files changed, 100 insertions(+), 25 deletions(-)
diff --git a/packages/api/src/crm/company/services/microsoftdynamicssales/index.ts b/packages/api/src/crm/company/services/microsoftdynamicssales/index.ts
index b04664a29..4ff25e07d 100644
--- a/packages/api/src/crm/company/services/microsoftdynamicssales/index.ts
+++ b/packages/api/src/crm/company/services/microsoftdynamicssales/index.ts
@@ -39,11 +39,9 @@ export class MicrosoftdynamicssalesService implements ICompanyService {
},
});
- const resp = await axios.post(
+ const respToPost = await axios.post(
`${connection.account_url}/api/data/v9.2/accounts`,
- JSON.stringify({
- data: companyData,
- }),
+ JSON.stringify(companyData),
{
headers: {
Authorization: `Bearer ${this.cryptoService.decrypt(
@@ -53,8 +51,24 @@ export class MicrosoftdynamicssalesService implements ICompanyService {
},
},
);
+
+ const postCompanyId = respToPost.headers['location'].split("/").pop();
+ // console.log(res.headers['location'].split('(')[1].split(')')[0])
+
+ const resp = await axios.get(
+ `${connection.account_url}/api/data/v9.2/${postCompanyId}`,
+ {
+ headers: {
+ 'Content-Type': 'application/json',
+ Authorization: `Bearer ${this.cryptoService.decrypt(
+ connection.access_token,
+ )}`,
+ },
+ },
+ );
+
return {
- data: resp.data.value,
+ data: resp.data,
message: 'Microsoftdynamicssales company created',
statusCode: 201,
};
diff --git a/packages/api/src/crm/contact/services/microsoftdynamicssales/index.ts b/packages/api/src/crm/contact/services/microsoftdynamicssales/index.ts
index f585e6966..caeeb9891 100644
--- a/packages/api/src/crm/contact/services/microsoftdynamicssales/index.ts
+++ b/packages/api/src/crm/contact/services/microsoftdynamicssales/index.ts
@@ -38,11 +38,9 @@ export class MicrosoftdynamicssalesService implements IContactService {
},
});
- const resp = await axios.post(
+ const respToPost = await axios.post(
`${connection.account_url}/api/data/v9.2/contacts`,
- JSON.stringify({
- data: contactData,
- }),
+ JSON.stringify(contactData),
{
headers: {
'Content-Type': 'application/json',
@@ -52,8 +50,23 @@ export class MicrosoftdynamicssalesService implements IContactService {
},
},
);
+
+ const postContactId = respToPost.headers['location'].split("/").pop();
+
+ const resp = await axios.get(
+ `${connection.account_url}/api/data/v9.2/${postContactId}`,
+ {
+ headers: {
+ accept: 'application/json',
+ 'Content-Type': 'application/json',
+ Authorization: `Bearer ${this.cryptoService.decrypt(
+ connection.access_token,
+ )}`,
+ },
+ },
+ );
return {
- data: resp.data.value,
+ data: resp.data,
message: 'microsoftdynamicssales contact created',
statusCode: 201,
};
diff --git a/packages/api/src/crm/deal/services/microsoftdynamicssales/index.ts b/packages/api/src/crm/deal/services/microsoftdynamicssales/index.ts
index 12979121b..fd93e9d74 100644
--- a/packages/api/src/crm/deal/services/microsoftdynamicssales/index.ts
+++ b/packages/api/src/crm/deal/services/microsoftdynamicssales/index.ts
@@ -37,11 +37,9 @@ export class MicrosoftdynamicssalesService implements IDealService {
},
});
- const resp = await axios.post(
+ const respToPost = await axios.post(
`${connection.account_url}/api/data/v9.2/opportunities`,
- JSON.stringify({
- data: dealData,
- }),
+ JSON.stringify(dealData),
{
headers: {
Authorization: `Bearer ${this.cryptoService.decrypt(
@@ -51,8 +49,28 @@ export class MicrosoftdynamicssalesService implements IDealService {
},
},
);
+
+ const postDealId = respToPost.headers['location'].split("/").pop();
+
+ const resp = await axios.get(
+ `${connection.account_url}/api/data/v9.2/${postDealId}`,
+ {
+ headers: {
+ accept: 'application/json',
+ 'Content-Type': 'application/json',
+ Authorization: `Bearer ${this.cryptoService.decrypt(
+ connection.access_token,
+ )}`,
+ },
+ },
+ );
+
+
+
+
+
return {
- data: resp.data.value,
+ data: resp.data,
message: 'Microsoftdynamicssales deal created',
statusCode: 201,
};
diff --git a/packages/api/src/crm/deal/services/microsoftdynamicssales/mappers.ts b/packages/api/src/crm/deal/services/microsoftdynamicssales/mappers.ts
index b8e64523d..a1ca99212 100644
--- a/packages/api/src/crm/deal/services/microsoftdynamicssales/mappers.ts
+++ b/packages/api/src/crm/deal/services/microsoftdynamicssales/mappers.ts
@@ -24,7 +24,7 @@ export class MicrosoftdynamicssalesDealMapper implements IDealMapper {
const result: MicrosoftdynamicssalesDealInput = {
name: source.name,
description: source.description,
- totalamount: source.amount
+ budgetamount: source.amount
}
@@ -103,9 +103,9 @@ export class MicrosoftdynamicssalesDealMapper implements IDealMapper {
}
}
- if (deal._accountid_value) {
+ if (deal._customerid_value) {
const company_id = await this.utils.getCompanyUuidFromRemoteId(
- deal._accountid_value,
+ deal._customerid_value,
connectionId
);
if (company_id) {
diff --git a/packages/api/src/crm/note/services/microsoftdynamicssales/index.ts b/packages/api/src/crm/note/services/microsoftdynamicssales/index.ts
index 8a17ca8d7..475fba1e5 100644
--- a/packages/api/src/crm/note/services/microsoftdynamicssales/index.ts
+++ b/packages/api/src/crm/note/services/microsoftdynamicssales/index.ts
@@ -36,7 +36,7 @@ export class MicrosoftdynamicssalesService implements INoteService {
vertical: 'crm',
},
});
- const resp = await axios.post(
+ const respToPost = await axios.post(
`${connection.account_url}/api/data/v9.2/annotations`,
JSON.stringify(noteData),
{
@@ -48,8 +48,24 @@ export class MicrosoftdynamicssalesService implements INoteService {
},
},
);
+
+ const postNoteId = respToPost.headers['location'].split("/").pop();
+
+ const resp = await axios.get(
+ `${connection.account_url}/api/data/v9.2/${postNoteId}`
+ , {
+ headers: {
+ 'Content-Type': 'application/json',
+ Authorization: `Bearer ${this.cryptoService.decrypt(
+ connection.access_token,
+ )}`,
+ },
+ });
+
+
+
return {
- data: resp?.data.value,
+ data: resp?.data,
message: 'Microsoftdynamicssales note created',
statusCode: 201,
};
diff --git a/packages/api/src/crm/task/services/microsoftdynamicssales/index.ts b/packages/api/src/crm/task/services/microsoftdynamicssales/index.ts
index b536fc781..3888854b6 100644
--- a/packages/api/src/crm/task/services/microsoftdynamicssales/index.ts
+++ b/packages/api/src/crm/task/services/microsoftdynamicssales/index.ts
@@ -36,7 +36,7 @@ export class MicrosoftdynamicssalesService implements ITaskService {
vertical: 'crm',
},
});
- const resp = await axios.post(
+ const respToPost = await axios.post(
`${connection.account_url}/api/data/v9.2/tasks`,
JSON.stringify(taskData),
{
@@ -49,8 +49,22 @@ export class MicrosoftdynamicssalesService implements ITaskService {
},
);
+ const postTaskId = respToPost.headers['location'].split("/").pop();
+
+ const resp = await axios.get(
+ `${connection.account_url}/api/data/v9.2/${postTaskId}`, {
+ headers: {
+ 'Content-Type': 'application/json',
+ Authorization: `Bearer ${this.cryptoService.decrypt(
+ connection.access_token,
+ )}`,
+ },
+ });
+
+
+
return {
- data: resp?.data?.value,
+ data: resp?.data,
message: 'Microsoftdynamicssales task created',
statusCode: 201,
};
diff --git a/packages/api/src/crm/task/services/microsoftdynamicssales/mappers.ts b/packages/api/src/crm/task/services/microsoftdynamicssales/mappers.ts
index 794a2e2fd..28020d540 100644
--- a/packages/api/src/crm/task/services/microsoftdynamicssales/mappers.ts
+++ b/packages/api/src/crm/task/services/microsoftdynamicssales/mappers.ts
@@ -31,11 +31,11 @@ export class MicrosoftdynamicssalesTaskMapper implements ITaskMapper {
}
if (source.due_date) {
- result.scheduledend = source.due_date.toUTCString();
+ result.scheduledend = new Date(source.due_date).toUTCString();
}
if (source.finished_date) {
- result.actualend = source.finished_date.toUTCString();
+ result.actualend = new Date(source.finished_date).toUTCString();
}
// User have to provide either company_id or deal_id which will be associated with current task
diff --git a/packages/shared/src/connectors/metadata.ts b/packages/shared/src/connectors/metadata.ts
index b31075d44..b5baeafac 100644
--- a/packages/shared/src/connectors/metadata.ts
+++ b/packages/shared/src/connectors/metadata.ts
@@ -3090,4 +3090,4 @@ export const CONNECTORS_METADATA: ProvidersConfig = {
}
},
}
-};
\ No newline at end of file
+};
From ff9e4a6c6231bed73836db862b28fc17a43c66ef Mon Sep 17 00:00:00 2001
From: Irwansyah
Date: Fri, 30 Aug 2024 20:23:12 +0700
Subject: [PATCH 24/49] fix: limit query param to use the correct int type
instead of string
---
packages/api/src/ats/user/user.controller.ts | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/packages/api/src/ats/user/user.controller.ts b/packages/api/src/ats/user/user.controller.ts
index fdbcc2d37..9b2b50fcb 100644
--- a/packages/api/src/ats/user/user.controller.ts
+++ b/packages/api/src/ats/user/user.controller.ts
@@ -8,6 +8,8 @@ import {
Param,
Headers,
UseGuards,
+ UsePipes,
+ ValidationPipe,
} from '@nestjs/common';
import { LoggerService } from '@@core/@core-services/logger/logger.service';
import {
@@ -57,6 +59,12 @@ export class UserController {
@ApiPaginatedResponse(UnifiedAtsUserOutput)
@UseGuards(ApiKeyAuthGuard)
@Get()
+ @UsePipes(
+ new ValidationPipe({
+ transform: true,
+ transformOptions: { enableImplicitConversion: true },
+ }),
+ )
async getUsers(
@Headers('x-connection-token') connection_token: string,
@Query() query: QueryDto,
From 87324457e3616f4181ffa62c8f42e18a885774c1 Mon Sep 17 00:00:00 2001
From: mit-27
Date: Fri, 30 Aug 2024 20:21:09 -0600
Subject: [PATCH 25/49] =?UTF-8?q?=E2=9C=A8=20Add=20engagement=20object?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
apps/magic-link/src/lib/ProviderModal.tsx | 2 +-
.../utils/types/original/original.crm.ts | 6 +-
.../src/crm/engagement/engagement.module.ts | 4 +
.../services/microsoftdynamicssales/index.ts | 361 ++++++++++++
.../microsoftdynamicssales/mappers.ts | 518 ++++++++++++++++++
.../services/microsoftdynamicssales/types.ts | 276 ++++++++++
6 files changed, 1164 insertions(+), 3 deletions(-)
create mode 100644 packages/api/src/crm/engagement/services/microsoftdynamicssales/index.ts
create mode 100644 packages/api/src/crm/engagement/services/microsoftdynamicssales/mappers.ts
create mode 100644 packages/api/src/crm/engagement/services/microsoftdynamicssales/types.ts
diff --git a/apps/magic-link/src/lib/ProviderModal.tsx b/apps/magic-link/src/lib/ProviderModal.tsx
index e08a2238c..f7bc182c0 100644
--- a/apps/magic-link/src/lib/ProviderModal.tsx
+++ b/apps/magic-link/src/lib/ProviderModal.tsx
@@ -22,7 +22,7 @@ interface IBasicAuthFormData {
}
const domainFormats: { [key: string]: string } = {
- microsoftdynamicssales: 'YOURORGNAME.api.crm12.dynamics.com',
+ microsoftdynamicssales: 'YOURORGNAME.api.crm3.dynamics.com',
bigcommerce: 'If your api domain is https://api.bigcommerce.com/stores/eubckcvkzg/v3 then store_hash is eubckcvkzg',
};
diff --git a/packages/api/src/@core/utils/types/original/original.crm.ts b/packages/api/src/@core/utils/types/original/original.crm.ts
index 2e64529d6..61503dad2 100644
--- a/packages/api/src/@core/utils/types/original/original.crm.ts
+++ b/packages/api/src/@core/utils/types/original/original.crm.ts
@@ -1,3 +1,5 @@
+import { MicrosoftdynamicssalesEngagementInput, MicrosoftdynamicssalesEngagementOutput } from '@crm/engagement/services/microsoftdynamicssales/types';
+
import { MicrosoftdynamicssalesTaskInput, MicrosoftdynamicssalesTaskOutput } from '@crm/task/services/microsoftdynamicssales/types';
import { MicrosoftdynamicssalesNoteInput, MicrosoftdynamicssalesNoteOutput } from '@crm/note/services/microsoftdynamicssales/types';
@@ -186,7 +188,7 @@ export type OriginalEngagementInput =
| ZohoEngagementInput
| ZendeskEngagementInput
| PipedriveEngagementInput
- | CloseEngagementInput;
+ | CloseEngagementInput | MicrosoftdynamicssalesEngagementInput;
/* note */
export type OriginalNoteInput =
@@ -268,7 +270,7 @@ export type OriginalEngagementOutput =
| ZohoEngagementOutput
| ZendeskEngagementOutput
| PipedriveEngagementOutput
- | CloseEngagementOutput;
+ | CloseEngagementOutput | MicrosoftdynamicssalesEngagementOutput;
/* note */
export type OriginalNoteOutput =
diff --git a/packages/api/src/crm/engagement/engagement.module.ts b/packages/api/src/crm/engagement/engagement.module.ts
index 4da6c55b5..bc2c9b92c 100644
--- a/packages/api/src/crm/engagement/engagement.module.ts
+++ b/packages/api/src/crm/engagement/engagement.module.ts
@@ -1,3 +1,5 @@
+import { MicrosoftdynamicssalesEngagementMapper } from './services/microsoftdynamicssales/mappers';
+import { MicrosoftdynamicssalesService } from './services/microsoftdynamicssales';
import { EncryptionService } from '@@core/@core-services/encryption/encryption.service';
import { LoggerService } from '@@core/@core-services/logger/logger.service';
import { BullQueueModule } from '@@core/@core-services/queues/queue.module';
@@ -48,6 +50,8 @@ import { SyncService } from './sync/sync.service';
PipedriveEngagementMapper,
HubspotEngagementMapper,
CloseEngagementMapper,
+ MicrosoftdynamicssalesService,
+ MicrosoftdynamicssalesEngagementMapper,
],
exports: [SyncService, ServiceRegistry, WebhookService],
})
diff --git a/packages/api/src/crm/engagement/services/microsoftdynamicssales/index.ts b/packages/api/src/crm/engagement/services/microsoftdynamicssales/index.ts
new file mode 100644
index 000000000..27c89a3a6
--- /dev/null
+++ b/packages/api/src/crm/engagement/services/microsoftdynamicssales/index.ts
@@ -0,0 +1,361 @@
+import { EncryptionService } from '@@core/@core-services/encryption/encryption.service';
+import { LoggerService } from '@@core/@core-services/logger/logger.service';
+import { PrismaService } from '@@core/@core-services/prisma/prisma.service';
+import { ApiResponse } from '@@core/utils/types';
+import { SyncParam } from '@@core/utils/types/interface';
+import { CrmObject } from '@crm/@lib/@types';
+import { IEngagementService } from '@crm/engagement/types';
+import { Injectable } from '@nestjs/common';
+import axios from 'axios';
+import { ServiceRegistry } from '../registry.service';
+import {
+ MicrosoftdynamicssalesEngagementAppointmentInput,
+ MicrosoftdynamicssalesEngagementAppointmentOutput,
+ MicrosoftdynamicssalesEngagementCallInput,
+ MicrosoftdynamicssalesEngagementCallOutput,
+ MicrosoftdynamicssalesEngagementEmailInput,
+ MicrosoftdynamicssalesEngagementEmailOutput,
+ MicrosoftdynamicssalesEngagementInput,
+ MicrosoftdynamicssalesEngagementOutput
+} from './types';
+
+@Injectable()
+export class MicrosoftdynamicssalesService implements IEngagementService {
+ constructor(
+ private prisma: PrismaService,
+ private logger: LoggerService,
+ private cryptoService: EncryptionService,
+ private registry: ServiceRegistry,
+ ) {
+ this.logger.setContext(
+ CrmObject.engagement.toUpperCase() + ':' + MicrosoftdynamicssalesService.name,
+ );
+ this.registry.registerService('microsoftdynamicssales', this);
+ }
+ async addEngagement(
+ engagementData: MicrosoftdynamicssalesEngagementInput,
+ linkedUserId: string,
+ engagement_type: string,
+ ): Promise> {
+ try {
+ switch (engagement_type) {
+ case 'CALL':
+ return this.addCall(
+ engagementData as MicrosoftdynamicssalesEngagementCallInput,
+ linkedUserId,
+ );
+ case 'MEETING':
+ return this.addMeeting(
+ engagementData as MicrosoftdynamicssalesEngagementAppointmentInput,
+ linkedUserId,
+ );
+ case 'EMAIL':
+ return this.addEmail(
+ engagementData as MicrosoftdynamicssalesEngagementEmailInput,
+ linkedUserId,
+ );
+ default:
+ break;
+ }
+ } catch (error) {
+ throw error;
+ }
+ }
+
+ private async addCall(
+ engagementData: MicrosoftdynamicssalesEngagementCallInput,
+ linkedUserId: string,
+ ): Promise> {
+ try {
+ const connection = await this.prisma.connections.findFirst({
+ where: {
+ id_linked_user: linkedUserId,
+ provider_slug: 'microsoftdynamicssales',
+ vertical: 'crm',
+ },
+ });
+
+ const respToPost = await axios.post(
+ `${connection.account_url}/api/data/v9.2/phonecalls`,
+ JSON.stringify(engagementData),
+ {
+ headers: {
+ 'Content-Type': 'application/json',
+ Authorization: `Bearer ${this.cryptoService.decrypt(
+ connection.access_token,
+ )}`,
+ },
+ },
+ );
+
+ const postCallId = respToPost.headers['location'].split("/").pop();
+
+ const resp = await axios.get(
+ `${connection.account_url}/api/data/v9.2/${postCallId}`,
+ {
+ headers: {
+ 'Content-Type': 'application/json',
+ Authorization: `Bearer ${this.cryptoService.decrypt(
+ connection.access_token,
+ )}`,
+ },
+ });
+
+ return {
+ data: resp.data,
+ message: 'Microsoftdynamicssales call created',
+ statusCode: 201,
+ };
+ } catch (error) {
+ throw error;
+ }
+ }
+
+ private async addMeeting(
+ engagementData: MicrosoftdynamicssalesEngagementAppointmentInput,
+ linkedUserId: string,
+ ): Promise> {
+ try {
+ const connection = await this.prisma.connections.findFirst({
+ where: {
+ id_linked_user: linkedUserId,
+ provider_slug: 'microsoftdynamicssales',
+ vertical: 'crm',
+ },
+ });
+
+ const respToPost = await axios.post(
+ `${connection.account_url}/api/data/v9.2/appointments`,
+ JSON.stringify(engagementData),
+ {
+ headers: {
+ 'Content-Type': 'application/json',
+ Authorization: `Bearer ${this.cryptoService.decrypt(
+ connection.access_token,
+ )}`,
+ },
+ },
+ );
+
+ const postAppointmentId = respToPost.headers['location'].split("/").pop();
+
+ const resp = await axios.get(
+ `${connection.account_url}/api/data/v9.2/${postAppointmentId}`,
+ {
+ headers: {
+ 'Content-Type': 'application/json',
+ Authorization: `Bearer ${this.cryptoService.decrypt(
+ connection.access_token,
+ )}`,
+ },
+ });
+
+
+ return {
+ data: resp.data,
+ message: 'Microsoftdynamicssales meeting created',
+ statusCode: 201,
+ };
+ } catch (error) {
+ throw error;
+ }
+ }
+
+ private async addEmail(
+ engagementData: MicrosoftdynamicssalesEngagementEmailInput,
+ linkedUserId: string,
+ ): Promise> {
+ try {
+ const connection = await this.prisma.connections.findFirst({
+ where: {
+ id_linked_user: linkedUserId,
+ provider_slug: 'microsoftdynamicssales',
+ vertical: 'crm',
+ },
+ });
+
+ const respToPost = await axios.post(
+ `${connection.account_url}/api/data/v9.2/emails`,
+ JSON.stringify(engagementData),
+ {
+ headers: {
+ 'Content-Type': 'application/json',
+ Authorization: `Bearer ${this.cryptoService.decrypt(
+ connection.access_token,
+ )}`,
+ },
+ },
+ );
+
+ const postEmailId = respToPost.headers['location'].split("/").pop();
+
+ const resp = await axios.get(
+ `${connection.account_url}/api/data/v9.2/${postEmailId}`,
+ {
+ headers: {
+ 'Content-Type': 'application/json',
+ Authorization: `Bearer ${this.cryptoService.decrypt(
+ connection.access_token,
+ )}`,
+ },
+ });
+
+
+ return {
+ data: resp.data,
+ message: 'Microsoftdynamicssales email created',
+ statusCode: 201,
+ };
+ } catch (error) {
+ throw error;
+ }
+ }
+
+ async sync(data: SyncParam): Promise> {
+ try {
+ const { linkedUserId, custom_properties, engagement_type } = data;
+
+ switch (engagement_type as string) {
+ case 'CALL':
+ return this.syncCalls(linkedUserId, custom_properties);
+ case 'MEETING':
+ return this.syncMeetings(linkedUserId, custom_properties);
+ case 'EMAIL':
+ return this.syncEmails(linkedUserId, custom_properties);
+ default:
+ break;
+ }
+ } catch (error) {
+ throw error;
+ }
+ }
+
+ private async syncCalls(linkedUserId: string, custom_properties?: string[]) {
+ try {
+ const connection = await this.prisma.connections.findFirst({
+ where: {
+ id_linked_user: linkedUserId,
+ provider_slug: 'microsoftdynamicssales',
+ vertical: 'crm',
+ },
+ });
+
+ // const commonPropertyNames = Object.keys(commonCallMicrosoftdynamicssaleProperties);
+ // const allProperties = [...commonPropertyNames, ...custom_properties];
+ // const baseURL = 'https://api.hubapi.com/crm/v3/objects/calls';
+
+ // const queryString = allProperties
+ // .map((prop) => `properties=${encodeURIComponent(prop)}`)
+ // .join('&');
+
+ // const url = `${baseURL}?${queryString}`;
+
+ const resp = await axios.get(
+ `${connection.account_url}/api/data/v9.2/phonecalls`,
+ {
+ headers: {
+ 'Content-Type': 'application/json',
+ Authorization: `Bearer ${this.cryptoService.decrypt(
+ connection.access_token,
+ )}`,
+ },
+ });
+ this.logger.log(`Synced microsoftdynamicssales engagements calls !`);
+
+ return {
+ data: resp.data.value,
+ message: 'Microsoftdynamicssales engagements calls retrieved',
+ statusCode: 200,
+ };
+ } catch (error) {
+ throw error;
+ }
+ }
+
+ private async syncMeetings(
+ linkedUserId: string,
+ custom_properties?: string[],
+ ) {
+ try {
+ const connection = await this.prisma.connections.findFirst({
+ where: {
+ id_linked_user: linkedUserId,
+ provider_slug: 'microsoftdynamicssales',
+ vertical: 'crm',
+ },
+ });
+
+ // const commonPropertyNames = Object.keys(commonMeetingMicrosoftdynamicssaleProperties);
+ // const allProperties = [...commonPropertyNames, ...custom_properties];
+ // const baseURL = 'https://api.hubapi.com/crm/v3/objects/meetings';
+
+ // const queryString = allProperties
+ // .map((prop) => `properties=${encodeURIComponent(prop)}`)
+ // .join('&');
+
+ // const url = `${baseURL}?${queryString}`;
+
+ const resp = await axios.get(
+ `${connection.account_url}/api/data/v9.2/appointments`,
+ {
+ headers: {
+ 'Content-Type': 'application/json',
+ Authorization: `Bearer ${this.cryptoService.decrypt(
+ connection.access_token,
+ )}`,
+ },
+ });
+ this.logger.log(`Synced microsoftdynamicssales engagements meetings !`);
+
+ return {
+ data: resp.data.value,
+ message: 'Microsoftdynamicssales engagements meetings retrieved',
+ statusCode: 200,
+ };
+ } catch (error) {
+ throw error;
+ }
+ }
+
+ private async syncEmails(linkedUserId: string, custom_properties?: string[]) {
+ try {
+ const connection = await this.prisma.connections.findFirst({
+ where: {
+ id_linked_user: linkedUserId,
+ provider_slug: 'microsoftdynamicssales',
+ vertical: 'crm',
+ },
+ });
+
+ // const commonPropertyNames = Object.keys(commonEmailMicrosoftdynamicssaleProperties);
+ // const allProperties = [...commonPropertyNames, ...custom_properties];
+ // const baseURL = 'https://api.hubapi.com/crm/v3/objects/emails';
+
+ // const queryString = allProperties
+ // .map((prop) => `properties=${encodeURIComponent(prop)}`)
+ // .join('&');
+
+ // const url = `${baseURL}?${queryString}`;
+
+ const resp = await axios.get(
+ `${connection.account_url}/api/data/v9.2/emails`,
+ {
+ headers: {
+ 'Content-Type': 'application/json',
+ Authorization: `Bearer ${this.cryptoService.decrypt(
+ connection.access_token,
+ )}`,
+ },
+ });
+ this.logger.log(`Synced microsoftdynamicssales engagements emails !`);
+
+ return {
+ data: resp.data.value,
+ message: 'Microsoftdynamicssales engagements emails retrieved',
+ statusCode: 200,
+ };
+ } catch (error) {
+ throw error;
+ }
+ }
+}
diff --git a/packages/api/src/crm/engagement/services/microsoftdynamicssales/mappers.ts b/packages/api/src/crm/engagement/services/microsoftdynamicssales/mappers.ts
new file mode 100644
index 000000000..95333a57b
--- /dev/null
+++ b/packages/api/src/crm/engagement/services/microsoftdynamicssales/mappers.ts
@@ -0,0 +1,518 @@
+import {
+ MicrosoftdynamicssalesEngagementAppointmentInput,
+ MicrosoftdynamicssalesEngagementAppointmentOutput,
+ MicrosoftdynamicssalesEngagementCallInput,
+ MicrosoftdynamicssalesEngagementCallOutput,
+ MicrosoftdynamicssalesEngagementEmailInput,
+ MicrosoftdynamicssalesEngagementEmailOutput,
+ MicrosoftdynamicssalesEngagementInput,
+ MicrosoftdynamicssalesEngagementOutput
+} from './types';
+import {
+ UnifiedCrmEngagementInput,
+ UnifiedCrmEngagementOutput,
+} from '@crm/engagement/types/model.unified';
+import { IEngagementMapper } from '@crm/engagement/types';
+import { Utils } from '@crm/@lib/@utils';
+import { MappersRegistry } from '@@core/@core-services/registries/mappers.registry';
+import { Injectable } from '@nestjs/common';
+
+@Injectable()
+export class MicrosoftdynamicssalesEngagementMapper implements IEngagementMapper {
+ constructor(private mappersRegistry: MappersRegistry, private utils: Utils) {
+ this.mappersRegistry.registerService('crm', 'engagement', 'microsoftdynamicssales', this);
+ }
+
+ async desunify(
+ source: UnifiedCrmEngagementInput,
+ customFieldMappings?: {
+ slug: string;
+ remote_id: string;
+ }[],
+ ): Promise {
+ const type = source.type;
+ switch (type) {
+ case 'CALL':
+ return await this.desunifyCall(source, customFieldMappings);
+ case 'MEETING':
+ return await this.desunifyMeeting(source, customFieldMappings);
+ case 'EMAIL':
+ return await this.desunifyEmail(source, customFieldMappings);
+ default:
+ break;
+ }
+ return;
+ }
+
+ private async desunifyCall(
+ source: UnifiedCrmEngagementInput,
+ customFieldMappings?: {
+ slug: string;
+ remote_id: string;
+ }[],
+ ): Promise {
+ const result: MicrosoftdynamicssalesEngagementCallInput = {
+ description: source.content ?? '',
+ subject: source.subject ?? '',
+ };
+
+ if (source.start_at) {
+ result.actualstart = new Date(source.start_at).toUTCString();
+ }
+
+ if (source.end_time) {
+ result.actualend = new Date(source.end_time).toUTCString();
+ }
+
+ if (source.direction) {
+ result.directioncode = source.direction === 'INBOUND' ? false : true;
+
+ }
+
+ if (source.company_id) {
+ const id = await this.utils.getRemoteIdFromCompanyUuid(source.company_id);
+ result["regardingobjectid_account@odata.bind"] = `/accounts(${id})`;
+ }
+
+ // Only assigning first contact from contacts
+ if (source.contacts && source.contacts.length > 0) {
+ const id = await this.utils.getRemoteIdFromContactUuid(source.contacts[0]);
+ result["regardingobjectid_contact@odata.bind"] = `/contacts(${id})`;
+ }
+
+ if (customFieldMappings && source.field_mappings) {
+ for (const [k, v] of Object.entries(source.field_mappings)) {
+ const mapping = customFieldMappings.find(
+ (mapping) => mapping.slug === k,
+ );
+ if (mapping) {
+ result[mapping.remote_id] = v;
+ }
+ }
+ }
+
+ return result;
+ }
+
+ private async desunifyMeeting(
+ source: UnifiedCrmEngagementInput,
+ customFieldMappings?: {
+ slug: string;
+ remote_id: string;
+ }[],
+ ): Promise {
+ const result: MicrosoftdynamicssalesEngagementAppointmentInput = {
+ description: source.content ?? '',
+ subject: source.subject ?? '',
+ };
+
+ if (source.start_at) {
+ result.actualstart = new Date(source.start_at).toUTCString();
+ }
+
+ if (source.end_time) {
+ result.actualend = new Date(source.end_time).toUTCString();
+ }
+
+ if (source.company_id) {
+ const id = await this.utils.getRemoteIdFromCompanyUuid(source.company_id);
+ result["regardingobjectid_account@odata.bind"] = `/accounts(${id})`;
+ }
+
+ // Only assigning first contact from contacts
+ if (source.contacts && source.contacts.length > 0) {
+ const id = await this.utils.getRemoteIdFromContactUuid(source.contacts[0]);
+ result["regardingobjectid_contact@odata.bind"] = `/contacts(${id})`;
+ }
+
+ if (customFieldMappings && source.field_mappings) {
+ for (const [k, v] of Object.entries(source.field_mappings)) {
+ const mapping = customFieldMappings.find(
+ (mapping) => mapping.slug === k,
+ );
+ if (mapping) {
+ result[mapping.remote_id] = v;
+ }
+ }
+ }
+
+ return result;
+ }
+
+ private async desunifyEmail(
+ source: UnifiedCrmEngagementInput,
+ customFieldMappings?: {
+ slug: string;
+ remote_id: string;
+ }[],
+ ): Promise {
+ const result: MicrosoftdynamicssalesEngagementEmailInput = {
+ description: source.content ?? '',
+ subject: source.subject ?? '',
+ };
+
+ if (source.start_at) {
+ result.actualstart = new Date(source.start_at).toUTCString();
+ }
+
+ if (source.end_time) {
+ result.actualend = new Date(source.end_time).toUTCString();
+ }
+
+ if (source.direction) {
+ result.directioncode = source.direction === 'INBOUND' ? false : true;
+
+ }
+
+ if (source.company_id) {
+ const id = await this.utils.getRemoteIdFromCompanyUuid(source.company_id);
+ result["regardingobjectid_account@odata.bind"] = `/accounts(${id})`;
+ }
+
+ // Only assigning first contact from contacts
+ if (source.contacts && source.contacts.length > 0) {
+ const id = await this.utils.getRemoteIdFromContactUuid(source.contacts[0]);
+ result["regardingobjectid_contact@odata.bind"] = `/contacts(${id})`;
+ }
+
+
+ if (customFieldMappings && source.field_mappings) {
+ for (const [k, v] of Object.entries(source.field_mappings)) {
+ const mapping = customFieldMappings.find(
+ (mapping) => mapping.slug === k,
+ );
+ if (mapping) {
+ result[mapping.remote_id] = v;
+ }
+ }
+ }
+
+ return result;
+ }
+
+ async unify(
+ source: MicrosoftdynamicssalesEngagementOutput | MicrosoftdynamicssalesEngagementOutput[],
+ engagement_type: string,
+ connectionId: string,
+ customFieldMappings?: {
+ slug: string;
+ remote_id: string;
+ }[],
+ ): Promise {
+ switch (engagement_type) {
+ case 'CALL':
+ return await this.unifyCall(
+ source as MicrosoftdynamicssalesEngagementCallOutput | MicrosoftdynamicssalesEngagementCallOutput[],
+ connectionId,
+ customFieldMappings,
+ );
+ case 'MEETING':
+ return await this.unifyMeeting(
+ source as
+ | MicrosoftdynamicssalesEngagementAppointmentOutput
+ | MicrosoftdynamicssalesEngagementAppointmentOutput[],
+ connectionId,
+ customFieldMappings,
+ );
+ case 'EMAIL':
+ return await this.unifyEmail(
+ source as
+ | MicrosoftdynamicssalesEngagementEmailOutput
+ | MicrosoftdynamicssalesEngagementEmailOutput[],
+ connectionId,
+ customFieldMappings,
+ );
+ default:
+ break;
+ }
+ }
+
+ private async unifyCall(
+ source: MicrosoftdynamicssalesEngagementCallOutput | MicrosoftdynamicssalesEngagementCallOutput[],
+ connectionId: string,
+ customFieldMappings?: {
+ slug: string;
+ remote_id: string;
+ }[],
+ ) {
+ if (!Array.isArray(source)) {
+ return this.mapSingleEngagementCallToUnified(
+ source,
+ connectionId,
+ customFieldMappings,
+ );
+ }
+ // Handling array of MicrosoftdynamicssalesEngagementOutput
+ return Promise.all(
+ source.map((engagement) =>
+ this.mapSingleEngagementCallToUnified(
+ engagement,
+ connectionId,
+ customFieldMappings,
+ ),
+ ),
+ );
+ }
+
+ private async unifyMeeting(
+ source: MicrosoftdynamicssalesEngagementAppointmentOutput | MicrosoftdynamicssalesEngagementAppointmentOutput[],
+ connectionId: string,
+ customFieldMappings?: {
+ slug: string;
+ remote_id: string;
+ }[],
+ ) {
+ if (!Array.isArray(source)) {
+ return this.mapSingleEngagementMeetingToUnified(
+ source,
+ connectionId,
+ customFieldMappings,
+ );
+ }
+ // Handling array of MicrosoftdynamicssalesEngagementOutput
+ return Promise.all(
+ source.map((engagement) =>
+ this.mapSingleEngagementMeetingToUnified(
+ engagement,
+ connectionId,
+ customFieldMappings,
+ ),
+ ),
+ );
+ }
+
+ private async unifyEmail(
+ source: MicrosoftdynamicssalesEngagementEmailOutput | MicrosoftdynamicssalesEngagementEmailOutput[],
+ connectionId: string,
+ customFieldMappings?: {
+ slug: string;
+ remote_id: string;
+ }[],
+ ) {
+ if (!Array.isArray(source)) {
+ return this.mapSingleEngagementEmailToUnified(
+ source,
+ connectionId,
+ customFieldMappings,
+ );
+ }
+ // Handling array of MicrosoftdynamicssalesEngagementOutput
+ return Promise.all(
+ source.map((engagement) =>
+ this.mapSingleEngagementEmailToUnified(
+ engagement,
+ connectionId,
+ customFieldMappings,
+ ),
+ ),
+ );
+ }
+
+ private async mapSingleEngagementCallToUnified(
+ engagement: MicrosoftdynamicssalesEngagementCallOutput,
+ connectionId: string,
+ customFieldMappings?: {
+ slug: string;
+ remote_id: string;
+ }[],
+ ): Promise {
+ const field_mappings: { [key: string]: any } = {};
+ if (customFieldMappings) {
+ for (const mapping of customFieldMappings) {
+ field_mappings[mapping.slug] = engagement[mapping.remote_id];
+ }
+ }
+
+ let opts: any = {};
+ if (engagement._ownerid_value) {
+ const owner_id = await this.utils.getUserUuidFromRemoteId(
+ engagement._ownerid_value,
+ connectionId,
+ );
+ if (owner_id) {
+ opts = {
+ ...opts,
+ user_id: owner_id,
+ };
+ }
+ }
+
+ if (engagement._regardingobjectid_value) {
+ const company_id = await this.utils.getCompanyUuidFromRemoteId(
+ engagement._regardingobjectid_value,
+ connectionId
+ );
+
+ if (company_id) {
+ opts = {
+ ...opts,
+ company_id: company_id
+ }
+ }
+
+ const contact_id = await this.utils.getContactUuidFromRemoteId(
+ engagement._regardingobjectid_value,
+ connectionId
+ );
+
+ if (contact_id) {
+ opts = {
+ ...opts,
+ contacts: [contact_id]
+ }
+ }
+ }
+
+
+
+ return {
+ remote_data: engagement,
+ remote_id: engagement.activityid,
+ content: engagement.description ?? '',
+ subject: engagement.subject ?? '',
+ start_at: engagement.actualstart ? new Date(engagement.actualstart) : null,
+ end_time: engagement.actualend ? new Date(engagement.actualend) : null,
+ type: 'CALL',
+ direction: engagement.directioncode ? engagement.directioncode ? "OUTBOUND" : "INBOUND" : null,
+ field_mappings,
+ ...opts,
+ };
+ }
+
+ private async mapSingleEngagementMeetingToUnified(
+ engagement: MicrosoftdynamicssalesEngagementAppointmentOutput,
+ connectionId: string,
+ customFieldMappings?: {
+ slug: string;
+ remote_id: string;
+ }[],
+ ): Promise {
+ const field_mappings: { [key: string]: any } = {};
+ if (customFieldMappings) {
+ for (const mapping of customFieldMappings) {
+ field_mappings[mapping.slug] = engagement[mapping.remote_id];
+ }
+ }
+
+ let opts: any = {};
+ if (engagement._ownerid_value) {
+ const owner_id = await this.utils.getUserUuidFromRemoteId(
+ engagement._ownerid_value,
+ connectionId,
+ );
+ if (owner_id) {
+ opts = {
+ ...opts,
+ user_id: owner_id,
+ };
+ }
+ }
+
+ if (engagement._regardingobjectid_value) {
+ const company_id = await this.utils.getCompanyUuidFromRemoteId(
+ engagement._regardingobjectid_value,
+ connectionId
+ );
+
+ if (company_id) {
+ opts = {
+ ...opts,
+ company_id: company_id
+ }
+ }
+
+ const contact_id = await this.utils.getContactUuidFromRemoteId(
+ engagement._regardingobjectid_value,
+ connectionId
+ );
+
+ if (contact_id) {
+ opts = {
+ ...opts,
+ contacts: [contact_id]
+ }
+ }
+ }
+
+ return {
+ remote_data: engagement,
+ remote_id: engagement.activityid,
+ content: engagement.description ?? '',
+ subject: engagement.subject ?? '',
+ start_at: engagement.actualstart ? new Date(engagement.actualstart) : null,
+ end_time: engagement.actualend ? new Date(engagement.actualend) : null,
+ type: 'MEETING',
+ field_mappings,
+ ...opts,
+ };
+ }
+
+ private async mapSingleEngagementEmailToUnified(
+ engagement: MicrosoftdynamicssalesEngagementEmailOutput,
+ connectionId: string,
+ customFieldMappings?: {
+ slug: string;
+ remote_id: string;
+ }[],
+ ): Promise {
+ const field_mappings: { [key: string]: any } = {};
+ if (customFieldMappings) {
+ for (const mapping of customFieldMappings) {
+ field_mappings[mapping.slug] = engagement[mapping.remote_id];
+ }
+ }
+
+ let opts: any = {};
+ if (engagement._ownerid_value) {
+ const owner_id = await this.utils.getUserUuidFromRemoteId(
+ engagement._ownerid_value,
+ connectionId,
+ );
+ if (owner_id) {
+ opts = {
+ ...opts,
+ user_id: owner_id,
+ };
+ }
+ }
+
+ if (engagement._regardingobjectid_value) {
+ const company_id = await this.utils.getCompanyUuidFromRemoteId(
+ engagement._regardingobjectid_value,
+ connectionId
+ );
+
+ if (company_id) {
+ opts = {
+ ...opts,
+ company_id: company_id
+ }
+ }
+
+ const contact_id = await this.utils.getContactUuidFromRemoteId(
+ engagement._regardingobjectid_value,
+ connectionId
+ );
+
+ if (contact_id) {
+ opts = {
+ ...opts,
+ contacts: [contact_id]
+ }
+ }
+ }
+
+ return {
+ remote_id: engagement.activityid,
+ remote_data: engagement,
+ content: engagement.description ?? '',
+ start_at: engagement.actualstart ? new Date(engagement.actualstart) : null,
+ end_time: engagement.actualend ? new Date(engagement.actualend) : null,
+ subject: engagement.subject ?? '',
+ type: 'EMAIL',
+ direction: engagement.directioncode ? engagement.directioncode ? "OUTBOUND" : "INBOUND" : null,
+ field_mappings,
+ ...opts,
+ };
+ }
+}
diff --git a/packages/api/src/crm/engagement/services/microsoftdynamicssales/types.ts b/packages/api/src/crm/engagement/services/microsoftdynamicssales/types.ts
new file mode 100644
index 000000000..92a7f8f97
--- /dev/null
+++ b/packages/api/src/crm/engagement/services/microsoftdynamicssales/types.ts
@@ -0,0 +1,276 @@
+interface MicrosoftdynamicssalesEmail {
+ activityadditionalparams: string;
+ activityid: string; // Guid
+ activitytypecode: string;
+ actualdurationminutes: number;
+ actualend: string;
+ actualstart: string;
+ attachmentcount: number;
+ attachmentopencount: number;
+ baseconversationindexhash: number;
+ category: string;
+ community: number;
+ compressed: boolean;
+ conversationindex: string;
+ conversationtrackingid: string; // Guid
+ correlatedsubjectchanged: boolean;
+ correlationmethod: number;
+ createdon: string;
+ delayedemailsendtime: string;
+ deliveryattempts: number;
+ deliverylastattemptedon: string;
+ deliveryprioritycode: number;
+ deliveryreceiptrequested: boolean;
+ description: string;
+ descriptionblobid: string; // Binary
+ descriptionblobid_name: string;
+ directioncode: boolean;
+ emailreminderexpirytime: string;
+ emailreminderstatus: number;
+ emailremindertext: string;
+ emailremindertype: number;
+ emailtrackingid: string; // Guid
+ exchangeitemid: string;
+ exchangerate: number;
+ exchangeweblink: string;
+ followemailuserpreference: boolean;
+ formattedscheduledend: string;
+ formattedscheduledstart: string;
+ importsequencenumber: number;
+ inreplyto: string;
+ instancetypecode: number;
+ internetmessageheaders: string;
+ isbilled: boolean;
+ isduplicatesenderunresolved: boolean;
+ isemailfollowed: boolean;
+ isemailreminderset: boolean;
+ ismapiprivate: boolean;
+ isregularactivity: boolean;
+ isunsafe: number;
+ isworkflowcreated: boolean;
+ lastonholdtime: string;
+ lastopenedtime: string;
+ leftvoicemail: boolean;
+ linksclickedcount: number;
+ messageid: string;
+ mimetype: string;
+ modifiedon: string;
+ notifications: number;
+ onholdtime: number;
+ opencount: number;
+ overriddencreatedon: string;
+ postponeactivityprocessinguntil: string;
+ postponeemailprocessinguntil: string;
+ prioritycode: number;
+ processid: string; // Guid
+ readreceiptrequested: boolean;
+ reminderactioncardid: string; // Guid
+ replycount: number;
+ reservedforinternaluse: string;
+ safedescription: string;
+ scheduleddurationminutes: number;
+ scheduledend: string;
+ scheduledstart: string;
+ sender: string;
+ senton: string;
+ seriesid: string; // Guid
+ sortdate: string;
+ stageid: string; // Guid
+ statecode: number;
+ statuscode: number;
+ subcategory: string;
+ subject: string;
+ submittedby: string;
+ timezoneruleversionnumber: number;
+ torecipients: string;
+ trackingtoken: string;
+ traversedpath: string;
+ utcconversiontimezonecode: number;
+ versionnumber: number;
+ _acceptingentityid_value: string;
+ _createdby_value: string;
+ _createdonbehalfby_value: string;
+ _emailsender_value: string;
+ _modifiedby_value: string;
+ _modifiedonbehalfby_value: string;
+ _ownerid_value: string;
+ _owningbusinessunit_value: string;
+ _owningteam_value: string;
+ _owninguser_value: string;
+ _receivingmailboxid_value: string;
+ _regardingobjectid_value: string;
+ _sendermailboxid_value: string;
+ _sendersaccount_value: string;
+ _slaid_value: string;
+ _slainvokedid_value: string;
+ _templateid_value: string;
+ _transactioncurrencyid_value: string;
+ [key: string]: any;
+}
+
+interface MicrosoftdynamicssalesAppointment {
+ activityadditionalparams: string;
+ activityid: string; // Guid
+ activitytypecode: string;
+ actualdurationminutes: number;
+ actualend: string;
+ actualstart: string;
+ attachmenterrors: number;
+ category: string;
+ community: number;
+ createdon: string;
+ deliverylastattemptedon: string;
+ deliveryprioritycode: number;
+ description: string;
+ descriptionblobid: string; // Binary
+ descriptionblobid_name: string;
+ exchangeitemid: string;
+ exchangerate: number;
+ exchangeweblink: string;
+ formattedscheduledend: string;
+ formattedscheduledstart: string;
+ globalobjectid: string;
+ importsequencenumber: number;
+ instancetypecode: number;
+ isalldayevent: boolean;
+ isbilled: boolean;
+ isdraft: boolean;
+ ismapiprivate: boolean;
+ isonlinemeeting: boolean;
+ isregularactivity: boolean;
+ isunsafe: number;
+ isworkflowcreated: boolean;
+ lastonholdtime: string;
+ leftvoicemail: boolean;
+ location: string;
+ modifiedfieldsmask: string;
+ modifiedon: string;
+ onholdtime: number;
+ onlinemeetingchatid: string;
+ onlinemeetingid: string;
+ onlinemeetingjoinurl: string;
+ onlinemeetingtype: number;
+ originalstartdate: string;
+ outlookownerapptid: number;
+ overriddencreatedon: string;
+ postponeactivityprocessinguntil: string;
+ prioritycode: number;
+ processid: string; // Guid
+ scheduleddurationminutes: number;
+ scheduledend: string;
+ scheduledstart: string;
+ senton: string;
+ seriesid: string; // Guid
+ sortdate: string;
+ stageid: string; // Guid
+ statecode: number;
+ statuscode: number;
+ subcategory: string;
+ subject: string;
+ subscriptionid: string; // Guid
+ timezoneruleversionnumber: number;
+ traversedpath: string;
+ utcconversiontimezonecode: number;
+ versionnumber: number;
+ _createdby_value: string;
+ _createdonbehalfby_value: string;
+ _modifiedby_value: string;
+ _modifiedonbehalfby_value: string;
+ _ownerid_value: string;
+ _owningbusinessunit_value: string;
+ _owningteam_value: string;
+ _owninguser_value: string;
+ _regardingobjectid_value: string;
+ _sendermailboxid_value: string;
+ _slaid_value: string;
+ _slainvokedid_value: string;
+ _transactioncurrencyid_value: string;
+ [key: string]: any;
+}
+
+interface MicrosoftdynamicssalesPhoneCall {
+ activityadditionalparams: string;
+ activityid: string; // Guid
+ activitytypecode: string;
+ actualdurationminutes: number;
+ actualend: string;
+ actualstart: string;
+ category: string;
+ community: number;
+ createdon: string;
+ deliverylastattemptedon: string;
+ deliveryprioritycode: number;
+ description: string;
+ descriptionblobid: string; // Binary
+ descriptionblobid_name: string;
+ directioncode: boolean;
+ exchangeitemid: string;
+ exchangerate: number;
+ exchangeweblink: string;
+ formattedscheduledend: string;
+ formattedscheduledstart: string;
+ importsequencenumber: number;
+ instancetypecode: number;
+ isbilled: boolean;
+ ismapiprivate: boolean;
+ isregularactivity: boolean;
+ isworkflowcreated: boolean;
+ lastonholdtime: string;
+ leftvoicemail: boolean;
+ modifiedon: string;
+ onholdtime: number;
+ overriddencreatedon: string;
+ phonenumber: string;
+ postponeactivityprocessinguntil: string;
+ prioritycode: number;
+ processid: string; // Guid
+ scheduleddurationminutes: number;
+ scheduledend: string;
+ scheduledstart: string;
+ senton: string;
+ seriesid: string; // Guid
+ sortdate: string;
+ stageid: string; // Guid
+ statecode: number;
+ statuscode: number;
+ subcategory: string;
+ subject: string;
+ subscriptionid: string; // Guid
+ timezoneruleversionnumber: number;
+ traversedpath: string;
+ utcconversiontimezonecode: number;
+ versionnumber: number;
+ _createdby_value: string;
+ _createdonbehalfby_value: string;
+ _modifiedby_value: string;
+ _modifiedonbehalfby_value: string;
+ _ownerid_value: string;
+ _owningbusinessunit_value: string;
+ _owningteam_value: string;
+ _owninguser_value: string;
+ _regardingobjectid_value: string;
+ _sendermailboxid_value: string;
+ _slaid_value: string;
+ _slainvokedid_value: string;
+ _transactioncurrencyid_value: string;
+ [key: string]: any;
+}
+
+export type MicrosoftdynamicssalesEngagementCallInput = Partial;
+export type MicrosoftdynamicssalesEngagementCallOutput = MicrosoftdynamicssalesEngagementCallInput;
+
+export type MicrosoftdynamicssalesEngagementEmailInput = Partial;
+export type MicrosoftdynamicssalesEngagementEmailOutput = MicrosoftdynamicssalesEngagementEmailInput;
+
+export type MicrosoftdynamicssalesEngagementAppointmentInput = Partial;
+export type MicrosoftdynamicssalesEngagementAppointmentOutput = MicrosoftdynamicssalesEngagementAppointmentInput;
+
+
+export type MicrosoftdynamicssalesEngagementInput = MicrosoftdynamicssalesEngagementCallInput
+ | MicrosoftdynamicssalesEngagementEmailInput
+ | MicrosoftdynamicssalesEngagementAppointmentInput;
+
+export type MicrosoftdynamicssalesEngagementOutput = MicrosoftdynamicssalesEngagementCallOutput
+ | MicrosoftdynamicssalesEngagementEmailOutput
+ | MicrosoftdynamicssalesEngagementAppointmentOutput;
+
From efa7c5ffc462eff509cbaf8f1f2f11615ff25e2e Mon Sep 17 00:00:00 2001
From: mit <1mitccc@gmail.com>
Date: Sat, 31 Aug 2024 08:28:04 +0530
Subject: [PATCH 26/49] Add customer object for webflow-ecommerce-connector
---
packages/api/scripts/init.sql | 3 +-
packages/api/scripts/seed.sql | 8 +-
.../types/original/original.ecommerce.ts | 11 ++-
.../src/ecommerce/customer/customer.module.ts | 4 +
.../customer/services/webflow/index.ts | 60 ++++++++++++
.../customer/services/webflow/mappers.ts | 91 +++++++++++++++++++
.../customer/services/webflow/types.ts | 26 ++++++
packages/shared/src/connectors/enum.ts | 3 +-
packages/shared/src/connectors/index.ts | 2 +-
packages/shared/src/connectors/metadata.ts | 2 +-
10 files changed, 200 insertions(+), 10 deletions(-)
create mode 100644 packages/api/src/ecommerce/customer/services/webflow/index.ts
create mode 100644 packages/api/src/ecommerce/customer/services/webflow/mappers.ts
create mode 100644 packages/api/src/ecommerce/customer/services/webflow/types.ts
diff --git a/packages/api/scripts/init.sql b/packages/api/scripts/init.sql
index 71a8c80ec..d90bf6bbc 100644
--- a/packages/api/scripts/init.sql
+++ b/packages/api/scripts/init.sql
@@ -549,7 +549,8 @@ CREATE TABLE connector_sets
ecom_amazon boolean NULL,
ecom_squarespace boolean NULL,
ats_ashby boolean NULL,
- CONSTRAINT PK_project_connector PRIMARY KEY ( id_connector_set )
+ ecom_webflow boolean NULL,
+CONSTRAINT PK_project_connector PRIMARY KEY ( id_connector_set )
);
diff --git a/packages/api/scripts/seed.sql b/packages/api/scripts/seed.sql
index 233841fa2..124e4b592 100644
--- a/packages/api/scripts/seed.sql
+++ b/packages/api/scripts/seed.sql
@@ -1,10 +1,10 @@
INSERT INTO users (id_user, identification_strategy, email, password_hash, first_name, last_name) VALUES
('0ce39030-2901-4c56-8db0-5e326182ec6b', 'b2c','local@panora.dev', '$2b$10$Y7Q8TWGyGuc5ecdIASbBsuXMo3q/Rs3/cnY.mLZP4tUgfGUOCUBlG', 'local', 'Panora');
-INSERT INTO connector_sets (id_connector_set, crm_hubspot, crm_zoho, crm_pipedrive, crm_attio, crm_zendesk, crm_close, tcg_zendesk, tcg_gorgias, tcg_front, tcg_jira, tcg_gitlab, fs_box, tcg_github, hris_deel, hris_sage, ats_ashby) VALUES
- ('1709da40-17f7-4d3a-93a0-96dc5da6ddd7', TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE),
- ('852dfff8-ab63-4530-ae49-e4b2924407f8', TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE),
- ('aed0f856-f802-4a79-8640-66d441581a99', TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE);
+INSERT INTO connector_sets (id_connector_set, crm_hubspot, crm_zoho, crm_pipedrive, crm_attio, crm_zendesk, crm_close, tcg_zendesk, tcg_gorgias, tcg_front, tcg_jira, tcg_gitlab, fs_box, tcg_github, hris_deel, hris_sage, ats_ashby, ecom_webflow) VALUES
+ ('1709da40-17f7-4d3a-93a0-96dc5da6ddd7', TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE),
+ ('852dfff8-ab63-4530-ae49-e4b2924407f8', TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE),
+ ('aed0f856-f802-4a79-8640-66d441581a99', TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE);
INSERT INTO projects (id_project, name, sync_mode, id_user, id_connector_set) VALUES
('1e468c15-aa57-4448-aa2b-7fed640d1e3d', 'Project 1', 'pull', '0ce39030-2901-4c56-8db0-5e326182ec6b', '1709da40-17f7-4d3a-93a0-96dc5da6ddd7'),
diff --git a/packages/api/src/@core/utils/types/original/original.ecommerce.ts b/packages/api/src/@core/utils/types/original/original.ecommerce.ts
index 95589729e..d7d034a72 100644
--- a/packages/api/src/@core/utils/types/original/original.ecommerce.ts
+++ b/packages/api/src/@core/utils/types/original/original.ecommerce.ts
@@ -1,3 +1,8 @@
+import {
+ WebflowCustomerInput,
+ WebflowCustomerOutput,
+} from '@ecommerce/customer/services/webflow/types';
+
/* INPUT */
import { AmazonCustomerOutput } from '@ecommerce/customer/services/amazon/types';
@@ -70,7 +75,8 @@ export type OriginalFulfillmentOrdersInput = ShopifyFulfillmentOrdersInput;
export type OriginalCustomerInput =
| ShopifyCustomerInput
| WoocommerceCustomerInput
- | SquarespaceCustomerInput;
+ | SquarespaceCustomerInput
+ | WebflowCustomerInput;
/* fulfillment */
export type OriginalFulfillmentInput = ShopifyFulfillmentInput;
@@ -105,7 +111,8 @@ export type OriginalCustomerOutput =
| ShopifyCustomerOutput
| WoocommerceCustomerOutput
| SquarespaceCustomerOutput
- | AmazonCustomerOutput;
+ | AmazonCustomerOutput
+ | WebflowCustomerOutput;
/* fulfillment */
export type OriginalFulfillmentOutput = ShopifyFulfillmentOutput;
diff --git a/packages/api/src/ecommerce/customer/customer.module.ts b/packages/api/src/ecommerce/customer/customer.module.ts
index a09f9f380..00b95c5f9 100644
--- a/packages/api/src/ecommerce/customer/customer.module.ts
+++ b/packages/api/src/ecommerce/customer/customer.module.ts
@@ -1,3 +1,5 @@
+import { WebflowCustomerMapper } from './services/webflow/mappers';
+import { WebflowService } from './services/webflow';
import { CoreUnification } from '@@core/@core-services/unification/core-unification.service';
import { IngestDataService } from '@@core/@core-services/unification/ingest-data.service';
import { WebhookService } from '@@core/@core-services/webhooks/panora-webhooks/webhook.service';
@@ -30,6 +32,8 @@ import { AmazonCustomerMapper } from './services/amazon/mappers';
/* PROVIDERS SERVICES */
ShopifyService,
WoocommerceService,
+ WebflowService,
+ WebflowCustomerMapper,
],
exports: [SyncService],
})
diff --git a/packages/api/src/ecommerce/customer/services/webflow/index.ts b/packages/api/src/ecommerce/customer/services/webflow/index.ts
new file mode 100644
index 000000000..1256429a8
--- /dev/null
+++ b/packages/api/src/ecommerce/customer/services/webflow/index.ts
@@ -0,0 +1,60 @@
+import { EncryptionService } from '@@core/@core-services/encryption/encryption.service';
+import { LoggerService } from '@@core/@core-services/logger/logger.service';
+import { PrismaService } from '@@core/@core-services/prisma/prisma.service';
+import { ApiResponse } from '@@core/utils/types';
+import { SyncParam } from '@@core/utils/types/interface';
+import { ICustomerService } from '@ecommerce/customer/types';
+import { Injectable } from '@nestjs/common';
+import { EcommerceObject } from '@panora/shared';
+import axios from 'axios';
+import { ServiceRegistry } from '../registry.service';
+import { WebflowCustomerOutput } from './types';
+
+@Injectable()
+export class WebflowService implements ICustomerService {
+ constructor(
+ private prisma: PrismaService,
+ private logger: LoggerService,
+ private cryptoService: EncryptionService,
+ private registry: ServiceRegistry,
+ ) {
+ this.logger.setContext(
+ EcommerceObject.customer.toUpperCase() + ':' + WebflowService.name,
+ );
+ this.registry.registerService('webflow', this);
+ }
+
+ async sync(data: SyncParam): Promise> {
+ try {
+ const { linkedUserId } = data;
+
+ const connection = await this.prisma.connections.findFirst({
+ where: {
+ id_linked_user: linkedUserId,
+ provider_slug: 'webflow',
+ vertical: 'ecommerce',
+ },
+ });
+
+ const resp = await axios.get(`${connection.account_url}/users`, {
+ headers: {
+ 'Content-Type': 'application/json',
+ authorization: `Bearer ${this.cryptoService.decrypt(
+ connection.access_token,
+ )}`,
+ },
+ });
+ const customers: WebflowCustomerOutput[] = resp.data.users;
+
+ this.logger.log(`Synced webflow customers !`);
+
+ return {
+ data: customers,
+ message: 'Webflow customers retrieved',
+ statusCode: 200,
+ };
+ } catch (error) {
+ throw error;
+ }
+ }
+}
diff --git a/packages/api/src/ecommerce/customer/services/webflow/mappers.ts b/packages/api/src/ecommerce/customer/services/webflow/mappers.ts
new file mode 100644
index 000000000..7aea5717d
--- /dev/null
+++ b/packages/api/src/ecommerce/customer/services/webflow/mappers.ts
@@ -0,0 +1,91 @@
+import { WebflowCustomerInput, WebflowCustomerOutput } from './types';
+import {
+ UnifiedEcommerceCustomerInput,
+ UnifiedEcommerceCustomerOutput,
+} from '@ecommerce/customer/types/model.unified';
+import { ICustomerMapper } from '@ecommerce/customer/types';
+import { MappersRegistry } from '@@core/@core-services/registries/mappers.registry';
+import { Injectable } from '@nestjs/common';
+import { CoreUnification } from '@@core/@core-services/unification/core-unification.service';
+import { Utils } from '@ecommerce/@lib/@utils';
+
+@Injectable()
+export class WebflowCustomerMapper implements ICustomerMapper {
+ constructor(
+ private mappersRegistry: MappersRegistry,
+ private utils: Utils,
+ private coreUnificationService: CoreUnification,
+ ) {
+ this.mappersRegistry.registerService(
+ 'ecommerce',
+ 'customer',
+ 'webflow',
+ this,
+ );
+ }
+
+ async desunify(
+ source: UnifiedEcommerceCustomerInput,
+ customFieldMappings?: {
+ slug: string;
+ remote_id: string;
+ }[],
+ ): Promise {
+ return;
+ }
+
+ async unify(
+ source: WebflowCustomerOutput | WebflowCustomerOutput[],
+ connectionId: string,
+ customFieldMappings?: {
+ slug: string;
+ remote_id: string;
+ }[],
+ ): Promise<
+ UnifiedEcommerceCustomerOutput | UnifiedEcommerceCustomerOutput[]
+ > {
+ if (!Array.isArray(source)) {
+ return await this.mapSingleCustomerToUnified(
+ source,
+ connectionId,
+ customFieldMappings,
+ );
+ }
+ // Handling array of WebflowCustomerOutput
+ return Promise.all(
+ source.map((customer) =>
+ this.mapSingleCustomerToUnified(
+ customer,
+ connectionId,
+ customFieldMappings,
+ ),
+ ),
+ );
+ }
+
+ private async mapSingleCustomerToUnified(
+ customer: WebflowCustomerOutput,
+ connectionId: string,
+ customFieldMappings?: {
+ slug: string;
+ remote_id: string;
+ }[],
+ ): Promise {
+ const result = {
+ remote_id: customer.id,
+ remote_data: customer,
+ email: customer.data.email,
+ first_name: customer.data.name,
+ last_name: null,
+ phone_number: null,
+ addresses: [],
+ field_mappings:
+ customFieldMappings?.reduce((acc, mapping) => {
+ acc[mapping.slug] = customer[mapping.remote_id];
+ return acc;
+ }, {} as Record) || {},
+ };
+
+ return result;
+ }
+}
diff --git a/packages/api/src/ecommerce/customer/services/webflow/types.ts b/packages/api/src/ecommerce/customer/services/webflow/types.ts
new file mode 100644
index 000000000..a55c2da4f
--- /dev/null
+++ b/packages/api/src/ecommerce/customer/services/webflow/types.ts
@@ -0,0 +1,26 @@
+export interface WebflowCustomerInput {
+ id: string;
+ isEmailVerified: boolean;
+ lastUpdated: string;
+ invitedOn: string;
+ createdOn: string;
+ lastLogin: string;
+ status: string;
+ accessGroups: AccessGroup[];
+ data: UserData;
+}
+
+type AccessGroup = {
+ slug: string;
+ type: string;
+};
+
+type UserData = {
+ name: string;
+ email: string;
+ 'accept-privacy': boolean;
+ 'accept-communications': boolean;
+ [key: string]: any;
+};
+
+export type WebflowCustomerOutput = Partial;
diff --git a/packages/shared/src/connectors/enum.ts b/packages/shared/src/connectors/enum.ts
index a66547391..6cea8afa5 100644
--- a/packages/shared/src/connectors/enum.ts
+++ b/packages/shared/src/connectors/enum.ts
@@ -11,7 +11,8 @@ export enum EcommerceConnectors {
SHOPIFY = 'shopify',
WOOCOMMERCE = 'woocommerce',
SQUARESPACE = 'squarespace',
- AMAZON = 'amazon'
+ AMAZON = 'amazon',
+ WEBFLOW = 'webflow'
}
export enum TicketingConnectors {
diff --git a/packages/shared/src/connectors/index.ts b/packages/shared/src/connectors/index.ts
index 105ca557a..27c8b40ec 100644
--- a/packages/shared/src/connectors/index.ts
+++ b/packages/shared/src/connectors/index.ts
@@ -5,4 +5,4 @@ export const ACCOUNTING_PROVIDERS = [];
export const TICKETING_PROVIDERS = ['zendesk', 'front', 'jira', 'gitlab', 'github'];
export const MARKETINGAUTOMATION_PROVIDERS = [];
export const FILESTORAGE_PROVIDERS = ['box'];
-export const ECOMMERCE_PROVIDERS = ['shopify', 'woocommerce', 'squarespace', 'amazon'];
+export const ECOMMERCE_PROVIDERS = ['shopify', 'woocommerce', 'squarespace', 'amazon', 'webflow'];
diff --git a/packages/shared/src/connectors/metadata.ts b/packages/shared/src/connectors/metadata.ts
index b5baeafac..3949a4f6c 100644
--- a/packages/shared/src/connectors/metadata.ts
+++ b/packages/shared/src/connectors/metadata.ts
@@ -2920,7 +2920,7 @@ export const CONNECTORS_METADATA: ProvidersConfig = {
},
logoPath: 'https://dailybrand.co.zw/wp-content/uploads/2023/10/webflow-2.png',
description: 'Sync & Create orders, fulfillments, fulfillment orders, customers and products',
- active: false,
+ active: true,
authStrategy: {
strategy: AuthStrategy.oauth2
},
From f880b1a1db08aa315c86948becbca36c852f972c Mon Sep 17 00:00:00 2001
From: nael
Date: Sat, 31 Aug 2024 06:38:19 +0200
Subject: [PATCH 27/49] :sparkles: Added posthog telemetry on backend
---
packages/api/package.json | 5 ++--
.../environment/environment.service.ts | 12 +++++++++
packages/api/src/@core/auth/auth.service.ts | 25 +++++++++++++++--
pnpm-lock.yaml | 27 +++++++++++++++++++
4 files changed, 65 insertions(+), 4 deletions(-)
diff --git a/packages/api/package.json b/packages/api/package.json
index f9952ae87..23a5c15b2 100644
--- a/packages/api/package.json
+++ b/packages/api/package.json
@@ -67,6 +67,7 @@
"passport-jwt": "^4.0.1",
"passport-local": "^1.0.0",
"pino-pretty": "^10.2.3",
+ "posthog-node": "^4.2.0",
"qs": "^6.12.3",
"reflect-metadata": "^0.1.13",
"rxjs": "^7.8.1",
@@ -75,6 +76,7 @@
"yargs": "^17.7.2"
},
"devDependencies": {
+ "@nestjs-modules/mailer": "^2.0.2",
"@nestjs/cli": "^10.0.0",
"@nestjs/schematics": "^10.0.0",
"@nestjs/testing": "^10.0.0",
@@ -99,8 +101,7 @@
"ts-loader": "^9.4.3",
"ts-node": "^10.9.1",
"tsconfig-paths": "^4.2.0",
- "typescript": "^5.1.3",
- "@nestjs-modules/mailer": "^2.0.2"
+ "typescript": "^5.1.3"
},
"jest": {
"moduleFileExtensions": [
diff --git a/packages/api/src/@core/@core-services/environment/environment.service.ts b/packages/api/src/@core/@core-services/environment/environment.service.ts
index 8982198ce..c8f25f3c0 100644
--- a/packages/api/src/@core/@core-services/environment/environment.service.ts
+++ b/packages/api/src/@core/@core-services/environment/environment.service.ts
@@ -46,6 +46,18 @@ export class EnvironmentService {
return this.configService.get('ENCRYPT_CRYPTO_SECRET_KEY');
}
+ getPosthogHost(): string {
+ return this.configService.get('POSTHOG_HOST');
+ }
+
+ getPosthogKey(): string {
+ return this.configService.get('POSTHOG_KEY');
+ }
+
+ getPhTelemetry(): string {
+ return this.configService.get('PH_TELEMETRY');
+ }
+
getThrottleConfig(): RateLimit {
return {
ttl: this.configService.get('THROTTLER_TTL'),
diff --git a/packages/api/src/@core/auth/auth.service.ts b/packages/api/src/@core/auth/auth.service.ts
index 73baee65d..7be4651ea 100644
--- a/packages/api/src/@core/auth/auth.service.ts
+++ b/packages/api/src/@core/auth/auth.service.ts
@@ -14,17 +14,27 @@ import { ConflictException } from '@nestjs/common';
import { ResetPasswordDto } from './dto/reset-password.dto';
import { RequestPasswordResetDto } from './dto/request-password-reset.dto';
import * as nodemailer from 'nodemailer';
+import { PostHog } from 'posthog-node'
+import { EnvironmentService } from '@@core/@core-services/environment/environment.service';
@Injectable()
export class AuthService {
+ private postHogClient: PostHog;
+
constructor(
private prisma: PrismaService,
private projectService: ProjectsService,
+ private env: EnvironmentService,
private jwtService: JwtService,
private logger: LoggerService,
) {
this.logger.setContext(AuthService.name);
+ this.postHogClient = new PostHog(
+ this.env.getPosthogKey(),
+ { host: this.env.getPosthogHost() }
+ );
}
+
async resetPassword(resetPasswordDto: ResetPasswordDto) {
const { email, new_password, reset_token } = resetPasswordDto;
@@ -179,10 +189,10 @@ export class AuthService {
async createUser(user: CreateUserDto, id_user?: string) {
try {
const hashedPassword = await bcrypt.hash(user.password_hash, 10);
+ const uuid_user = id_user || uuidv4();
const user_ = await this.prisma.users.create({
data: {
- // ...user,
- id_user: id_user || uuidv4(),
+ id_user: uuid_user,
password_hash: hashedPassword,
identification_strategy: 'b2c',
first_name: user.first_name,
@@ -195,6 +205,17 @@ export class AuthService {
name: 'My Project',
id_user: user_.id_user,
});
+ // send posthog event
+ if(this.env.getPhTelemetry() == "TRUE"){
+ this.postHogClient.capture({
+ distinctId: uuid_user,
+ event: 'user signed up',
+ properties: {
+ login_type: 'email',
+ email: user.email,
+ },
+ })
+ }
return user_;
} catch (error) {
throw error;
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 630e6c431..bc6da2246 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -553,6 +553,9 @@ importers:
pino-pretty:
specifier: ^10.2.3
version: 10.3.1
+ posthog-node:
+ specifier: ^4.2.0
+ version: 4.2.0
qs:
specifier: ^6.12.3
version: 6.12.3
@@ -7179,6 +7182,16 @@ packages:
- debug
dev: false
+ /axios@1.7.6:
+ resolution: {integrity: sha512-Ekur6XDwhnJ5RgOCaxFnXyqlPALI3rVeukZMwOdfghW7/wGz784BYKiQq+QD8NPcr91KRo30KfHOchyijwWw7g==}
+ dependencies:
+ follow-redirects: 1.15.6
+ form-data: 4.0.0
+ proxy-from-env: 1.1.0
+ transitivePeerDependencies:
+ - debug
+ dev: false
+
/axobject-query@3.2.1:
resolution: {integrity: sha512-jsyHu61e6N4Vbz/v18DHwWYKK0bSWLqn47eeDSKPB7m8tqMHF9YJ+mhIk2lVteyZrY8tnSj/jHOv4YiTCuCJgg==}
dependencies:
@@ -13893,6 +13906,16 @@ packages:
preact: 10.20.2
dev: false
+ /posthog-node@4.2.0:
+ resolution: {integrity: sha512-hgyCYMyzMvuF3qWMw6JvS8gT55v7Mtp5wKWcnDrw+nu39D0Tk9BXD7I0LOBp0lGlHEPaXCEVYUtviNKrhMALGA==}
+ engines: {node: '>=15.0.0'}
+ dependencies:
+ axios: 1.7.6
+ rusha: 0.8.14
+ transitivePeerDependencies:
+ - debug
+ dev: false
+
/preact@10.20.2:
resolution: {integrity: sha512-S1d1ernz3KQ+Y2awUxKakpfOg2CEmJmwOP+6igPx6dgr6pgDvenqYviyokWso2rhHvGtTlWWnJDa7RaPbQerTg==}
dev: false
@@ -15301,6 +15324,10 @@ packages:
dependencies:
queue-microtask: 1.2.3
+ /rusha@0.8.14:
+ resolution: {integrity: sha512-cLgakCUf6PedEu15t8kbsjnwIFFR2D4RfL+W3iWFJ4iac7z4B0ZI8fxy4R3J956kAI68HclCFGL8MPoUVC3qVA==}
+ dev: false
+
/rxjs@7.8.1:
resolution: {integrity: sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==}
dependencies:
From 7811bc65d6c80a92c263ff120964d29afca794d7 Mon Sep 17 00:00:00 2001
From: nael
Date: Sat, 31 Aug 2024 07:52:47 +0200
Subject: [PATCH 28/49] :memo: Updated readme
---
README.md | 136 ++++++++++++++++---
docs/integrations/ecommerce/amazon/index.mdx | 2 +-
docs/integrations/hris/gusto/index.mdx | 2 +-
3 files changed, 120 insertions(+), 20 deletions(-)
diff --git a/README.md b/README.md
index 7f793964e..66a80afcc 100644
--- a/README.md
+++ b/README.md
@@ -19,7 +19,6 @@
-
# 🕹️ Try
- Prerequisite: You should have Git and Docker installed
@@ -46,7 +45,6 @@ Panora is now running! Follow our [Quickstart Guide](https://docs.panora.dev/qu
See also [our selfhost guide here !](https://docs.panora.dev/open-source/selfhost/self-host-guide)
-
# ✨ Core Features
| |
@@ -64,13 +62,14 @@ Panora supports integration with the following objects across multiple platforms
### CRM Unified API
-| | Contacts | Deals | Notes | Engagements | Tasks | Users | Companies |
-|-----------------------------------------------|:--------:|:-----:|:-----:|:-----------:|:-----:|:-----:|:---------:|
-| Hubspot | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | |
-| Pipedrive | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | |
-| Zoho CRM | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | |
-| Zendesk Sell | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | |
-| Attio | ✔️ | | | | | | ✔️ |
+| | Contacts | Deals | Notes | Engagements | Tasks | Users | Companies | Stage |
+|-----------------------------------------------|:--------:|:-----:|:-----:|:-----------:|:-----:|:-----:|:---------:|:---------:|
+| Hubspot | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | | ✔️ |
+| Pipedrive | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | |✔️ |
+| Zoho CRM | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | | |
+| Zendesk Sell | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | | ✔️|
+| Attio | ✔️ | ✔️ | ✔️ | | ✔️ | ✔️ | ✔️ | ✔️ |
+| Close | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ |✔️ |
### Ticketing Unified API
@@ -80,27 +79,128 @@ Panora supports integration with the following objects across multiple platforms
| Front | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | |
| Jira | ✔ | ✔ | ✔ | | | ✔ | ✔ | ✔ |
| Gitlab | ✔ | ✔ | ✔ | | | | | ✔|
-
+| Github | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔| |
+
### ATS Unified API (New!)
-| | Activities | Applications | Candidates | Departments | Interviews | Jobs | Offers | Offices | Scorecard | Users |
-|-------------|:----------:|:------------:|:----------:|:-----------:|:----------:|:----:|:------:|:-------:|:---------:|:-----:|
-| Ashby | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ |
+| | Activities | Applications | Candidates | Departments | Interviews | Jobs | Offers | Offices | Scorecard | Users | Eeocs | Job Interview Stage | Tags | Reject Reasons |
+|-------------|:----------:|:------------:|:----------:|:-----------:|:----------:|:----:|:------:|:-------:|:---------:|:-----:|:-------:|:-------:|:-------:|:-------:|
+| Ashby | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | | ✔ | | ✔| ✔| |
+
+### HRIS Unified API (New!)
+| | Bankinfos | Benefits | Companies | Dependents | Employee | Employee Payroll Runs | Employer Benefits | Employments | Groups | Locations | Paygroups | Payrollrun | Timeoff | Timeoff Balances | Timesheet Entries |
+|-------------|:----------:|:------------:|:----------:|:-----------:|:----------:|:----:|:------:|:-------:|:---------:|:-----:|:-----:|:-----:|:-----:|:-----:| :-----:|
+| Gusto | | ✔ | ✔ | | ✔ | | ✔ | ✔ | ✔ | ✔ | | | | | |
### File Storage Unified API
-| File Storage | Drives | Files | Folders | Groups | Users | Permissions | Shared Links |
+| | Drives | Files | Folders | Groups | Users | Permissions | Shared Links |
|-----------------------------------------------|:--------:|:-----:|:-----:|:-----------:|:-----:|:-----:|:---------:|
-| [Google Drive]() | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | | |
-| [Box]() | | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | |
-| [Dropbox]() | | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | |
-| [OneDrive]() | ✔️ | ✔️ | ✔️| ✔️ | ✔️ | | |
+| Google Drive | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | | |
+| Box | | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | |
+| Dropbox | | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | |
+| OneDrive | ✔️ | ✔️ | ✔️| ✔️ | ✔️ | | |
+### Ecommerce Unified API
+| | Customers | Orders | Fulfillments | Fulfillment Orders | Products |
+|-----------------------------------------------|:--------:|:-----:|:-----:|:-----------:|:-----:|
+| Amazon | ✔️ | ✔️ | | | |
+| Shopify | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ |
+| Squarespace | ✔️ | ✔️ | | | ✔️ |
+| Woocommerce | ✔️ | ✔️ | | | ✔️ |
Your favourite software is missing? [Ask the community to build a connector!](https://github.com/panoratech/Panora/issues/new)
+# 🚢 Roadmap
+
+## 🧠 Retrieval Engine for RAG
+
+- [ ] Access and manage data from any source, including documents, chunk & vectors
+- [ ] Semantic, keyword and hybrid search against a vector database
+
+## 🪄 Integrations Coming Soon
+
+#### CRM
+
+- [x] Microsoft Dynamics 365
+- [x] Linear
+- [x] Redtail CRM
+- [x] Wealthbox
+- [x] Leadsquared
+- [ ] Salesforce
+- [ ] Affinity CRM
+- [ ] Odoo
+- [ ] Intelliflow
+- [ ] Xplan
+- [ ] Plannr
+- [ ] ACT!
+- [ ] Jungo
+- [ ] Surefire
+- [ ] Velocity
+
+#### Ticketing
+
+- [ ] Service Now
+- [ ] Wrike
+- [ ] Dixa
+- [ ] Service Now
+- [ ] Asana
+- [ ] Aha
+- [ ] Clickup
+
+#### Accounting
+
+- [ ] Wave Financial
+- [ ] Xero
+- [ ] Quickbooks
+
+#### File Storage
+
+- [ ] Google Drive
+- [ ] Dropbox
+- [ ] Sharepoint
+
+#### Productivity
+
+- [ ] Slack
+- [ ] Notion
+
+#### HRIS
+
+- [ ] Workday
+- [ ] ADP Workforce
+- [x] Sage
+- [x] Deel
+- [ ] BambooHR
+- [ ] Rippling
+
+#### Ecommerce
+
+- [ ] Ebay
+- [ ] Faire
+- [ ] Webflow
+- [ ] Mercado Libre
+- [ ] Prestashop
+- [ ] Magento
+- [ ] BigCommerce
+
+#### ATS
+
+- [ ] Greenhouse
+- [ ] Lever
+- [ ] Avature
+
+#### Legacy Softwares
+
+- [ ] Netsuite
+- [ ] SAP (ERP)
+- [ ] Ariba
+- [ ] Concur
+- [ ] Magaya (TMS)
+- [ ] Cargowise (TMS)
+
# 👾 Join the community
- [Join the Discord](https://discord.com/invite/PH5k7gGubt)
diff --git a/docs/integrations/ecommerce/amazon/index.mdx b/docs/integrations/ecommerce/amazon/index.mdx
index c4cbdfb6b..8c0d728d4 100644
--- a/docs/integrations/ecommerce/amazon/index.mdx
+++ b/docs/integrations/ecommerce/amazon/index.mdx
@@ -2,7 +2,7 @@
title: "Amazon"
description: ""
---
-
+
# Common Objects
diff --git a/docs/integrations/hris/gusto/index.mdx b/docs/integrations/hris/gusto/index.mdx
index aecd42b50..9cc3e37ac 100644
--- a/docs/integrations/hris/gusto/index.mdx
+++ b/docs/integrations/hris/gusto/index.mdx
@@ -4,7 +4,7 @@ description: ""
---
# Common Objects
-
+
| Unified Model | Supported | Provider Endpoints |
| ---------------- | --------- | ------------------ |
| Bankinfo | No 🚫 | |
From 64e53547b7a004b229ef3ecceece4a761601fc29 Mon Sep 17 00:00:00 2001
From: nael
Date: Sat, 31 Aug 2024 07:57:01 +0200
Subject: [PATCH 29/49] :memo: Updated readme
---
README.md | 14 +++++++++++++-
1 file changed, 13 insertions(+), 1 deletion(-)
diff --git a/README.md b/README.md
index 66a80afcc..a96df5438 100644
--- a/README.md
+++ b/README.md
@@ -161,6 +161,7 @@ Your favourite software is missing? [Ask the community to build a connector!](ht
- [ ] Google Drive
- [ ] Dropbox
- [ ] Sharepoint
+- [ ] One Drive
#### Productivity
@@ -192,9 +193,20 @@ Your favourite software is missing? [Ask the community to build a connector!](ht
- [ ] Lever
- [ ] Avature
+#### Cybersecurity
+
+- [ ] Snyk
+- [ ] Qualys
+- [ ] Crowdstrike
+- [ ] Semgrep
+- [ ] Rapids7InsightVm
+- [ ] Tenable
+- [ ] SentinelOne
+- [ ] Microsoft Defender
+
#### Legacy Softwares
-- [ ] Netsuite
+- [ ] Netsuite (Accounting)
- [ ] SAP (ERP)
- [ ] Ariba
- [ ] Concur
From 000e22ef28a84bd16829e0aef353d986b9ad7f20 Mon Sep 17 00:00:00 2001
From: nael
Date: Sat, 31 Aug 2024 09:48:55 +0200
Subject: [PATCH 30/49] :bug: Added dockerfile env vars
---
apps/webapp/Dockerfile | 2 ++
docker-compose.source.yml | 43 ++++++++++++++++++++-------------------
docker-compose.yml | 14 ++++++++-----
3 files changed, 33 insertions(+), 26 deletions(-)
diff --git a/apps/webapp/Dockerfile b/apps/webapp/Dockerfile
index 8a3ba64e4..38519ee0c 100644
--- a/apps/webapp/Dockerfile
+++ b/apps/webapp/Dockerfile
@@ -34,12 +34,14 @@ ARG NEXT_PUBLIC_DISTRIBUTION
ARG NEXT_PUBLIC_BACKEND_DOMAIN
ARG NEXT_PUBLIC_MAGIC_LINK_DOMAIN
ARG NEXT_PUBLIC_WEBAPP_DOMAIN
+ARG NEXT_PUBLIC_REDIRECT_WEBHOOK_INGRESS
ENV NEXT_PUBLIC_DISTRIBUTION="$NEXT_PUBLIC_DISTRIBUTION"
ENV NEXT_PUBLIC_BACKEND_DOMAIN="${NEXT_PUBLIC_BACKEND_DOMAIN}"
ENV NEXT_PUBLIC_MAGIC_LINK_DOMAIN="${NEXT_PUBLIC_MAGIC_LINK_DOMAIN}"
ENV NEXT_PUBLIC_WEBAPP_DOMAIN="${NEXT_PUBLIC_WEBAPP_DOMAIN}"
+ENV NEXT_PUBLIC_REDIRECT_WEBHOOK_INGRESS="${NEXT_PUBLIC_REDIRECT_WEBHOOK_INGRESS}"
RUN corepack enable
diff --git a/docker-compose.source.yml b/docker-compose.source.yml
index d81637773..4ddc42544 100644
--- a/docker-compose.source.yml
+++ b/docker-compose.source.yml
@@ -188,7 +188,10 @@ services:
SNYK_CYBERSECURITY_CLOUD_CLIENT_SECRET: ${SNYK_CYBERSECURITY_CLOUD_CLIENT_SECRET}
CROWDSTRIKE_CYBERSECURITY_CLOUD_CLIENT_ID: ${CROWDSTRIKE_CYBERSECURITY_CLOUD_CLIENT_ID}
CROWDSTRIKE_CYBERSECURITY_CLOUD_CLIENT_SECRET: ${CROWDSTRIKE_CYBERSECURITY_CLOUD_CLIENT_SECRET}
-
+ POSTHOG_HOST: "https://us.i.posthog.com"
+ POSTHOG_KEY: "phc_WhWJfNPOHAuWVdyTacGxrPa9JW54scnofA9KVEjFcFw"
+ PH_TELEMETRY: "TRUE"
+
restart: unless-stopped
ports:
- 3000:3000
@@ -199,12 +202,12 @@ services:
condition: service_healthy
networks:
- backend
- healthcheck:
- test: ["CMD-SHELL", "curl", "-f", "http://localhost:3000/health"]
- start_period: 60s
- interval: 10s
- timeout: 1s
- retries: 50
+ #healthcheck:
+ #test: ["CMD-SHELL", "curl", "-f", "http://localhost:3000/health"]
+ #start_period: 60s
+ #interval: 10s
+ #timeout: 1s
+ #retries: 50
redis:
image: valkey/valkey:7.2-alpine
@@ -230,15 +233,15 @@ services:
args:
NEXT_PUBLIC_DISTRIBUTION: ${DISTRIBUTION}
NEXT_PUBLIC_BACKEND_DOMAIN: ${NEXT_PUBLIC_BACKEND_DOMAIN}
- NEXT_PUBLIC_FRONTEND_DOMAIN: ${NEXT_PUBLIC_FRONTEND_DOMAIN}
+ NEXT_PUBLIC_MAGIC_LINK_DOMAIN: ${NEXT_PUBLIC_MAGIC_LINK_DOMAIN}
NEXT_PUBLIC_WEBAPP_DOMAIN: ${NEXT_PUBLIC_WEBAPP_DOMAIN}
- NEXT_PUBLIC_REDIRECT_WEBHOOK_INGRESS: ${REDIRECT_TUNNEL_INGRESS}
+ NEXT_PUBLIC_REDIRECT_WEBHOOK_INGRESS: ${REDIRECT_TUNNEL_INGRESS}
restart: unless-stopped
ports:
- 80:8090
- depends_on:
- api:
- condition: service_healthy
+ #depends_on:
+ #api:
+ #condition: service_healthy
networks:
- backend
- frontend
@@ -247,14 +250,12 @@ services:
build:
dockerfile: ./apps/magic-link/Dockerfile
context: ./
- args:
- VITE_BACKEND_DOMAIN: ${NEXT_PUBLIC_MAGIC_LINK_DOMAIN}
- restart: always
+ restart: always
ports:
- 81:80
- depends_on:
- api:
- condition: service_healthy
+ #depends_on:
+ #api:
+ #condition: service_healthy
networks:
- backend
- frontend
@@ -271,9 +272,9 @@ services:
- ./ngrok.yml:/etc/ngrok.yml
ports:
- 4040:4040
- depends_on:
- api:
- condition: service_healthy
+ #depends_on:
+ #api:
+ #condition: service_healthy
network_mode: "host"
networks:
diff --git a/docker-compose.yml b/docker-compose.yml
index c8603707e..d5db1b698 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -30,7 +30,7 @@ services:
DATABASE_URL: postgresql://${POSTGRES_USER}:${POSTGRES_PASSWORD}@${POSTGRES_HOST}:5432/${POSTGRES_DB}?ssl=false
DISTRIBUTION: ${DISTRIBUTION}
WEBHOOK_INGRESS: ${WEBHOOK_INGRESS}
- REDIRECT_TUNNEL_INGRESS: ${REDIRECT_TUNNEL_INGRESS}
+ REDIRECT_TUNNEL_INGRESS: "https://panora-contributors-redirect.rachid-7e5.workers.dev/http://localhost:3000"
JWT_SECRET: ${JWT_SECRET}
SENTRY_ENABLED: ${SENTRY_ENABLED}
SENTRY_DSN: ${SENTRY_DSN}
@@ -41,8 +41,8 @@ services:
REDIS_DB: ${REDIS_DB}
WEBAPP_URL: ${NEXT_PUBLIC_WEBAPP_DOMAIN}
ENCRYPT_CRYPTO_SECRET_KEY: ${ENCRYPT_CRYPTO_SECRET_KEY}
- HUBSPOT_CRM_CLOUD_CLIENT_ID: ${HUBSPOT_CRM_CLOUD_CLIENT_ID}
- HUBSPOT_CRM_CLOUD_CLIENT_SECRET: ${HUBSPOT_CRM_CLOUD_CLIENT_SECRET}
+ HUBSPOT_CRM_CLOUD_CLIENT_ID: "ca8ef3b9-201d-4472-84c3-1246f83d0b03"
+ HUBSPOT_CRM_CLOUD_CLIENT_SECRET: "16b75410-8884-4c4a-a6b7-ca50b61eb289"
ATTIO_CRM_CLOUD_CLIENT_ID: ${ATTIO_CRM_CLOUD_CLIENT_ID}
ATTIO_CRM_CLOUD_CLIENT_SECRET: ${ATTIO_CRM_CLOUD_CLIENT_SECRET}
ZOHO_CRM_CLOUD_CLIENT_ID: ${ZOHO_CRM_CLOUD_CLIENT_ID}
@@ -182,7 +182,9 @@ services:
SNYK_CYBERSECURITY_CLOUD_CLIENT_SECRET: ${SNYK_CYBERSECURITY_CLOUD_CLIENT_SECRET}
CROWDSTRIKE_CYBERSECURITY_CLOUD_CLIENT_ID: ${CROWDSTRIKE_CYBERSECURITY_CLOUD_CLIENT_ID}
CROWDSTRIKE_CYBERSECURITY_CLOUD_CLIENT_SECRET: ${CROWDSTRIKE_CYBERSECURITY_CLOUD_CLIENT_SECRET}
-
+ POSTHOG_HOST: "https://us.i.posthog.com"
+ POSTHOG_KEY: "phc_WhWJfNPOHAuWVdyTacGxrPa9JW54scnofA9KVEjFcFw"
+ PH_TELEMETRY: "TRUE"
restart: unless-stopped
ports:
- 3000:3000
@@ -231,10 +233,12 @@ services:
webapp-next:
image: panora.docker.scarf.sh/panoradotdev/frontend-webapp:selfhosted
environment:
- NEXT_PUBLIC_DISTRIBUTION: ${DISTRIBUTION}
+ NEXT_PUBLIC_DISTRIBUTION: "selfhost"
NEXT_PUBLIC_BACKEND_DOMAIN: ${NEXT_PUBLIC_BACKEND_DOMAIN}
NEXT_PUBLIC_MAGIC_LINK_DOMAIN: ${NEXT_PUBLIC_MAGIC_LINK_DOMAIN}
NEXT_PUBLIC_WEBAPP_DOMAIN: ${NEXT_PUBLIC_WEBAPP_DOMAIN}
+ NEXT_PUBLIC_REDIRECT_WEBHOOK_INGRESS: "https://panora-contributors-redirect.rachid-7e5.workers.dev/http://localhost:3000"
+
restart: unless-stopped
ports:
- 80:8090
From 59a781aaf364d3fa897006dc2bb066265d040deb Mon Sep 17 00:00:00 2001
From: Rachid Flih
Date: Sat, 31 Aug 2024 01:04:56 -0700
Subject: [PATCH 31/49] =?UTF-8?q?=F0=9F=93=9D=20Update=20to=20docs?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
docs/mint.json | 2 +-
docs/quick-start.mdx | 142 +++++++++++--------------------------------
2 files changed, 37 insertions(+), 107 deletions(-)
diff --git a/docs/mint.json b/docs/mint.json
index 5456ae6ec..9076d1888 100644
--- a/docs/mint.json
+++ b/docs/mint.json
@@ -1,5 +1,6 @@
{
"$schema": "https://mintlify.com/schema.json",
+ "layout": "topnav",
"analytics": {
"hotjar": {
"hjid": "5154921",
@@ -53,7 +54,6 @@
{
"group": "Documentation",
"pages": [
- "welcome",
"quick-start",
"catalog"
]
diff --git a/docs/quick-start.mdx b/docs/quick-start.mdx
index ef6cd12e2..a7074e894 100644
--- a/docs/quick-start.mdx
+++ b/docs/quick-start.mdx
@@ -8,29 +8,19 @@ icon: "star"
Before you begin, make sure you have the following:
-- A cloud [account](https://tally.so/r/w5ZoaN?source=docs_welcome) (or see our guide [here](/open-source/self-host-guide) on getting started with the selfhost version)
-- An API key, see our guide [here](/core-concepts/auth)
-- Node JS v18.17.1 or newer installed on your computer
-
-## **Step 1: Get access to your users data**
-
-You either have the option to use a [**no-code magic link**](/core-concepts/magic-links) or the [**embedded frontend snippet**](/recipes/embed-catalog) to get access to your user's data.
-Choose the one that fits your needs !
-
-[We recommend listening to webhooks to get notified once a user connects and catch the connection token used for requests.
-](/recipes/catch-connection-token)
-
-
-
- Let's send our first magic link so you can ask your customers to grant you access to their tools, without writing code.
-
-
-
+- **Panora Running on your machine** (⏱️ 1 min self-hosting guide [here](/open-source/self_hosting/guide))
+- **An API key** (⏱️ 1 min guide guide [here](/core-concepts/auth#learn-how-to-generate-your-api-keys))
+- **A free Hubspot account** (signup [here](https://app.hubspot.com/signup-hubspot/crm) - use a [disposable email](https://temp-mail.org/en/) if you prefer)
+
+## **Step 1: Getting access to your users data**
+
+There are two ways for a user to grant you access to their data:
+- [**No-code: Magic Links**](/core-concepts/magic-links)
+- [**Natively embedding into frontend**](/recipes/embed-catalog).
+
+Magic Links help you invite your users to grant you access to their data without a dedicated website.
+Let's now create our first magic link!
+
Login to your [account dashboard](https://dashboard.panora.dev)
@@ -48,86 +38,29 @@ Choose the one that fits your needs !
Click `Generate`
-
-
- Embed Panora into your product with our native component to collect access to use user's data.
-
- You can find the component on NPM
- [here](https://www.npmjs.com/package/@panora/embedded-card-react)
-
-
-
-
- ```shell React
- npm i @panora/embedded-card-react
- ```
-
-
-
-
-
- ```javascript React
- import "@panora/embedded-card-react/dist/index.css";
- import PanoraProviderCard from "@panora/embedded-card-react";
- import PanoraDynamicCatalog from "@panora/embedded-card-react";
- ```
-
-
-
-
- You can either import a single connector card or a catalog of all connectors that you select in the UI dashboard configuration (see [here](/recipes/embed-catalog) for more details).
- In order to fill the `linkedUserId` prop, use your own remote id that exist in your system **OR** check this [recipe](/recipes/import-existing-users) !
-
- ```javascript Single Connector Card
- import "@panora/embedded-card-react/dist/index.css";
- import { PanoraProviderCard } from "@panora/embedded-card-react";
- import { ConnectorCategory } from '@panora/shared'
-
-
- ```
- ```javascript Whole Connector Catalog
- import "@panora/embedded-card-react/dist/index.css";
- import { PanoraDynamicCatalogCard } from "@panora/embedded-card-react";
- import { ConnectorCategory } from '@panora/shared'
-
-
- ```
-
- You should see a card or catalog being rendered client-side !
-
- __insert photo__
-
-
+Once the user successfully completes the granting auth flow, the connection will have a `status` value of `valid`.
-
-
+## Step 2: Grab the connection token
-Once the user successfully completes the granting auth flow, the connection will have a `status` value of `valid`.
+Connection tokens are the way Panora represents a third party's account, whatever the underlying identification mechanism is.
+There are two ways to get these tokens: catchting them with a webhook, or just finding them in your dashboard. For now, we'll stick to the dashboard,.
-## **Step 2: Send your first unified API requests**
+Let's find the `connection token` in the dashboard.
+
+ADD SCREEN HERE
+
+## **Step 3: Make your first API requests**
+
+Let's Create a contact in our Hubspot acccount, using Panora's API.
+
+This will require you to have:
+- The `connection token` from the previous step
+- An API key (guide [here](/core-concepts/auth#learn-how-to-generate-your-api-keys))
+
+The API key identifies _YOU_ as a user of Panora, while the connection token identifies which user's account you behalf you want to. In the future, you will have one connection token per user account connected on the Panora platform, while keeping one API key.
-### _Create a contact in a CRM_
-
- We assume for this tutorial that you have a valid Panora API Key, and a
- `connection_token`. Find help [here](/core-concepts/auth).
-
-
- You can find the Typescript SDK on NPM
- [here](https://www.npmjs.com/package/@panora/sdk)
-
In this example, we will create a contact in a CRM. Visit other sections of the [documentation](/api-reference/introduction) to find category-specific examples.
```javascript TypeScript
@@ -225,16 +158,13 @@ Let’s break down what’s happening here:
- We pass the connection token catched during step 1 ([More info here](/core-concepts/auth#catch-connection-tokens))
- Finally, we print the response.
-## Next Steps
-
-Congratulations, you’ve successfully sent your first unified API request with Panora! Here are some next steps to continue your journey.
-
-### Listen to events using a webhook
+## Suggested Next Steps
-Visit our [webhooks section](/webhooks/overview).
+Amazing! You’ve successfully sent your first unified API request with Panora! Here are some next steps to continue your learning journey:
-### API resources
+- Setup your first [webhooks](/webhooks/overview)
-Drop into our [API documentation](/api-reference/introduction) for more details on the available endpoints and parameters.
+API resources:
+Check our [API documentation](/api-reference/introduction) for more details on the available endpoints and parameters.
-Check out our [client SDKs](/backend-sdk/typescript) for a set of tools to make it easier for you to build with and integrate Panora into your applications.
\ No newline at end of file
+Check our SDKs: [Typescript](/backend-sdk/typescript) for a set of tools to make it easier for you to build with and integrate Panora into your applications.
\ No newline at end of file
From 74aaf489f1d147272b8fcb982fd0cf3de21c2b3b Mon Sep 17 00:00:00 2001
From: Rachid Flih
Date: Sat, 31 Aug 2024 02:36:16 -0700
Subject: [PATCH 32/49] =?UTF-8?q?=F0=9F=93=9D=20Update=20docs=20quickstart?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
docs/images/connections_screen.png | Bin 0 -> 68117 bytes
docs/quick-start.mdx | 111 +++++++++--------------------
2 files changed, 32 insertions(+), 79 deletions(-)
create mode 100644 docs/images/connections_screen.png
diff --git a/docs/images/connections_screen.png b/docs/images/connections_screen.png
new file mode 100644
index 0000000000000000000000000000000000000000..ce306336b5040c89cff925cc11289beda1708440
GIT binary patch
literal 68117
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