first commit Riabu
This commit is contained in:
20
force-app/main/default/classes/AccountTriggerHandler.cls
Normal file
20
force-app/main/default/classes/AccountTriggerHandler.cls
Normal file
@@ -0,0 +1,20 @@
|
||||
public class AccountTriggerHandler {
|
||||
public static boolean firstCreation = True;
|
||||
|
||||
public static void createCustomer(List<Account> accList){
|
||||
if(firstCreation){
|
||||
|
||||
|
||||
for (Account acc : accList ) {
|
||||
if (acc.Id != null) {
|
||||
System.debug('Triggered Account Id: ' + acc.Id);
|
||||
system.enqueueJob(new RiabuAccountToCustomer(acc.Id));
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ApexClass xmlns="http://soap.sforce.com/2006/04/metadata">
|
||||
<apiVersion>65.0</apiVersion>
|
||||
<status>Active</status>
|
||||
</ApexClass>
|
||||
3
force-app/main/default/classes/ContactTriggerHandler.cls
Normal file
3
force-app/main/default/classes/ContactTriggerHandler.cls
Normal file
@@ -0,0 +1,3 @@
|
||||
public class ContactTriggerHandler {
|
||||
public static Boolean becamePrimary = true;
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ApexClass xmlns="http://soap.sforce.com/2006/04/metadata">
|
||||
<apiVersion>65.0</apiVersion>
|
||||
<status>Active</status>
|
||||
</ApexClass>
|
||||
37
force-app/main/default/classes/CustomerCreationService.cls
Normal file
37
force-app/main/default/classes/CustomerCreationService.cls
Normal file
@@ -0,0 +1,37 @@
|
||||
public with sharing class CustomerCreationService {
|
||||
public static void createCustomer(Id accountId) {
|
||||
System.Debug('Triggering Account' +accountId
|
||||
);
|
||||
Account acc = [
|
||||
SELECT Id, Name, Registration_Number__c, CreatedDate, Days_to_Pay__c, Procurement_Portal__c
|
||||
FROM Account WHERE Id = :accountId
|
||||
|
||||
];
|
||||
|
||||
RIABU_Integration__mdt cfg = RiabuConfigUtil.getConfig();
|
||||
String token = RiabuAuthService.getValidAccessToken();
|
||||
String baseUrl = cfg.Endpoint__c.replace('/oauth/token', ''); // adjust base
|
||||
|
||||
HttpRequest req = new HttpRequest();
|
||||
req.setEndpoint(cfg.Endpoint__c + '/api/v1/wizard/customer');
|
||||
req.setMethod('POST');
|
||||
req.setHeader('Content-Type', 'application/x-www-form-urlencoded');
|
||||
req.setHeader('Authorization', 'Bearer ' + token);
|
||||
|
||||
String body =
|
||||
'company_name=' + EncodingUtil.urlEncode(acc.Name,'UTF-8') +
|
||||
'&company_uen=' + EncodingUtil.urlEncode(acc.Registration_Number__c,'UTF-8') +
|
||||
'&customer_since=' + EncodingUtil.urlEncode(acc.CreatedDate.format('yyyy-MM-dd'),'UTF-8') +
|
||||
'&agreed_credit_terms_day=' + EncodingUtil.urlEncode(String.valueOf(acc.Days_to_Pay__c),'UTF-8') +
|
||||
'&procurement_portal=' + EncodingUtil.urlEncode(acc.Procurement_Portal__c,'UTF-8');
|
||||
|
||||
req.setBody(body);
|
||||
System.Debug('Request Body' + body);
|
||||
System.Debug('Endpoint' + req.getEndpoint());
|
||||
|
||||
Http http = new Http();
|
||||
HttpResponse res = http.send(req);
|
||||
System.debug('Customer Response: ' + res.getBody());
|
||||
System.debug('Response Code: ' + res.getStatusCode());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ApexClass xmlns="http://soap.sforce.com/2006/04/metadata">
|
||||
<apiVersion>65.0</apiVersion>
|
||||
<status>Active</status>
|
||||
</ApexClass>
|
||||
7
force-app/main/default/classes/DEF.cls
Normal file
7
force-app/main/default/classes/DEF.cls
Normal file
@@ -0,0 +1,7 @@
|
||||
public with sharing class DEF {
|
||||
|
||||
public DEF() {
|
||||
|
||||
System.System.debug('HELLO WORLD');
|
||||
}
|
||||
}
|
||||
5
force-app/main/default/classes/DEF.cls-meta.xml
Normal file
5
force-app/main/default/classes/DEF.cls-meta.xml
Normal file
@@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ApexClass xmlns="http://soap.sforce.com/2006/04/metadata">
|
||||
<apiVersion>65.0</apiVersion>
|
||||
<status>Active</status>
|
||||
</ApexClass>
|
||||
13542
force-app/main/default/classes/MetadataService.cls
Normal file
13542
force-app/main/default/classes/MetadataService.cls
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ApexClass xmlns="http://soap.sforce.com/2006/04/metadata">
|
||||
<apiVersion>65.0</apiVersion>
|
||||
<status>Active</status>
|
||||
</ApexClass>
|
||||
15
force-app/main/default/classes/MetadataUtil.cls
Normal file
15
force-app/main/default/classes/MetadataUtil.cls
Normal file
@@ -0,0 +1,15 @@
|
||||
public class MetadataUtil {
|
||||
|
||||
public static MetadataService.MetadataPort createService() {
|
||||
|
||||
MetadataService.MetadataPort service = new MetadataService.MetadataPort();
|
||||
|
||||
service.SessionHeader = new MetadataService.SessionHeader_element();
|
||||
|
||||
service.SessionHeader.sessionId = UserInfo.getSessionId();
|
||||
|
||||
return service;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
5
force-app/main/default/classes/MetadataUtil.cls-meta.xml
Normal file
5
force-app/main/default/classes/MetadataUtil.cls-meta.xml
Normal file
@@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ApexClass xmlns="http://soap.sforce.com/2006/04/metadata">
|
||||
<apiVersion>65.0</apiVersion>
|
||||
<status>Active</status>
|
||||
</ApexClass>
|
||||
94
force-app/main/default/classes/RiabuAccountSync.cls
Normal file
94
force-app/main/default/classes/RiabuAccountSync.cls
Normal file
@@ -0,0 +1,94 @@
|
||||
public class RiabuAccountSync {
|
||||
|
||||
public static String insertAccounts() {
|
||||
|
||||
RIABU_Integration__mdt config = [
|
||||
SELECT Access_Token__c, Refresh_Token__c, Endpoint__c, RIABU_Fetch_Accounts_Endpoint__c
|
||||
FROM RIABU_Integration__mdt
|
||||
WHERE DeveloperName = 'Riabu_Record'
|
||||
LIMIT 1
|
||||
];
|
||||
|
||||
HttpRequest req = new HttpRequest();
|
||||
req.setEndpoint(config.RIABU_Fetch_Accounts_Endpoint__c);
|
||||
req.setMethod('GET');
|
||||
|
||||
if (config.Access_Token__c == null) {
|
||||
RiabuAuthAccessToken.getAccessToken();
|
||||
}
|
||||
|
||||
req.setHeader('Authorization', 'Bearer ' + config.Access_Token__c);
|
||||
|
||||
Http http = new Http();
|
||||
HttpResponse res = http.send(req);
|
||||
|
||||
if (res.getStatusCode() != 200) {
|
||||
return 'Invalid Field Callout';
|
||||
}
|
||||
|
||||
Map<String, Object> root = (Map<String, Object>) JSON.deserializeUntyped(res.getBody());
|
||||
List<Object> dataList = (List<Object>) root.get('data');
|
||||
|
||||
if (dataList == null || dataList.isEmpty()) {
|
||||
return 'No Data Returned';
|
||||
}
|
||||
|
||||
// step 1: collect incoming riabu ids
|
||||
Set<String> incomingIds = new Set<String>();
|
||||
for (Object o : dataList) {
|
||||
Map<String, Object> item = (Map<String, Object>) o;
|
||||
incomingIds.add(String.valueOf(item.get('id')));
|
||||
}
|
||||
|
||||
// step 2: fetch existing SF accounts
|
||||
Map<String, Account> existingMap = new Map<String, Account>();
|
||||
|
||||
if (!incomingIds.isEmpty()) {
|
||||
for (Account acc : [
|
||||
SELECT Id, RIABU_Customer_ID__c
|
||||
FROM Account
|
||||
WHERE RIABU_Customer_ID__c IN :incomingIds
|
||||
]) {
|
||||
existingMap.put(acc.RIABU_Customer_ID__c, acc);
|
||||
}
|
||||
}
|
||||
|
||||
// step 3: build list of new accounts
|
||||
Set<String> processedIds = new Set<String>();
|
||||
List<Account> toInsert = new List<Account>();
|
||||
|
||||
for (Object o : dataList) {
|
||||
Map<String, Object> item = (Map<String, Object>) o;
|
||||
String riabuId = String.valueOf(item.get('id'));
|
||||
|
||||
if (riabuId == null) continue;
|
||||
|
||||
// skip duplicates in API response
|
||||
if (processedIds.contains(riabuId)) continue;
|
||||
processedIds.add(riabuId);
|
||||
|
||||
// skip existing SF accounts
|
||||
if (existingMap.containsKey(riabuId)) {
|
||||
System.debug('[' + riabuId + '] ALREADY EXISTS IN SALESFORCE');
|
||||
continue;
|
||||
}
|
||||
|
||||
// insert new
|
||||
Account a = new Account();
|
||||
a.Name = (String) item.get('name');
|
||||
a.RIABU_Customer_ID__c = riabuId;
|
||||
a.Days_to_Pay__c = (Integer) item.get('agreed_credit_terms_day');
|
||||
toInsert.add(a);
|
||||
|
||||
System.debug('[' + riabuId + '] Record Inserted ***');
|
||||
}
|
||||
|
||||
// step 4: insert
|
||||
if (!toInsert.isEmpty()) {
|
||||
insert toInsert;
|
||||
return toInsert.size() + ' new records inserted';
|
||||
}
|
||||
|
||||
return 'No new records';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ApexClass xmlns="http://soap.sforce.com/2006/04/metadata">
|
||||
<apiVersion>65.0</apiVersion>
|
||||
<status>Active</status>
|
||||
</ApexClass>
|
||||
88
force-app/main/default/classes/RiabuAccountToCustomer.cls
Normal file
88
force-app/main/default/classes/RiabuAccountToCustomer.cls
Normal file
@@ -0,0 +1,88 @@
|
||||
public class RiabuAccountToCustomer implements Queueable, Database.AllowsCallouts {
|
||||
|
||||
Id accId;
|
||||
|
||||
public RiabuAccountToCustomer(Id accountId) {
|
||||
|
||||
this.accId = accountId;
|
||||
|
||||
}
|
||||
|
||||
public void execute(QueueableContext qc) {
|
||||
|
||||
try {
|
||||
|
||||
Account acc = [
|
||||
|
||||
SELECT Id, Name, Registration_Number__c, CreatedDate, Days_to_Pay__c
|
||||
|
||||
FROM Account
|
||||
|
||||
WHERE Id = :accId
|
||||
|
||||
];
|
||||
|
||||
System.debug('✅ Account Record to Send: ' + acc.Id);
|
||||
|
||||
RIABU_Integration__mdt config = [
|
||||
|
||||
SELECT Access_Token__c, Refresh_Token__c,Endpoint__c
|
||||
|
||||
FROM RIABU_Integration__mdt
|
||||
|
||||
WHERE DeveloperName = 'Riabu_Record'
|
||||
|
||||
LIMIT 1
|
||||
|
||||
];
|
||||
|
||||
String token = config.Access_Token__c;
|
||||
|
||||
if (String.isBlank(token)) {
|
||||
|
||||
System.debug('❌ No Access Token. Stopping.');
|
||||
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
HttpRequest req = new HttpRequest();
|
||||
|
||||
req.setEndpoint(config.Endpoint__c + '/api/v1/wizard/customer');
|
||||
|
||||
req.setMethod('POST');
|
||||
|
||||
req.setHeader('Authorization', 'Bearer ' + token);
|
||||
|
||||
req.setHeader('Content-Type', 'application/json');
|
||||
|
||||
Map<String, Object> payload = new Map<String, Object>{
|
||||
|
||||
'company_name' => acc.Name,
|
||||
|
||||
'company_uen' => acc.Registration_Number__c,
|
||||
|
||||
'customer_since' => acc.CreatedDate.format('yyyy-MM-dd'),
|
||||
|
||||
'agreed_credit_terms_day' => (acc.Days_to_Pay__c == null ? 0 : acc.Days_to_Pay__c)
|
||||
|
||||
};
|
||||
|
||||
req.setBody(JSON.serialize(payload));
|
||||
|
||||
Http http = new Http();
|
||||
|
||||
HttpResponse res = http.send(req);
|
||||
|
||||
System.debug('🌍 Riabu Response Code: ' + res.getStatusCode());
|
||||
|
||||
|
||||
} catch (Exception e) {
|
||||
|
||||
System.debug('❌ Error: ' + e.getMessage());
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ApexClass xmlns="http://soap.sforce.com/2006/04/metadata">
|
||||
<apiVersion>65.0</apiVersion>
|
||||
<status>Active</status>
|
||||
</ApexClass>
|
||||
45
force-app/main/default/classes/RiabuAuthAccessToken.cls
Normal file
45
force-app/main/default/classes/RiabuAuthAccessToken.cls
Normal file
@@ -0,0 +1,45 @@
|
||||
public class RiabuAuthAccessToken {
|
||||
|
||||
public static String getAccessToken() {
|
||||
|
||||
RIABU_Integration__mdt config = RIABU_Integration__mdt.getInstance('Riabu_Record');
|
||||
|
||||
System.debug('🔄 Token expired or unavailable. Requesting new token...');
|
||||
|
||||
HttpRequest req = new HttpRequest();
|
||||
req.setEndpoint(config.Endpoint__c + '/api/v1/oauth/token');
|
||||
req.setMethod('POST');
|
||||
req.setHeader('Content-Type', 'application/json');
|
||||
|
||||
|
||||
Map<String, String> payload = new Map<String, String>();
|
||||
payload.put('username', config.Username__c);
|
||||
payload.put('client_id',config.Client_Id__c);
|
||||
payload.put('client_secret',config.Client_Secret__c);
|
||||
payload.put('password', config.Password__c);
|
||||
payload.put('grant_type', config.Grant_Type__c);
|
||||
req.setBody(JSON.serialize(payload));
|
||||
|
||||
|
||||
Http http = new Http();
|
||||
HttpResponse res = http.send(req);
|
||||
|
||||
System.debug('📥 Token Response: ' + res.getBody());
|
||||
|
||||
if (res.getStatusCode() != 200) {
|
||||
System.debug('❌ Token generation failed');
|
||||
return null;
|
||||
}
|
||||
|
||||
Map<String, Object> tokenMap = (Map<String, Object>) JSON.deserializeUntyped(res.getBody());
|
||||
|
||||
String newAccessToken = (String) tokenMap.get('access_token');
|
||||
String newRefreshToken = (String) tokenMap.get('refresh_token');
|
||||
|
||||
System.enqueueJob(new RiabuTokenUpdateJob('Riabu_Record', newAccessToken, newRefreshToken));
|
||||
|
||||
System.debug('✅ Token refreshed and CMDT update queued');
|
||||
|
||||
return newAccessToken;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ApexClass xmlns="http://soap.sforce.com/2006/04/metadata">
|
||||
<apiVersion>65.0</apiVersion>
|
||||
<status>Active</status>
|
||||
</ApexClass>
|
||||
95
force-app/main/default/classes/RiabuContactSync.cls
Normal file
95
force-app/main/default/classes/RiabuContactSync.cls
Normal file
@@ -0,0 +1,95 @@
|
||||
public class RiabuContactSync {
|
||||
|
||||
public static String syncContacts(String riabuCustomerId) {
|
||||
|
||||
System.debug(' START — RiabuContactSync for CustomerId: ' + riabuCustomerId);
|
||||
|
||||
// Load Integration Config
|
||||
RIABU_Integration__mdt config = [
|
||||
SELECT Access_Token__c, Refresh_Token__c, RIABU_Fetch_Contacts_Endpoint__c
|
||||
FROM RIABU_Integration__mdt
|
||||
WHERE DeveloperName = 'Riabu_Record'
|
||||
LIMIT 1
|
||||
];
|
||||
|
||||
if (config == null || config.RIABU_Fetch_Contacts_Endpoint__c == null) {
|
||||
return 'Config or endpoint missing from Metadata';
|
||||
}
|
||||
|
||||
String baseEndpoint = config.RIABU_Fetch_Contacts_Endpoint__c;
|
||||
if (!baseEndpoint.endsWith('/')) {
|
||||
baseEndpoint += '/';
|
||||
}
|
||||
|
||||
String endpoint = baseEndpoint + riabuCustomerId;
|
||||
System.debug(' Corrected Request Endpoint: ' + endpoint);
|
||||
|
||||
HttpRequest req = new HttpRequest();
|
||||
req.setEndpoint(endpoint);
|
||||
req.setMethod('GET');
|
||||
|
||||
if (String.isBlank(config.Access_Token__c)) {
|
||||
System.debug('Access Token missing — Generating new token');
|
||||
RiabuAuthAccessToken.getAccessToken();
|
||||
}
|
||||
|
||||
req.setHeader('Authorization', 'Bearer ' + config.Access_Token__c);
|
||||
|
||||
Http http = new Http();
|
||||
HttpResponse res = http.send(req);
|
||||
|
||||
System.debug('Response Status: ' + res.getStatusCode());
|
||||
System.debug('Body: ' + res.getBody());
|
||||
|
||||
if (res.getStatusCode() != 200) {
|
||||
return 'Riabu Contact Fetch Error: ' + res.getStatus();
|
||||
}
|
||||
|
||||
// Parse JSON
|
||||
Map<String, Object> root = (Map<String, Object>)
|
||||
JSON.deserializeUntyped(res.getBody());
|
||||
|
||||
if (root == null || root.get('data') == null) {
|
||||
return 'Invalid data from Riabu API';
|
||||
}
|
||||
|
||||
Map<String, Object> data = (Map<String, Object>) root.get('data');
|
||||
Map<String, Object> model = (Map<String, Object>) data.get('model');
|
||||
|
||||
if (model == null) {
|
||||
return 'No Contact Model Received';
|
||||
}
|
||||
|
||||
System.debug('Riabu Contact: ' + model);
|
||||
|
||||
// Ensure Account exists
|
||||
Account acc;
|
||||
try {
|
||||
acc = [
|
||||
SELECT Id
|
||||
FROM Account
|
||||
WHERE RIABU_Customer_ID__c = :riabuCustomerId
|
||||
LIMIT 1
|
||||
];
|
||||
} catch (Exception e) {
|
||||
return 'No matching Salesforce Account';
|
||||
}
|
||||
|
||||
String riabuContactId = String.valueOf(model.get('id'));
|
||||
|
||||
Contact con = new Contact();
|
||||
con.RIABU_Contact_ID__c = riabuContactId;
|
||||
con.LastName = String.valueOf(model.get('accounts_payable_contact_name'));
|
||||
con.Phone = String.valueOf(model.get('accounts_payable_phone_number'));
|
||||
con.Email = String.valueOf(model.get('accounts_payable_email_address'));
|
||||
con.Invoice_Email__c = String.valueOf(model.get('email_to_send_e_invoices_to'));
|
||||
con.isPrimary__c = true;
|
||||
con.AccountId = acc.Id;
|
||||
|
||||
// Use UPSERT with external Id (safe duplicate handling)
|
||||
ContactTriggerHandler.becamePrimary = false;
|
||||
upsert con RIABU_Contact_ID__c;
|
||||
|
||||
return 'Contact synced successfully! Riabu ID: ' + riabuContactId;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ApexClass xmlns="http://soap.sforce.com/2006/04/metadata">
|
||||
<apiVersion>65.0</apiVersion>
|
||||
<status>Active</status>
|
||||
</ApexClass>
|
||||
116
force-app/main/default/classes/RiabuOrderSync.cls
Normal file
116
force-app/main/default/classes/RiabuOrderSync.cls
Normal file
@@ -0,0 +1,116 @@
|
||||
public class RiabuOrderSync {
|
||||
|
||||
public static String syncOrders(String riabuCustomerId) {
|
||||
|
||||
System.debug('START — RiabuOrderSync for CustomerId: ' + riabuCustomerId);
|
||||
|
||||
// Load Integration Config
|
||||
RIABU_Integration__mdt config = [
|
||||
SELECT Access_Token__c, RIABU_Fetch_Orders_Endpoint__c
|
||||
FROM RIABU_Integration__mdt
|
||||
WHERE DeveloperName = 'Riabu_Record'
|
||||
LIMIT 1
|
||||
];
|
||||
|
||||
if (config == null || config.RIABU_Fetch_Orders_Endpoint__c == null) {
|
||||
return 'Orders Endpoint missing in Metadata';
|
||||
}
|
||||
|
||||
// Ensure correct format with trailing slash
|
||||
String baseEndpoint = config.RIABU_Fetch_Orders_Endpoint__c;
|
||||
if (!baseEndpoint.endsWith('/')) {
|
||||
baseEndpoint += '/';
|
||||
}
|
||||
|
||||
String endpoint = baseEndpoint + riabuCustomerId + '?per-page=99999&page=1';
|
||||
System.debug('Final API Endpoint: ' + endpoint);
|
||||
|
||||
HttpRequest req = new HttpRequest();
|
||||
req.setEndpoint(endpoint);
|
||||
req.setMethod('GET');
|
||||
req.setHeader('Authorization', 'Bearer ' + config.Access_Token__c);
|
||||
|
||||
Http http = new Http();
|
||||
HttpResponse res = http.send(req);
|
||||
|
||||
System.debug('Response Code: ' + res.getStatusCode());
|
||||
System.debug('Response Body: ' + res.getBody());
|
||||
|
||||
if (res.getStatusCode() != 200) {
|
||||
return 'Riabu Order Fetch Error: ' + res.getStatus();
|
||||
}
|
||||
|
||||
Map<String, Object> root =
|
||||
(Map<String, Object>) JSON.deserializeUntyped(res.getBody());
|
||||
|
||||
if (root == null || root.get('data') == null) {
|
||||
return 'Invalid or Empty Riabu Response';
|
||||
}
|
||||
|
||||
Map<String, Object> data = (Map<String, Object>) root.get('data');
|
||||
List<Object> items = (List<Object>) data.get('items');
|
||||
|
||||
if (items == null || items.isEmpty()) {
|
||||
return 'No Orders Found in Riabu';
|
||||
}
|
||||
|
||||
System.debug('Total Orders Returned: ' + items.size());
|
||||
|
||||
Account acc;
|
||||
try {
|
||||
acc = [
|
||||
SELECT Id FROM Account
|
||||
WHERE RIABU_Customer_ID__c = :riabuCustomerId
|
||||
LIMIT 1
|
||||
];
|
||||
} catch (Exception e) {
|
||||
return 'No Matching Salesforce Account Found';
|
||||
}
|
||||
|
||||
List<Opportunity> oppsToUpsert = new List<Opportunity>();
|
||||
|
||||
for (Object o : items) {
|
||||
Map<String, Object> order = (Map<String, Object>) o;
|
||||
|
||||
String riabuOrderId = String.valueOf(order.get('id'));
|
||||
|
||||
Opportunity opp = new Opportunity();
|
||||
opp.Riabu_Order_Id__c = riabuOrderId;
|
||||
opp.AccountId = acc.Id;
|
||||
|
||||
// Name
|
||||
opp.Name = String.isNotBlank((String)order.get('opportunity'))
|
||||
? (String) order.get('opportunity')
|
||||
: 'Order ' + riabuOrderId;
|
||||
|
||||
// Amount
|
||||
if (order.get('total_invoice_amount') != null) {
|
||||
opp.Amount = Decimal.valueOf(String.valueOf(order.get('total_invoice_amount')));
|
||||
}
|
||||
|
||||
// Close Date
|
||||
try {
|
||||
if (order.get('invoice_due_date') != null) {
|
||||
opp.CloseDate = Date.valueOf(
|
||||
String.valueOf(order.get('invoice_due_date'))
|
||||
);
|
||||
} else {
|
||||
opp.CloseDate = Date.today().addDays(7);
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
opp.CloseDate = Date.today().addDays(7);
|
||||
}
|
||||
|
||||
opp.StageName = 'Prospecting';
|
||||
|
||||
oppsToUpsert.add(opp);
|
||||
}
|
||||
|
||||
if (!oppsToUpsert.isEmpty()) {
|
||||
upsert oppsToUpsert Riabu_Order_Id__c;
|
||||
return oppsToUpsert.size() + ' Orders Synced (Upserted)';
|
||||
}
|
||||
|
||||
return 'No New Orders to Sync';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ApexClass xmlns="http://soap.sforce.com/2006/04/metadata">
|
||||
<apiVersion>65.0</apiVersion>
|
||||
<status>Active</status>
|
||||
</ApexClass>
|
||||
62
force-app/main/default/classes/RiabuTokenUpdateJob.cls
Normal file
62
force-app/main/default/classes/RiabuTokenUpdateJob.cls
Normal file
@@ -0,0 +1,62 @@
|
||||
public class RiabuTokenUpdateJob implements Queueable, Database.AllowsCallouts {
|
||||
|
||||
private String recordName;
|
||||
private String newAccessToken;
|
||||
private String newRefreshToken;
|
||||
//private Datetime expiryTime;
|
||||
|
||||
public RiabuTokenUpdateJob(String recordName, String accessToken, String refreshToken) {
|
||||
this.recordName = recordName;
|
||||
this.newAccessToken = accessToken;
|
||||
this.newRefreshToken = refreshToken;
|
||||
//this.expiryTime = expiryTime;
|
||||
}
|
||||
|
||||
public void execute(QueueableContext qc) {
|
||||
MetadataService.MetadataPort service = MetadataUtil.createService();
|
||||
MetadataService.IReadResult readResult =
|
||||
service.readMetadata('CustomMetadata', new String[] { 'RIABU_Integration__mdt.' + recordName });
|
||||
MetadataService.CustomMetadata cmdt =
|
||||
(MetadataService.CustomMetadata) readResult.getRecords()[0];
|
||||
// Keep existing field values
|
||||
List<MetadataService.CustomMetadataValue> updatedValues = cmdt.values;
|
||||
// Update Access Token
|
||||
upsertValue(updatedValues, 'Access_Token__c', newAccessToken);
|
||||
// Update Refresh Token only if returned
|
||||
if(String.isNotBlank(newRefreshToken)){
|
||||
upsertValue(updatedValues, 'Refresh_Token__c', newRefreshToken);
|
||||
}
|
||||
cmdt.values = updatedValues;
|
||||
MetadataService.SaveResult[] results =
|
||||
service.updateMetadata(new MetadataService.Metadata[] { cmdt });
|
||||
if (results[0].success) {
|
||||
System.debug('✅ CMDT Updated Successfully');
|
||||
} else {
|
||||
System.debug('❌ CMDT Update Failed: ' + results[0].errors[0].message);
|
||||
}
|
||||
}
|
||||
private void upsertValue(List<MetadataService.CustomMetadataValue> listVals, String fieldName, String fieldValue) {
|
||||
Boolean found = false;
|
||||
for(MetadataService.CustomMetadataValue v : listVals) {
|
||||
if(v.field == fieldName){
|
||||
v.value = fieldValue;
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(!found){
|
||||
MetadataService.CustomMetadataValue newVal = new MetadataService.CustomMetadataValue();
|
||||
newVal.field = fieldName;
|
||||
newVal.value = fieldValue;
|
||||
listVals.add(newVal);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private MetadataService.CustomMetadataValue createValue(String fieldName, String val) {
|
||||
MetadataService.CustomMetadataValue v = new MetadataService.CustomMetadataValue();
|
||||
v.field = fieldName;
|
||||
v.value = val;
|
||||
return v;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ApexClass xmlns="http://soap.sforce.com/2006/04/metadata">
|
||||
<apiVersion>65.0</apiVersion>
|
||||
<status>Active</status>
|
||||
</ApexClass>
|
||||
5
force-app/main/default/classes/Test2.cls
Normal file
5
force-app/main/default/classes/Test2.cls
Normal file
@@ -0,0 +1,5 @@
|
||||
public with sharing class Test2{
|
||||
public Test2(){
|
||||
|
||||
}
|
||||
}
|
||||
5
force-app/main/default/classes/Test2.cls-meta.xml
Normal file
5
force-app/main/default/classes/Test2.cls-meta.xml
Normal file
@@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ApexClass xmlns="http://soap.sforce.com/2006/04/metadata">
|
||||
<apiVersion>65.0</apiVersion>
|
||||
<status>Active</status>
|
||||
</ApexClass>
|
||||
@@ -0,0 +1,91 @@
|
||||
@isTest
|
||||
public class TestLinkCOACustomerToLMALicense {
|
||||
@testSetup
|
||||
static void setup() {
|
||||
// Create test data for licenses
|
||||
List<sfLma__License__c> licenses = new List<sfLma__License__c>();
|
||||
for (Integer i = 0; i < 5; i++) {
|
||||
sfLma__License__c license = new sfLma__License__c();
|
||||
license.sfLma__Subscriber_Org_ID__c = '00D' + i + '00000000001';
|
||||
license.sfLma__Seats__c = 4;
|
||||
licenses.add(license);
|
||||
}
|
||||
insert licenses;
|
||||
}
|
||||
|
||||
@isTest
|
||||
static void testTriggerAfterInsert() {
|
||||
// Create test customer records
|
||||
List<CHANNEL_ORDERS__Customer__c> customers = new List<CHANNEL_ORDERS__Customer__c>();
|
||||
for (Integer i = 0; i < 5; i++) {
|
||||
CHANNEL_ORDERS__Customer__c customer = new CHANNEL_ORDERS__Customer__c();
|
||||
customer.CHANNEL_ORDERS__Customer_Company_Name__c = 'Test Customer'+ i;
|
||||
customer.CHANNEL_ORDERS__Customer_Country__c = 'US';
|
||||
customer.CHANNEL_ORDERS__Customer_State__c = 'CA';
|
||||
customer.CHANNEL_ORDERS__Customer_City__c = 'Marseille';
|
||||
customer.CHANNEL_ORDERS__Customer_Street__c = 'MyStreet';
|
||||
customer.CHANNEL_ORDERS__Customer_Zip_Postal_Code__c = '13001';
|
||||
customer.CHANNEL_ORDERS__Customer_Org_ID__c = '00D' + i + '00000000001';
|
||||
customers.add(customer);
|
||||
}
|
||||
insert customers;
|
||||
|
||||
// Query licenses to verify they are updated
|
||||
List<sfLma__License__c> updatedLicenses = [SELECT COA_Customer__c
|
||||
FROM sfLma__License__c
|
||||
WHERE COA_Customer__c != null];
|
||||
|
||||
// Assert that the licenses have been correctly updated with customer references
|
||||
System.assertEquals(5, updatedLicenses.size(), 'All licenses should be updated');
|
||||
for (sfLma__License__c license : updatedLicenses) {
|
||||
System.assertNotEquals(null, license.COA_Customer__c, 'License should be linked to a customer');
|
||||
}
|
||||
}
|
||||
|
||||
@isTest
|
||||
static void testTriggerAfterUpdate() {
|
||||
// Create a test customer record and insert it
|
||||
CHANNEL_ORDERS__Customer__c customer = new CHANNEL_ORDERS__Customer__c();
|
||||
customer.CHANNEL_ORDERS__Customer_Company_Name__c = 'Test Customer A';
|
||||
customer.CHANNEL_ORDERS__Customer_Country__c = 'US';
|
||||
customer.CHANNEL_ORDERS__Customer_State__c = 'CA';
|
||||
customer.CHANNEL_ORDERS__Customer_City__c = 'Marseille';
|
||||
customer.CHANNEL_ORDERS__Customer_Street__c = 'MyStreet';
|
||||
customer.CHANNEL_ORDERS__Customer_Zip_Postal_Code__c = '13001';
|
||||
customer.CHANNEL_ORDERS__Customer_Org_ID__c = '00DA00000000001';
|
||||
insert customer;
|
||||
|
||||
// Update the customer to trigger the update scenario
|
||||
customer.CHANNEL_ORDERS__Customer_Org_ID__c = '00D100000000001';
|
||||
update customer;
|
||||
|
||||
// Query licenses to verify they are updated
|
||||
List<sfLma__License__c> updatedLicenses = [SELECT Id, COA_Customer__c, sfLma__Subscriber_Org_ID__c
|
||||
FROM sfLma__License__c
|
||||
WHERE sfLma__Subscriber_Org_ID__c = :customer.CHANNEL_ORDERS__Customer_Org_ID__c];
|
||||
|
||||
// Assert that the license has been correctly updated with customer references
|
||||
System.assertEquals(1, updatedLicenses.size(), 'One license should be updated');
|
||||
for (sfLma__License__c license : updatedLicenses) {
|
||||
System.assertEquals(customer.Id, license.COA_Customer__c, 'License should be linked to the updated customer');
|
||||
}
|
||||
}
|
||||
|
||||
@isTest
|
||||
static void testTriggerNoMatchingLicense() {
|
||||
// Create a customer with an org ID that does not match any licenses
|
||||
CHANNEL_ORDERS__Customer__c customer = new CHANNEL_ORDERS__Customer__c();
|
||||
customer.CHANNEL_ORDERS__Customer_Company_Name__c = 'Test Customer B';
|
||||
customer.CHANNEL_ORDERS__Customer_Country__c = 'US';
|
||||
customer.CHANNEL_ORDERS__Customer_State__c = 'CA';
|
||||
customer.CHANNEL_ORDERS__Customer_City__c = 'Marseille';
|
||||
customer.CHANNEL_ORDERS__Customer_Street__c = 'MyStreet';
|
||||
customer.CHANNEL_ORDERS__Customer_Zip_Postal_Code__c = '13001';
|
||||
customer.CHANNEL_ORDERS__Customer_Org_ID__c = '00D000000000999';
|
||||
insert customer;
|
||||
|
||||
// Ensure no licenses are updated
|
||||
List<sfLma__License__c> licenses = [SELECT Id, COA_Customer__c FROM sfLma__License__c WHERE COA_Customer__c != null];
|
||||
System.assertEquals(0, licenses.size(), 'No licenses should be updated when there is no matching org ID');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ApexClass xmlns="http://soap.sforce.com/2006/04/metadata">
|
||||
<apiVersion>61.0</apiVersion>
|
||||
<packageVersions>
|
||||
<majorNumber>3</majorNumber>
|
||||
<minorNumber>71</minorNumber>
|
||||
<namespace>CHANNEL_ORDERS</namespace>
|
||||
</packageVersions>
|
||||
<packageVersions>
|
||||
<majorNumber>1</majorNumber>
|
||||
<minorNumber>21</minorNumber>
|
||||
<namespace>sfLma</namespace>
|
||||
</packageVersions>
|
||||
<status>Active</status>
|
||||
</ApexClass>
|
||||
5
force-app/main/default/triggers/AccountTrigger.trigger
Normal file
5
force-app/main/default/triggers/AccountTrigger.trigger
Normal file
@@ -0,0 +1,5 @@
|
||||
trigger AccountTrigger on Account (after insert, after update) {
|
||||
AccountTriggerHandler.createCustomer(Trigger.New);
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ApexTrigger xmlns="http://soap.sforce.com/2006/04/metadata">
|
||||
<apiVersion>65.0</apiVersion>
|
||||
<status>Active</status>
|
||||
</ApexTrigger>
|
||||
12
force-app/main/default/triggers/ContactTrigger.trigger
Normal file
12
force-app/main/default/triggers/ContactTrigger.trigger
Normal file
@@ -0,0 +1,12 @@
|
||||
trigger ContactTrigger on Contact (after insert, after update) {
|
||||
|
||||
if (Trigger.isAfter) {
|
||||
if (Trigger.isInsert || Trigger.isUpdate) {
|
||||
// Only run trigger logic if allowed
|
||||
if (ContactTriggerHandler.becamePrimary) {
|
||||
System.debug('Trigger executed - becamePrimary is TRUE');
|
||||
// your logic here if needed
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ApexTrigger xmlns="http://soap.sforce.com/2006/04/metadata">
|
||||
<apiVersion>65.0</apiVersion>
|
||||
<status>Active</status>
|
||||
</ApexTrigger>
|
||||
@@ -0,0 +1,29 @@
|
||||
trigger OpportunityAfterTrigger on Opportunity(after update, after insert){
|
||||
map<Id, List<Decimal>> accIdOppAmtMap = new map<Id, List<Decimal>>();
|
||||
List<Account> accListToUpdate = new List<Account>();
|
||||
for(Opportunity opp : Trigger.new){
|
||||
accIdOppAmtMap.put(opp.accountId, new List<Decimal>());
|
||||
|
||||
}
|
||||
if(accIdOppAmtMap.size() > 0){
|
||||
|
||||
List<Opportunity> oppList = [Select AccountId, Amount From Opportunity Where AccountId IN : accIdOppAmtMap.keySet() Order By Amount DESC] ;
|
||||
|
||||
for(Opportunity opp : oppList){
|
||||
if(accIdOppAmtMap.ContainsKey(opp.AccountId)){
|
||||
accIdOppAmtMap.get(opp.AccountId).add(opp.Amount);
|
||||
}
|
||||
}
|
||||
}
|
||||
for(Id accId : accIdOppAmtMap.KeySet()){
|
||||
Account acc = new Account(Id = accId);
|
||||
if(accIdOppAmtMap.get(accId).size() > 1){
|
||||
acc.AnnualRevenue = accIdOppAmtMap.get(accId).get(1);
|
||||
} else{
|
||||
acc.AnnualRevenue = accIdOppAmtMap.get(accId).get(0);
|
||||
}
|
||||
accListToUpdate.add(acc);
|
||||
}
|
||||
update accListToUpdate;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ApexTrigger xmlns="http://soap.sforce.com/2006/04/metadata">
|
||||
<apiVersion>63.0</apiVersion>
|
||||
<status>Active</status>
|
||||
</ApexTrigger>
|
||||
@@ -0,0 +1,26 @@
|
||||
trigger linkCOACustomerToLMALicense on CHANNEL_ORDERS__Customer__c (after insert, after update) {
|
||||
// map to capture license id + customer id
|
||||
map<string,id> allCustomersWithOrgID = new map<string,id>();
|
||||
// retrieve all customer org id in the trigger
|
||||
string customerOrgId = '';
|
||||
for (CHANNEL_ORDERS__Customer__c c : trigger.new)
|
||||
{
|
||||
customerOrgId=c.CHANNEL_ORDERS__Customer_Org_ID__c;
|
||||
allCustomersWithOrgID.put(customerOrgId.left(15), c.id);
|
||||
}
|
||||
|
||||
list<sfLma__License__c> licenseToUpdate = new list<sfLma__License__c>();
|
||||
// retrieve all licenses
|
||||
list<sfLma__License__c> allLicensesWithCustomer = [select id, sfLma__Account__c, COA_Customer__c, sfLma__Subscriber_Org_ID__c
|
||||
from sfLma__License__c
|
||||
where sfLma__Subscriber_Org_ID__c in :allCustomersWithOrgID.keyset()];
|
||||
|
||||
for (sfLma__License__c mylicense : allLicensesWithCustomer)
|
||||
{
|
||||
// assigne the right customer to the right license via orgid
|
||||
mylicense.COA_Customer__c = allCustomersWithOrgID.get(mylicense.sfLma__Subscriber_Org_ID__c);
|
||||
licenseToUpdate.add(mylicense);
|
||||
}
|
||||
|
||||
update licenseToUpdate;
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ApexTrigger xmlns="http://soap.sforce.com/2006/04/metadata">
|
||||
<apiVersion>61.0</apiVersion>
|
||||
<packageVersions>
|
||||
<majorNumber>3</majorNumber>
|
||||
<minorNumber>71</minorNumber>
|
||||
<namespace>CHANNEL_ORDERS</namespace>
|
||||
</packageVersions>
|
||||
<packageVersions>
|
||||
<majorNumber>1</majorNumber>
|
||||
<minorNumber>21</minorNumber>
|
||||
<namespace>sfLma</namespace>
|
||||
</packageVersions>
|
||||
<status>Active</status>
|
||||
</ApexTrigger>
|
||||
Reference in New Issue
Block a user