Skip to content

Commit

Permalink
Merge pull request dimagi#106 from tstalka/Domain_Snapshot
Browse files Browse the repository at this point in the history
248914: Monthly Domain Snapshots
  • Loading branch information
tstalka authored Mar 15, 2017
2 parents 9503a47 + e32967f commit 41745ba
Show file tree
Hide file tree
Showing 4 changed files with 224 additions and 0 deletions.
100 changes: 100 additions & 0 deletions src/classes/DomainMonthlySnapshotBatch.cls
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
public class DomainMonthlySnapshotBatch implements Database.Batchable<Accounting_Subscription__c>, Database.Stateful {

private Map<String, Decimal> wamMap;
private Map<String, Decimal> formsMap;
private Map<String, Decimal> mobileUsersMap;
private Map<String, Decimal> recordCountMap;
private Date currentDate;
private Boolean error;
private BatchDefaultSettings__c settings;

public DomainMonthlySnapshotBatch() {
this(Date.today());
}

public DomainMonthlySnapshotBatch(Date currentDate) {
this.currentDate = currentDate;
this.wamMap = new Map<String, Decimal>{ 'Empty' => 0, 'Advanced' => 0, 'Community' => 0, 'Enterprise' => 0, 'Standard' => 0, 'Pro' => 0};
this.formsMap = new Map<String, Decimal>{ 'Empty' => 0, 'Advanced' => 0, 'Community' => 0, 'Enterprise' => 0, 'Standard' => 0, 'Pro' => 0};
this.mobileUsersMap = new Map<String, Decimal>{ 'Empty' => 0, 'Advanced' => 0, 'Community' => 0, 'Enterprise' => 0, 'Standard' => 0, 'Pro' => 0};
this.recordCountMap = new Map<String, Decimal>{ 'Empty' => 0, 'Advanced' => 0, 'Community' => 0, 'Enterprise' => 0, 'Standard' => 0, 'Pro' => 0};
this.error = false;
this.settings = BatchDefaultSettings__c.getOrgDefaults();
}

public List<Accounting_Subscription__c> start(Database.BatchableContext context) { // We cannot group by formula field
return [SELECT Id, Software_Plan_Edition__c, Accounting_subscriber_domain__r.Wam__c, Accounting_subscriber_domain__r.cpActiveMobileUsers__c, service_type__c,
Accounting_subscriber_domain__r.cpAllForms__c, Accounting_subscriber_domain__r.InternalProp_self_started__c FROM Accounting_Subscription__c
WHERE is_trial__c = false AND is_active__c = true AND Accounting_subscriber_domain__c != null AND
Accounting_subscriber_domain__r.Likely_Real__c = true AND Accounting_subscriber_domain__r.is_test__c != 'true' AND
Accounting_subscriber_domain__r.cpIsActive__c = true];
}

public void execute(Database.BatchableContext context, List<Accounting_Subscription__c> scope) {
try {
for (Accounting_Subscription__c sub : scope) {
String softwarePlan = sub.Software_Plan_Edition__c;
if (softwarePlan == '' || softwarePlan == null || softwarePlan == '-') {
softwarePlan = 'Empty';
}

this.wamMap.put(softwarePlan, wamMap.get(softwarePlan) + sub.Accounting_subscriber_domain__r.Wam__c);
this.formsMap.put(softwarePlan, formsMap.get(softwarePlan) + sub.Accounting_subscriber_domain__r.cpAllForms__c);
this.mobileUsersMap.put(softwarePlan, mobileUsersMap.get(softwarePlan) + sub.Accounting_subscriber_domain__r.cpActiveMobileUsers__c);
if ((sub.service_type__c == 'Self_service' || sub.service_type__c == 'Product') && sub.Accounting_subscriber_domain__r.InternalProp_self_started__c == true) {
this.recordCountMap.put(softwarePlan, recordCountMap.get(softwarePlan) + 1);
}
}
} catch (Exception e) {
System.debug('Error: ' + e);
if (!Test.isRunningTest()) {
EmailHelper.sendEmailFromException(this.settings.Error_Emails__c.split(','), 'Cannot calculate monthy Domain Snapshots',
'Error : ', e);
}
throw e; // we want stop calculations and fix problems
}
}

public void finish(Database.BatchableContext context) {
try {
if (error == false) {
SObject sobj = (SObject) new Domain_Monthly_Snapshot__c();
sobj = setValues(sobj, wamMap, '_Wam__c');
sobj = setValues(sobj, formsMap, '_Forms__c');
sobj = setValues(sobj, mobileUsersMap, '_Active_Mobile_Users__c');
sobj = setValues(sobj, recordCountMap, '_Scale_of_Programs__c');
Domain_Monthly_Snapshot__c domainSnapshot = (Domain_Monthly_Snapshot__c) sobj;
domainSnapshot.Snapshot_Date__c = this.currentDate;
insert domainSnapshot;
}
} catch (Exception e) {
System.debug('Error: ' + e);
if (!Test.isRunningTest()) {
EmailHelper.sendEmailFromException(this.settings.Error_Emails__c.split(','), 'Cannot calculate monthy Domain Snapshots',
'Error : ', e);
}
}
}

private SObject setValues(SObject obj, Map<String, Decimal> values, String suffix) {

for (String key : values.keySet()) {
String name = (key + suffix).toLowerCase();
Decimal value = values.get(key);
if (hasSObjectField(name, obj)) {
obj.put(name, value);
} else {
System.debug('Cannot find field with name : ' + name);
if (!Test.isRunningTest()) {
EmailHelper.sendEmail(this.settings.Error_Emails__c.split(','), 'Cannot find sObject field for Domain Monthly Snapshot',
'Cannot find fields: ' + name);
}
}
}
return obj;
}

private Boolean hasSObjectField(String fieldName, SObject so) {
return so.getSobjectType().getDescribe().fields.getMap().keySet().contains(fieldName);
}
}
5 changes: 5 additions & 0 deletions src/classes/DomainMonthlySnapshotBatch.cls-meta.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<ApexClass xmlns="http://soap.sforce.com/2006/04/metadata">
<apiVersion>36.0</apiVersion>
<status>Active</status>
</ApexClass>
113 changes: 113 additions & 0 deletions src/classes/HqIntegrationTests.cls
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,118 @@ public class HqIntegrationTests {
insert testCustomSetting;
}

@isTest
static void shouldCreateDomainMonthlySnapshot() {
Accounting_SoftwareProductRate__c productRate1 = new Accounting_SoftwareProductRate__c(is_active__c = true, monthly_fee__c = 150, Server_Name__c = 'CommCare HQ');
Accounting_SoftwareProductRate__c productRate2 = new Accounting_SoftwareProductRate__c(is_active__c = true, monthly_fee__c = 75, Server_Name__c = 'CommCare HQ');
Accounting_SoftwareProductRate__c productRate3 = new Accounting_SoftwareProductRate__c(is_active__c = true, monthly_fee__c = 25, Server_Name__c = 'CommCare HQ');

insert productRate1;
insert productRate2;
insert productRate3;

Accounting_Softwareplan__c softwarePlan1 = new Accounting_Softwareplan__c(Name = 'softwarePlan1', edition__c = 'Community', Server_Name__c = 'CommCare HQ');
Accounting_Softwareplan__c softwarePlan2 = new Accounting_Softwareplan__c(Name = 'softwarePlan2', edition__c = 'Standard', Server_Name__c = 'CommCare HQ');
Accounting_Softwareplan__c softwarePlan3 = new Accounting_Softwareplan__c(Name = 'softwarePlan3', edition__c = 'Pro', Server_Name__c = 'CommCare HQ');

insert softwarePlan1;
insert softwarePlan2;
insert softwarePlan3;

Accounting_SoftwarePlanVersion__c planVersion1 = new Accounting_SoftwarePlanVersion__c(is_active__c = true, Software_Product_Rate__c = productRate1.Id,
Accounting_SoftwarePlan__c = softwarePlan1.Id, Server_Name__c = 'CommCare HQ');
Accounting_SoftwarePlanVersion__c planVersion2 = new Accounting_SoftwarePlanVersion__c(is_active__c = true, Software_Product_Rate__c = productRate2.Id,
Accounting_SoftwarePlan__c = softwarePlan2.Id, Server_Name__c = 'CommCare HQ');
Accounting_SoftwarePlanVersion__c planVersion3 = new Accounting_SoftwarePlanVersion__c(is_active__c = true, Software_Product_Rate__c = productRate3.Id,
Accounting_SoftwarePlan__c = softwarePlan3.Id, Server_Name__c = 'CommCare HQ');

insert planVersion1;
insert planVersion2;
insert planVersion3;

Internal_Properties__c InternalPropRec1 = new Internal_Properties__c(self_started__c = true, Server_Name__c = 'CommCare HQ');
Internal_Properties__c InternalPropRec2 = new Internal_Properties__c(self_started__c = true, Server_Name__c = 'CommCare HQ');
Internal_Properties__c InternalPropRec3 = new Internal_Properties__c(self_started__c = true, Server_Name__c = 'CommCare HQ');
Internal_Properties__c InternalPropRec4 = new Internal_Properties__c(self_started__c = true, Server_Name__c = 'CommCare HQ');
Internal_Properties__c InternalPropRec5 = new Internal_Properties__c(self_started__c = true, Server_Name__c = 'CommCare HQ');

insert InternalPropRec1;
insert InternalPropRec2;
insert InternalPropRec3;
insert InternalPropRec4;
insert InternalPropRec5;

Domain__c domain1 = new Domain__c(Name = 'Sample 1', Server_Name__c = 'CommCare HQ', is_test__c = 'false', cpIsActive__c = true,
Wam__c = 15, cpActiveMobileUsers__c = 20, cpAllForms__c = 325, Internal_Properties__c = InternalPropRec1.Id);
Domain__c domain2 = new Domain__c(Name = 'Sample 2', Server_Name__c = 'CommCare HQ', is_test__c = 'false', cpIsActive__c = true,
Wam__c = 30, cpActiveMobileUsers__c = 35, cpAllForms__c = 340, Internal_Properties__c = InternalPropRec2.Id);
Domain__c domain3 = new Domain__c(Name = 'Sample 3', Server_Name__c = 'CommCare HQ', is_test__c = 'false', cpIsActive__c = true,
Wam__c = 45, cpActiveMobileUsers__c = 50, cpAllForms__c = 355, Internal_Properties__c = InternalPropRec3.Id);
Domain__c domain4 = new Domain__c(Name = 'Sample 4', Server_Name__c = 'CommCare HQ', is_test__c = 'false', cpIsActive__c = true,
Wam__c = 60, cpActiveMobileUsers__c = 65, cpAllForms__c = 370, Internal_Properties__c = InternalPropRec4.Id);
Domain__c domain5 = new Domain__c(Name = 'Sample 5', Server_Name__c = 'CommCare HQ', is_test__c = 'false', cpIsActive__c = true,
Wam__c = 75, cpActiveMobileUsers__c = 80, cpAllForms__c = 385, Internal_Properties__c = InternalPropRec5.Id);

insert domain1;
insert domain2;
insert domain3;
insert domain4;
insert domain5;

Accounting_Subscription__c subscription1 = new Accounting_Subscription__c(date_start__c = Date.newInstance(2015, 11, 2), date_end__c = Date.newInstance(2016, 2 ,1), is_active__c = true,
Accounting_subscriber_domain__c = domain1.Id, plan_version__c = planVersion1.Id, Server_Name__c = 'CommCare HQ',
is_trial__c = false, service_type__c = 'Self_service');
insert subscription1;
Accounting_Subscription__c subscription2 = new Accounting_Subscription__c(date_start__c = Date.newInstance(2016, 1, 1), date_end__c = Date.newInstance(2016, 2 ,1), is_active__c = true,
Accounting_subscriber_domain__c = domain2.Id, plan_version__c = planVersion2.Id, Server_Name__c = 'CommCare HQ',
is_trial__c = false, service_type__c = 'Product');
insert subscription2;
Accounting_Subscription__c subscription3 = new Accounting_Subscription__c(date_start__c = Date.newInstance(2014, 1, 1), date_end__c = Date.newInstance(2014, 3 ,4), is_active__c = true,
Accounting_subscriber_domain__c = domain3.Id, plan_version__c = planVersion3.Id, Server_Name__c = 'CommCare HQ',
is_trial__c = false, service_type__c = 'Self_service');
insert subscription3;
Accounting_Subscription__c subscription4 = new Accounting_Subscription__c(date_start__c = Date.newInstance(2016, 1, 1), date_end__c = Date.newInstance(2016, 2 ,1), is_active__c = true,
Accounting_subscriber_domain__c = domain4.Id, plan_version__c = planVersion1.Id, Server_Name__c = 'CommCare HQ',
is_trial__c = false, service_type__c = 'Self_service');
insert subscription4;
Accounting_Subscription__c subscription5 = new Accounting_Subscription__c(date_start__c = Date.newInstance(2016, 1, 1), date_end__c = Date.newInstance(2016, 2 ,1), is_active__c = true,
Accounting_subscriber_domain__c = domain5.Id, plan_version__c = planVersion2.Id, Server_Name__c = 'CommCare HQ',
is_trial__c = false, service_type__c = 'Product');
insert subscription5;

Test.startTest();
Database.executeBatch(new DomainMonthlySnapshotBatch());
Test.stopTest();

Domain_Monthly_Snapshot__c domainSn = [SELECT Advanced_Active_Mobile_Users__c, Advanced_Forms__c, Advanced_Wam__c,
Community_Active_Mobile_Users__c, Community_Forms__c, Community_Wam__c,
Empty_Active_Mobile_Users__c, Empty_Forms__c, Empty_Wam__c,
Enterprise_Active_Mobile_Users__c, Enterprise_Forms__c, Enterprise_Wam__c,
Pro_Active_Mobile_Users__c, Pro_Forms__c, Pro_Wam__c,
Standard_Active_Mobile_Users__c, Standard_Forms__c, Standard_Wam__c, Snapshot_Date__c,
Pro_Scale_of_Programs__c, Community_Scale_of_Programs__c, Standard_Scale_of_Programs__c
FROM Domain_Monthly_Snapshot__c LIMIT 1];

// Community => subscription1 AND subscription4 => Wam = 15 + 60 = 75, Mobile Users = 20 + 65 = 85, Forms = 325 + 370 = 695
// Standard => subscription1 AND subscription4 => Wam = 30 + 75 = 105, Mobile Users = 35 + 80 = 115, Forms = 340 + 385 = 725
// Pro => subscription1 AND subscription4 => Wam = 45, Mobile Users = 50, Forms = 355

System.assertEquals(75, domainSn.Community_Wam__c);
System.assertEquals(85, domainSn.Community_Active_Mobile_Users__c);
System.assertEquals(695, domainSn.Community_Forms__c);
System.assertEquals(2, domainSn.Community_Scale_of_Programs__c);

System.assertEquals(105, domainSn.Standard_Wam__c);
System.assertEquals(115, domainSn.Standard_Active_Mobile_Users__c);
System.assertEquals(725, domainSn.Standard_Forms__c);
System.assertEquals(2, domainSn.Standard_Scale_of_Programs__c);

System.assertEquals(45, domainSn.Pro_Wam__c);
System.assertEquals(50, domainSn.Pro_Active_Mobile_Users__c);
System.assertEquals(355, domainSn.Pro_Forms__c);
System.assertEquals(1, domainSn.Pro_Scale_of_Programs__c);
}

@isTest
static void shouldCalculateWAM() {
hqInt_Model_DomainClass d1 = new hqInt_Model_DomainClass();
Expand Down Expand Up @@ -942,6 +1054,7 @@ public class HqIntegrationTests {
cAdj = [SELECT id__c, amount__c FROM Accounting_CreditAdjustment__c WHERE id__c = '3'];
System.assertEquals(-500, cAdj.amount__c);
}

/**
@isTest
static void hqIntShouldUpdateMissingRelationsInSubscriberCustomObject() {
Expand Down
6 changes: 6 additions & 0 deletions src/classes/PROContractSnapshotScheduled.cls
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,11 @@ global class PROContractSnapshotScheduled implements Schedulable {
PROContractSnapshotBatch proContractSnapshotBatch = new PROContractSnapshotBatch();
database.executeBatch(proContractSnapshotBatch, 50);
}

Integer numberOfDays = Date.daysInMonth(currentDate.year(), currentDate.month());
Date lastDayOfMonth = Date.newInstance(currentDate.year(), currentDate.month(), numberOfDays);
if (currentDate.isSameDay(lastDayOfMonth)) {
Database.executeBatch(new DomainMonthlySnapshotBatch());
}
}
}

0 comments on commit 41745ba

Please sign in to comment.