Skip to content

Instantly share code, notes, and snippets.

@Vergil333
Created December 13, 2022 05:28
Show Gist options
  • Save Vergil333/114d8ba65defe0c3b609d095aba94f2c to your computer and use it in GitHub Desktop.
Save Vergil333/114d8ba65defe0c3b609d095aba94f2c to your computer and use it in GitHub Desktop.
/**
* @property accountNumber Text(40)
* @property accountSource Picklist
* @property active__c Picklist
* @property annualRevenue Currency(18, 0)
* @property billingAddress Address
* @property cleanStatus Picklist
* @property createdById Lookup(User)
* @property createdDate Date/Time
* @property customerPriority__c Picklist
* @property dandbCompanyId Lookup(D&B Company)
* @property description Long Text Area(32000)
* @property dunsNumber Text(9)
* @property fax Fax
* @property id Lookup()
* @property industry Picklist
* @property isDeleted Checkbox
* @property jigsaw Text(20)
* @property jigsawCompanyId External Lookup
* @property lastActivityDate Date
* @property lastModifiedById Lookup(User)
* @property lastModifiedDate Date/Time
* @property lastReferencedDate Date/Time
* @property lastViewedDate Date/Time
* @property masterRecordId Lookup(Account)
* @property naicsCode Text(8)
* @property naicsDesc Text(120)
* @property name Name
* @property numberOfEmployees Number(8, 0)
* @property numberofLocations__c Number(3, 0)
* @property operatingHoursId Lookup(Operating Hours)
* @property ownerId Lookup(User)
* @property ownership Picklist
* @property parentId Hierarchy
* @property phone Phone
* @property photoUrl URL(255)
* @property rating Picklist
* @property sLAExpirationDate__c Date
* @property sLASerialNumber__c Text(10)
* @property sLA__c Picklist
* @property shippingAddress Address
* @property sic Text(20)
* @property sicDesc Text(80)
* @property site Text(80)
* @property systemModstamp Date/Time
* @property tickerSymbol Content(20)
* @property tradestyle Text(255)
* @property type Picklist
* @property upsellOpportunity__c Picklist
* @property userRecordAccessId Lookup(User Record Access)
* @property website URL(255)
* @property yearStarted Text(4)
*/
class Account (
@JsonProperty("AccountNumber") val accountNumber: String? = null,
@JsonProperty("AccountSource") val accountSource: String? = null,
@JsonProperty("Active__c") val active__c: String? = null,
@JsonProperty("AnnualRevenue") val annualRevenue: Double? = null,
@JsonProperty("BillingAddress") val billingAddress: Map<String, Any?>? = null,
@JsonProperty("CleanStatus") val cleanStatus: String? = null,
@JsonProperty("CreatedById") val createdById: String,
@JsonProperty("CreatedDate") val createdDate: String,
@JsonProperty("CustomerPriority__c") val customerPriority__c: String? = null,
@JsonProperty("DandbCompanyId") val dandbCompanyId: String? = null,
@JsonProperty("Description") val description: String? = null,
@JsonProperty("DunsNumber") val dunsNumber: String? = null,
@JsonProperty("Fax") val fax: String? = null,
@JsonProperty("Industry") val industry: String? = null,
@JsonProperty("IsDeleted") val isDeleted: Boolean,
@JsonProperty("Jigsaw") val jigsaw: String? = null,
@JsonProperty("JigsawCompanyId") val jigsawCompanyId: String? = null,
@JsonProperty("LastActivityDate") val lastActivityDate: String? = null,
@JsonProperty("LastModifiedById") val lastModifiedById: String,
@JsonProperty("LastModifiedDate") val lastModifiedDate: String,
@JsonProperty("LastReferencedDate") val lastReferencedDate: String? = null,
@JsonProperty("LastViewedDate") val lastViewedDate: String? = null,
@JsonProperty("MasterRecordId") val masterRecordId: String? = null,
@JsonProperty("NaicsCode") val naicsCode: String? = null,
@JsonProperty("NaicsDesc") val naicsDesc: String? = null,
@JsonProperty("Name") val name: String,
@JsonProperty("NumberOfEmployees") val numberOfEmployees: Double? = null,
@JsonProperty("NumberofLocations__c") val numberofLocations__c: Double? = null,
@JsonProperty("OperatingHoursId") val operatingHoursId: String? = null,
@JsonProperty("OwnerId") val ownerId: String,
@JsonProperty("Ownership") val ownership: String? = null,
@JsonProperty("ParentId") val parentId: Map<String, Any?>? = null,
@JsonProperty("Phone") val phone: String? = null,
@JsonProperty("PhotoUrl") val photoUrl: String? = null,
@JsonProperty("Rating") val rating: String? = null,
@JsonProperty("SLAExpirationDate__c") val sLAExpirationDate__c: String? = null,
@JsonProperty("SLASerialNumber__c") val sLASerialNumber__c: String? = null,
@JsonProperty("SLA__c") val sLA__c: String? = null,
@JsonProperty("ShippingAddress") val shippingAddress: Map<String, Any?>? = null,
@JsonProperty("Sic") val sic: String? = null,
@JsonProperty("SicDesc") val sicDesc: String? = null,
@JsonProperty("Site") val site: String? = null,
@JsonProperty("SystemModstamp") val systemModstamp: String,
@JsonProperty("TickerSymbol") val tickerSymbol: String? = null,
@JsonProperty("Tradestyle") val tradestyle: String? = null,
@JsonProperty("Type") val type: String? = null,
@JsonProperty("UpsellOpportunity__c") val upsellOpportunity__c: String? = null,
@JsonProperty("UserRecordAccessId") val userRecordAccessId: String? = null,
@JsonProperty("Website") val website: String? = null,
@JsonProperty("YearStarted") val yearStarted: String? = null,
) : AbstractSObject<SObjectType>(type = SObjectType.ACCOUNT)
/**
* @property accountId Lookup(Account)
* @property assetLevel Number(9, 0)
* @property assetProvidedById Lookup(Account)
* @property assetServicedById Lookup(Account)
* @property contactId Lookup(Contact)
* @property createdById Lookup(User)
* @property createdDate Date/Time
* @property currentAmount Currency(16, 2)
* @property currentLifecycleEndDate Date/Time
* @property currentMrr Currency(16, 2)
* @property currentQuantity Number(12, 2)
* @property description Long Text Area(32000)
* @property hasLifecycleManagement Checkbox
* @property id Lookup()
* @property installDate Date
* @property isCompetitorProduct Checkbox
* @property isDeleted Checkbox
* @property isInternal Checkbox
* @property lastModifiedById Lookup(User)
* @property lastModifiedDate Date/Time
* @property lastReferencedDate Date/Time
* @property lastViewedDate Date/Time
* @property lifecycleEndDate Date/Time
* @property lifecycleStartDate Date/Time
* @property name Text(255)
* @property ownerId Lookup(User)
* @property parentId Lookup(Asset)
* @property price Currency(18, 0)
* @property product2Id Lookup(Product)
* @property productCode Text(255)
* @property purchaseDate Date
* @property quantity Number(10, 2)
* @property rootAssetId Lookup(Asset)
* @property serialNumber Text(80)
* @property status Picklist
* @property stockKeepingUnit Text(180)
* @property systemModstamp Date/Time
* @property totalLifecycleAmount Currency(16, 2)
* @property usageEndDate Date
* @property userRecordAccessId Lookup(User Record Access)
*/
class Asset (
@JsonProperty("AccountId") val accountId: String? = null,
@JsonProperty("AssetLevel") val assetLevel: Double? = null,
@JsonProperty("AssetProvidedById") val assetProvidedById: String? = null,
@JsonProperty("AssetServicedById") val assetServicedById: String? = null,
@JsonProperty("ContactId") val contactId: String? = null,
@JsonProperty("CreatedById") val createdById: String,
@JsonProperty("CreatedDate") val createdDate: String,
@JsonProperty("CurrentAmount") val currentAmount: Double? = null,
@JsonProperty("CurrentLifecycleEndDate") val currentLifecycleEndDate: String? = null,
@JsonProperty("CurrentMrr") val currentMrr: Double? = null,
@JsonProperty("CurrentQuantity") val currentQuantity: Double? = null,
@JsonProperty("Description") val description: String? = null,
@JsonProperty("HasLifecycleManagement") val hasLifecycleManagement: Boolean,
@JsonProperty("InstallDate") val installDate: String? = null,
@JsonProperty("IsCompetitorProduct") val isCompetitorProduct: Boolean,
@JsonProperty("IsDeleted") val isDeleted: Boolean,
@JsonProperty("IsInternal") val isInternal: Boolean,
@JsonProperty("LastModifiedById") val lastModifiedById: String,
@JsonProperty("LastModifiedDate") val lastModifiedDate: String,
@JsonProperty("LastReferencedDate") val lastReferencedDate: String? = null,
@JsonProperty("LastViewedDate") val lastViewedDate: String? = null,
@JsonProperty("LifecycleEndDate") val lifecycleEndDate: String? = null,
@JsonProperty("LifecycleStartDate") val lifecycleStartDate: String? = null,
@JsonProperty("Name") val name: String,
@JsonProperty("OwnerId") val ownerId: String,
@JsonProperty("ParentId") val parentId: String? = null,
@JsonProperty("Price") val price: Double? = null,
@JsonProperty("Product2Id") val product2Id: String? = null,
@JsonProperty("ProductCode") val productCode: String? = null,
@JsonProperty("PurchaseDate") val purchaseDate: String? = null,
@JsonProperty("Quantity") val quantity: Double? = null,
@JsonProperty("RootAssetId") val rootAssetId: String? = null,
@JsonProperty("SerialNumber") val serialNumber: String? = null,
@JsonProperty("Status") val status: String? = null,
@JsonProperty("StockKeepingUnit") val stockKeepingUnit: String? = null,
@JsonProperty("SystemModstamp") val systemModstamp: String,
@JsonProperty("TotalLifecycleAmount") val totalLifecycleAmount: Double? = null,
@JsonProperty("UsageEndDate") val usageEndDate: String? = null,
@JsonProperty("UserRecordAccessId") val userRecordAccessId: String? = null,
) : AbstractSObject<SObjectType>(type = SObjectType.ASSET)
/**
* @property body Text Area
* @property bodyLength Number(8, 0)
* @property contentType Text(120)
* @property createdById Lookup(User)
* @property createdDate Date/Time
* @property description Text Area(500)
* @property id Lookup()
* @property isDeleted Checkbox
* @property isPrivate Checkbox
* @property lastModifiedById Lookup(User)
* @property lastModifiedDate Date/Time
* @property name Text(255)
* @property ownerId Lookup(User,Calendar)
* @property parentId Lookup(Contract,Order,Email Template,Campaign,Account,Contact,Lead,Opportunity,Product,Asset,Case,Solution,Task,Event,Email Message,Invoice,Work Order,Work Order Line Item,Service Appointment,Service Resource,Entitlement,Service Contract,Contract Line Item,Location,Image,Shift,Credit Memo,Communication Subscription,Communication Subscription Channel Type,Communication Subscription Consent,Communication Subscription Timing,Engagement Channel Type,Legal Entity,Work Plan,Work Plan Template,Work Step,Work Step Template,Change Request,Incident,Problem,TestObject)
* @property systemModstamp Date/Time
*/
class Attachment (
@JsonProperty("Body") val body: String,
@JsonProperty("BodyLength") val bodyLength: Double? = null,
@JsonProperty("ContentType") val contentType: String? = null,
@JsonProperty("CreatedById") val createdById: String,
@JsonProperty("CreatedDate") val createdDate: String,
@JsonProperty("Description") val description: String? = null,
@JsonProperty("IsDeleted") val isDeleted: Boolean,
@JsonProperty("IsPrivate") val isPrivate: Boolean,
@JsonProperty("LastModifiedById") val lastModifiedById: String,
@JsonProperty("LastModifiedDate") val lastModifiedDate: String,
@JsonProperty("Name") val name: String,
@JsonProperty("OwnerId") val ownerId: String,
@JsonProperty("ParentId") val parentId: String,
@JsonProperty("SystemModstamp") val systemModstamp: String,
) : AbstractSObject<SObjectType>(type = SObjectType.ATTACHMENT)
/**
* @property createdById Lookup(User)
* @property createdDate Date/Time
* @property id Lookup()
* @property isActive Checkbox
* @property lastModifiedById Lookup(User)
* @property lastModifiedDate Date/Time
* @property name Text(80)
* @property systemModstamp Date/Time
* @property type Picklist
* @property userId Lookup(User)
*/
class Calendar (
@JsonProperty("CreatedById") val createdById: String,
@JsonProperty("CreatedDate") val createdDate: String,
@JsonProperty("IsActive") val isActive: Boolean,
@JsonProperty("LastModifiedById") val lastModifiedById: String,
@JsonProperty("LastModifiedDate") val lastModifiedDate: String,
@JsonProperty("Name") val name: String,
@JsonProperty("SystemModstamp") val systemModstamp: String,
@JsonProperty("Type") val type: String,
@JsonProperty("UserId") val userId: String? = null,
) : AbstractSObject<SObjectType>(type = SObjectType.CALENDAR)
/**
* @property accountId Lookup(Account)
* @property assistantName Text(40)
* @property assistantPhone Phone
* @property birthdate Date
* @property cleanStatus Picklist
* @property createdById Lookup(User)
* @property createdDate Date/Time
* @property department Text(80)
* @property description Long Text Area(32000)
* @property email Email
* @property emailBouncedDate Date/Time
* @property emailBouncedReason Text(255)
* @property fax Fax
* @property homePhone Phone
* @property id Lookup()
* @property individualId Lookup(Individual)
* @property isDeleted Checkbox
* @property isEmailBounced Checkbox
* @property jigsaw Text(20)
* @property jigsawContactId External Lookup
* @property languages__c Text(100)
* @property lastActivityDate Date
* @property lastCURequestDate Date/Time
* @property lastCUUpdateDate Date/Time
* @property lastModifiedById Lookup(User)
* @property lastModifiedDate Date/Time
* @property lastReferencedDate Date/Time
* @property lastViewedDate Date/Time
* @property leadSource Picklist
* @property level__c Picklist
* @property mailingAddress Address
* @property masterRecordId Lookup(Contact)
* @property mobilePhone Phone
* @property name Name
* @property otherAddress Address
* @property otherPhone Phone
* @property ownerId Lookup(User)
* @property phone Phone
* @property photoUrl URL(255)
* @property reportsToId Lookup(Contact)
* @property systemModstamp Date/Time
* @property title Text(128)
* @property userRecordAccessId Lookup(User Record Access)
*/
class Contact (
@JsonProperty("AccountId") val accountId: String? = null,
@JsonProperty("AssistantName") val assistantName: String? = null,
@JsonProperty("AssistantPhone") val assistantPhone: String? = null,
@JsonProperty("Birthdate") val birthdate: String? = null,
@JsonProperty("CleanStatus") val cleanStatus: String? = null,
@JsonProperty("CreatedById") val createdById: String,
@JsonProperty("CreatedDate") val createdDate: String,
@JsonProperty("Department") val department: String? = null,
@JsonProperty("Description") val description: String? = null,
@JsonProperty("Email") val email: String? = null,
@JsonProperty("EmailBouncedDate") val emailBouncedDate: String? = null,
@JsonProperty("EmailBouncedReason") val emailBouncedReason: String? = null,
@JsonProperty("Fax") val fax: String? = null,
@JsonProperty("HomePhone") val homePhone: String? = null,
@JsonProperty("IndividualId") val individualId: String? = null,
@JsonProperty("IsDeleted") val isDeleted: Boolean,
@JsonProperty("IsEmailBounced") val isEmailBounced: Boolean,
@JsonProperty("Jigsaw") val jigsaw: String? = null,
@JsonProperty("JigsawContactId") val jigsawContactId: String? = null,
@JsonProperty("Languages__c") val languages__c: String? = null,
@JsonProperty("LastActivityDate") val lastActivityDate: String? = null,
@JsonProperty("LastCURequestDate") val lastCURequestDate: String? = null,
@JsonProperty("LastCUUpdateDate") val lastCUUpdateDate: String? = null,
@JsonProperty("LastModifiedById") val lastModifiedById: String,
@JsonProperty("LastModifiedDate") val lastModifiedDate: String,
@JsonProperty("LastReferencedDate") val lastReferencedDate: String? = null,
@JsonProperty("LastViewedDate") val lastViewedDate: String? = null,
@JsonProperty("LeadSource") val leadSource: String? = null,
@JsonProperty("Level__c") val level__c: String? = null,
@JsonProperty("MailingAddress") val mailingAddress: Map<String, Any?>? = null,
@JsonProperty("MasterRecordId") val masterRecordId: String? = null,
@JsonProperty("MobilePhone") val mobilePhone: String? = null,
@JsonProperty("Name") val name: String,
@JsonProperty("OtherAddress") val otherAddress: Map<String, Any?>? = null,
@JsonProperty("OtherPhone") val otherPhone: String? = null,
@JsonProperty("OwnerId") val ownerId: String,
@JsonProperty("Phone") val phone: String? = null,
@JsonProperty("PhotoUrl") val photoUrl: String? = null,
@JsonProperty("ReportsToId") val reportsToId: String? = null,
@JsonProperty("SystemModstamp") val systemModstamp: String,
@JsonProperty("Title") val title: String? = null,
@JsonProperty("UserRecordAccessId") val userRecordAccessId: String? = null,
) : AbstractSObject<SObjectType>(type = SObjectType.CONTACT)
/**
* @property createdById Lookup(User)
* @property createdDate Date/Time
* @property customerStatusType Picklist
* @property id Lookup()
* @property isDeleted Checkbox
* @property lastModifiedById Lookup(User)
* @property lastModifiedDate Date/Time
* @property lastReferencedDate Date/Time
* @property lastViewedDate Date/Time
* @property name Text(255)
* @property ownerId Lookup(User,Group)
* @property partyId Lookup(Individual)
* @property systemModstamp Date/Time
* @property totalLifeTimeValue Number(9, 0)
* @property userRecordAccessId Lookup(User Record Access)
*/
class Customer (
@JsonProperty("CreatedById") val createdById: String,
@JsonProperty("CreatedDate") val createdDate: String,
@JsonProperty("CustomerStatusType") val customerStatusType: String? = null,
@JsonProperty("IsDeleted") val isDeleted: Boolean,
@JsonProperty("LastModifiedById") val lastModifiedById: String,
@JsonProperty("LastModifiedDate") val lastModifiedDate: String,
@JsonProperty("LastReferencedDate") val lastReferencedDate: String? = null,
@JsonProperty("LastViewedDate") val lastViewedDate: String? = null,
@JsonProperty("Name") val name: String,
@JsonProperty("OwnerId") val ownerId: String,
@JsonProperty("PartyId") val partyId: String? = null,
@JsonProperty("SystemModstamp") val systemModstamp: String,
@JsonProperty("TotalLifeTimeValue") val totalLifeTimeValue: Double? = null,
@JsonProperty("UserRecordAccessId") val userRecordAccessId: String? = null,
) : AbstractSObject<SObjectType>(type = SObjectType.CUSTOMER)
import com.fasterxml.jackson.annotation.JsonProperty
import com.fasterxml.jackson.core.type.TypeReference
import com.fasterxml.jackson.databind.DeserializationFeature
import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
import com.fasterxml.jackson.module.kotlin.registerKotlinModule
import java.net.HttpURLConnection
import java.net.IDN
import java.net.URI
import java.net.URL
import kotlin.reflect.KVisibility
import kotlin.reflect.full.findAnnotations
import kotlin.reflect.full.memberProperties
import kotlin.reflect.full.primaryConstructor
import kotlin.reflect.jvm.javaField
/**
* @param accessToken has to have [web, chatter_api, api] permissions for querying
* @param instanceUrl acquired in the same response as accessToken
*
* @credits to mjg123 https://github.com/mjg123/java-http-clients/blob/master/src/main/java/com/twilio/JavaHttpURLConnectionDemo.java
* @credits to madmax1028, broot https://discuss.kotlinlang.org/t/how-to-specify-generic-output-type-to-be-subclass-of-generic-type/24637/12
*/
class SalesforceClient(
@PublishedApi internal inline val accessToken: String,
@PublishedApi internal inline val instanceUrl: String,
) {
@PublishedApi
internal val apiVersion = "v53.0"
@PublishedApi
internal val mapper = jacksonObjectMapper().registerKotlinModule()
.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
inline fun <reified T: SObjectInterface> getAll(): SfResponse<T> =
getResponse<T>("SELECT ${getFields<T>().joinToString()} FROM ${T::class.simpleName}")
inline fun <reified T: SObjectInterface> count(): Int =
getResponse<T>("SELECT COUNT() FROM+${T::class.simpleName}")
.totalSize
@PublishedApi
internal inline fun <reified T: SObjectInterface> getResponse(query: String): SfResponse<T> {
val url = URL("$instanceUrl/services/data/$apiVersion/query?q=$query").toUri().toURL()
val connection: HttpURLConnection = url.openConnection() as HttpURLConnection
connection.setRequestProperty("accept", "application/json")
connection.setRequestProperty("Authorization", "Bearer $accessToken")
return mapper.readValue(connection.inputStream, object : TypeReference<SfResponse<T>>() {})
}
@OptIn(ExperimentalStdlibApi::class)
inline fun <reified T: SObjectInterface> getFields(): List<String> {
val propertiesWeWant = T::class.java.kotlin.memberProperties
.filter { prop ->
prop.visibility == KVisibility.PUBLIC
&& listOf("java.util", "java.lang").contains(prop.javaField?.type?.packageName)
&& prop.name != "attributes"
}
val bodyProps = propertiesWeWant.mapNotNull { it.javaField?.getAnnotation(JsonProperty::class.java)?.value }
val constructorProps = T::class.java.kotlin.primaryConstructor?.parameters
?.filter { it.name in (propertiesWeWant.map { it.name }) }
?.map { it.findAnnotations(JsonProperty::class).first().value }
?: emptyList()
return bodyProps + constructorProps
}
/**
* URI is used for URL encoding.
*/
@PublishedApi
internal fun URL.toUri() = URI(
this.protocol,
this.userInfo,
IDN.toASCII(this.host),
this.port,
this.path,
this.query, this.ref,
)
}
class SfResponse<T: SObjectInterface>(
val totalSize: Int,
val done: Boolean,
val records: List<T>,
)
interface SObjectInterface
data class SObjectAttributes<T: SObjectType>(
val type: T,
val url: String? = null,
)
abstract class AbstractSObject<T: SObjectType>(
type: T,
) : SObjectInterface {
val attributes: SObjectAttributes<T> = SObjectAttributes(type = type)
@JsonProperty("Id") val id: String? = null
}
enum class SObjectType(val jsonName: String) {
@JsonProperty("Account") ACCOUNT("Account"),
@JsonProperty("Asset") ASSET("Asset"),
@JsonProperty("Attachment") ATTACHMENT("Attachment"),
@JsonProperty("Calendar") CALENDAR("Calendar"),
@JsonProperty("Contact") CONTACT("Contact"),
@JsonProperty("Customer") CUSTOMER("Customer"),
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment