Batch Class Add contact to Account - batch-processing

I have created 20 records with the 'name=SampleAccountOne'. I am trying to create a batch class that will add a given contact to the 20 records. Stuck with syntax and where to go. Any help in the right direction is greatly appreciated.
global class UpdateProjectNameBatch implementsDatabase.Batchable<sObject> {
List<Contact> conList = new conList<Contact>();
String query = 'Select Id,Name FROM Account WHERE Name = \'SampleAccountOne\''
global Database.QueryLocator start(Database.BatchableContext bc){
return Database.getQueryLocator(query);
}
global void execute(Database.BatchableContext bc,List<sObject> batch){
for(Contact c : conList){
batch.c = 'New Contact Name';
}
}
global void finish(){
}
}

I believe you are trying to associate a single contact to multiple accounts. This functionality was released in Spring 16' and is implemented through a Salesforce Junction object - AccountContactRelation.
I assume you have already enabled this functionality through the UI and a parent Account is declared for this Contact.
I have modified your code to associate the contact to all 20 account.
global class UpdateProjectNameBatch implements Database.Batchable
<sObject>
{ ID conId = '0037F00000IfCCKQA3'; //Add the contact Id here
List<AccountContactRelation> ListInsertion = new List<AccountContactRelation>();
String query = 'Select Id,Name FROM Account WHERE Name = \'SampleAccountOne\'';
global Database.QueryLocator start(Database.BatchableContext bc)
{
return Database.getQueryLocator(query);
}
global void execute(Database.BatchableContext bc,List<Account> batch){
for (Account a : batch)
{
AccountContactRelation c = new AccountContactRelation();
c.AccountId = a.id;
c.contactId = conId;
ListInsertion.add(c);
}
Insert ListInsertion;
}
global void finish(Database.BatchableContext bc)
{
//DoNothing.
}
}

Related

Error in apex test logs: common.apex.runtime.impl.ExecutionException: List has no rows for assignment to SObject"

Here is what i tried. I think the problem is somewhere in the test class when i create the apex test controller and i want to link the record of the controller to the solution that i created in the test class.
This is the error that i found in logs:
"common.apex.runtime.impl.ExecutionException: List has no rows for assignment to SObject"|0x4888dd3c
apex class:
public with sharing class SolutionWrapper {
public ApexPages.StandardSetController controller;
public Opportunity opp{get; set;}
public Solutions__c oppId{get; set;}
public Solutions__c sol{get; set;}
public Solutions__c solution{get; set;}
public Account acc{get; set;}
public SolutionWrapper(ApexPages.StandardSetController controller) {
try{
solution = new Solutions__c();
solution = (Solutions__c)controller.getRecord();
if(solution.Id != null){
oppId = [SELECT id, Solutions__c.Opportunity__c
FROM Solutions__c
WHERE id =: solution.Id
LIMIT 1];
opp = [Select id,Name, AccountId, CurrencyIsoCode from
Opportunity where id =: oppId.Opportunity__c LIMIT:1];
}
if(opp.id !=null){
sol = [SELECT id,Name, Mail_Merge_Id__c,Solution_Country__c, Solutions__c.Opportunity__c
FROM Solutions__c
WHERE Solutions__c.Opportunity__c =: opp.id
LIMIT 1];
acc = [Select id,Name,Country__c from
Account where id=:opp.AccountId LIMIT: 1];
}
}
catch(Exception e){
ApexPages.addMessage(new ApexPages.message(ApexPages.Severity.ERROR,e.getMessage()));
}
}
}
Here is my test class
apex test class:
#isTest
public class SolutionWrapperTest {
static testMethod void testMethodOpp(){
Account acc = new Account(Name='test', Country__c='test');
insert acc;
Opportunity opp = new Opportunity(Name='test', AccountId=acc.id, CurrencyIsoCode='GBP', StageName = 'Good',
CloseDate = date.today());
insert opp;
Solutions__c sol = new Solutions__c( Opportunity__c= opp.id, CurrencyIsoCode='GBP');
insert sol;
List<Solutions__c> listSol = new List<Solutions__c>();
listSol.add(sol);
PageReference pageRef = Page.NewVisualForcePage;
Test.setCurrentPage(pageRef);
Test.startTest();
ApexPages.StandardSetController stdController = new ApexPages.StandardSetController(listSol);
SolutionWrapper testSolution = new SolutionWrapper(stdController);
Test.stopTest();
}
}
Solution id is different from the one that i inserted in the test class. I inserted a dummy value (eq 'test') on a field like Currency. After that i selected from the db based on Currency instead of id.

Why do I receive an error when I consult data in my Micronaut Gorm application?

I have a simple application in Mironaut with three entities, Customer, Contact and Loans.
Customer has a 1 to many relationship with Contact and Loans. I test with Grails / Gorm and it works fine.
I have a DataLoader class that works well and creates all entities with their relationships.
/****** Contact.groovy *******/
package com.gnc.demo.domain
import grails.gorm.annotation.Entity
#Entity
class Contact {
Long id
Long version
Customer customer
static belongsTo = Customer
String email
String phone
String cellPhone
String address
}
/****** Customer.groovy *******/
package com.gnc.demo.domain
import grails.gorm.annotation.Entity
#Entity
class Customer {
Long id
Long version
String driverId
String name
String lastName
static hasMany = [contacts: Contact, loans: Loan]
static constraints = {
contacts nullable: true
loans nullable: true
}
static mapping = {
contacts lazy: false
loans lazy: false
}
}
/****** Loan.groovy *******/
package com.gnc.demo.domain
import grails.gorm.annotation.Entity
#Entity
class Loan {
Long id
Long version
Customer customer
static belongsTo = Customer
BigDecimal amount
long term
BigDecimal rate
}
/******* CustomerController.groovy *******/
package com.gnc.demo.controllers
import com.gnc.demo.domain.Customer
import com.gnc.demo.services.ContactService
import com.gnc.demo.services.CustomerService
import com.gnc.demo.services.LoanService
import io.micronaut.http.annotation.Controller
import io.micronaut.http.annotation.Get
import org.slf4j.Logger
import org.slf4j.LoggerFactory
#Controller("/customer")
class CustomerController {
private static final Logger LOG = LoggerFactory.getLogger(CustomerController.class);
final CustomerService customerService
final LoanService loanService
final ContactService contactService
CustomerController(CustomerService customerService, LoanService loanService, ContactService contactService) {
this.customerService = customerService
this.loanService = loanService
this.contactService = contactService
}
#Get("/")
String index() {
return "Hola ! " + new Date()
}
#Get("/all/{offset}/{max}")
List<Customer> getCustomers(String offset, String max) {
List<Customer> customers = customerService.findAll([offset: offset, max: max])
try {
customers.each { customer ->
// LOG.info(">>> Loans :" +customer.loans.size())
customer.contacts = []
customer.loans = []
}
} catch (Exception e) {
LOG.info(">>> Error :" + e)
}
return customers
}
#Get("/{id}")
Customer getCustomers(String id) {
Customer customer = customerService.get(id)
customer?.contacts = []
customer?.loans = []
customer?.contacts = contactService.findAllByCustomer(customer)
customer?.loans = loanService.findAllByCustomer(customer)
return customer
}
}
All the code is available in: https://github.com/gnpitty/com-gnc-demo
But when I test in Micronaut with my browser: http://localhost:9020/customer/10
I receive this error:
{"message":"Internal Server Error: Error encoding object
[com.gnc.demo.domain.Customer : 10] to JSON: could not initialize proxy - no
Session (through reference chain: com.gnc.demo.domain.Customer[\"contacts\"]-
>java.util.LinkedHashSet[0]->com.gnc.demo.domain.Contact[\"customer\"]-
>com.gnc.demo.domain.Customer_$$_jvst110_0[\"driverId\"])"}
As one comment said, you should make sure the #Transactional or withTransaction {} is used when reading the record.
Also, if you want to reference the proxy elements (like the Customer reference), you need to force the proxy element to be read. I know of two ways: 1) do an eager fetch on them or 2) resolve the proxy explicitly.
I chose option 2) since I did not want to force eager fetching when it wasn't needed. I only use this in controllers where I am return a JSON encoded domain object. This is usually just in my REST API methods.
Example:
Loan.withTransaction {
def loan = Loan.findByXYZ()
resolveProxies(loan)
}
This converts the proxies into real objects so you can access them outside of the withTransaction{} closure. This usually is Jackson converting them to JSON.
I use this method to resolve any proxies in lists or as simple references to another domain object:
/**
* Resolves all proxies for the given domain class. This allows the domain to be used outside of an hibernate session
* if needed. This will check all fields and sub-objects for proxies.
* <p>
* <b>Note:</b> This will usually force a read of all referenced objects.
* #param object The object.
*/
def resolveProxies(Object object) {
if (object == null) {
return
}
for (property in object.class.gormPersistentEntity.persistentProperties) {
def value = object[property.name]
if (Collection.isAssignableFrom(property.type) && value) {
for (item in value) {
if (item != null) {
// Resolved any sub-objects too.
resolveProxies(item)
}
}
} else if (value instanceof HibernateProxy) {
// A simple reference, so unproxy it the GORM way.
object[property.name] = value.getClass().get(value.id)
}
}
}
Feel free to use this code anywhere you need it.

Seed method doesn't update database second time after editing it. What to do?

I create web app using ASP.Net Core 2.1 MVC. To add initial data to some tables (for ex. categories) I wrote Seed method and added Migration and updated database successfully (with no errors). Data (with all values added) was seen in the database (SQL Server) after running application. Then I added some other categories in the seed method. This time I didn't see changes (updates) in SQL server after running application and updating database using migration.
Does Seed work only first time or I can somehow update (increase initial data) the database using Seed?
This is my Seed method:
public static void Seed(OfferDbContext offerDbContext)
{
if (!offerDbContext.Categories.Any())
{
Category avto = new Category()
{
Name = "Avto"
};
Category home = new Category()
{
Name = "Ev"
};
Category digital = new Category()
{
Name = "Digital"
};
Category household = new Category()
{
Name = "Məişət"
};
Category entertainment = new Category()
{
Name = "Əyləncə"
};
Category furniture = new Category()
{
Name = "Mebel"
};
Category clothes = new Category()
{
Name = "Geyim"
};
Category cafe = new Category()
{
Name = "Kafe"
};
Category food = new Category()
{
Name = "Qida"
};
Category edu = new Category()
{
Name = "Təhsil"
};
Category medical = new Category()
{
Name = "Tibb"
};
Category tourism = new Category()
{
Name = "turizm"
};
offerDbContext.Categories.AddRange(avto, home, digital, household, entertainment, furniture, clothes, cafe, food, edu, medical, tourism);
offerDbContext.SaveChanges();
}
}
And Main method in Program.cs where I call that Seed:
public static void Main(string[] args)
{
IWebHost webHost = CreateWebHostBuilder(args).Build();
using (IServiceScope serviceScope = webHost.Services.CreateScope())
{
using(OfferDbContext offerDbContext = serviceScope.ServiceProvider.GetRequiredService<OfferDbContext>())
{
OfferDb.Seed(offerDbContext);
}
}
webHost.Run();
}
I would think that the issue is with the below line
if (!offerDbContext.Categories.Any())
Basically it says if there are no categories then do the adds, there is no else so if there are already categories there it will do nothing.
So maybe throw an else in and if there are already categories just add the new ones,
OR
Potentially you could wrap each of the creates in an if to see if it already exists and if it does not then crate it.

not able to create constructor of model class and getting object reference not set to instance of object error

this is my Model:
public class UserDetails
{
public string UserName { get; set; }
public virtual Category Category { get; set; }
}
this is my query to fetch user details along with category:
var data = (from temp in context.UserDetails.Include("Category") select temp).OrderBy(c => c.UserId);
this is how i am accessing on controller:
List<UserDetails> staffDetails = staffBal.fetchStaffDetails();
var categoryModel = new CategoryModel();
Data = staffDetails.Select(x =>
{
var userDetailModel = new UserDetailsModel();
userDetailModel.UserId = x.UserId;
userDetailModel.FName = x.FName;
categoryModel.CategoryName = x.Category.Name;//i am getting error on this line.object reference not set to instance of object
can anybody tell me what is the solution???
You say in your comment: for some records it is coming null for some records it is not null meaning that x.Category is null. Therefore, any attempt to access x.Category.Name will fail. Change the line to this:
categoryModel.CategoryName = x.Category == null ? "" : x.Category.Name;

Create a test method to a class - Force.com

Can anyone help me to create a test method for the following class. The basic idea of this code is to clone a patent with all child elements and just change the date.
public class NovoDia {
//added an instance varaible for the standard controller
private ApexPages.StandardController controller {get; set;}
// add the instance for the variables being passed by id on the url
private Itinerario_Diario__c po {get;set;}
private Itinerario_Diario__c pi {get;set;}
// set the id of the record that is created -- ONLY USED BY THE TEST CLASS
public ID newRecordId {get;set;}
// initialize the controller
public NovoDia(ApexPages.StandardController controller) {
//initialize the stanrdard controller
this.controller = controller;
// load the current record
po = (Itinerario_Diario__c)controller.getRecord();
}
// method called from the VF's action attribute to clone the po
public PageReference cloneWithItems() {
// setup the save point for rollback
Savepoint sp = Database.setSavepoint();
Itinerario_Diario__c newPO;
try {
//copy the purchase order - ONLY INCLUDE THE FIELDS YOU WANT TO CLONE
po = [select Dia__c from Itinerario_Diario__c where id = :po.id];
newPO = po.clone(false);
insert newPO;
// set the id of the new po created for testing
newRecordId = newPO.id;
// copy over the line items - ONLY INCLUDE THE FIELDS YOU WANT TO CLONE
List<Viagem__c> items = new List<Viagem__c>();
//PI.Dia__c = PO.Dia__c;
for (Viagem__c pi : [Select Cliente__c,Inicio_planejado__c,Entrada_Sa_da_de_Turno__c,Meio_de_Solicitacao__c,Motorista__c,Rota__c,Tipo_de_Viagem__c,Turno__c,Veiculo__c From Viagem__c p where Itinerario_Diario__c = :po.id ]) {
Viagem__c newPI = pi.clone(false);
newPI.Itinerario_Diario__c = newPO.id;
//newPI.Dia__c = PO.Dia__c;
items.add(newPI);
}
insert items;
} catch (Exception e){
// roll everything back in case of error
Database.rollback(sp);
ApexPages.addMessages(e);
return null;
}
return new PageReference('/'+newPO.id+'/e?retURL=%2F'+newPO.id);
}
I really appreciate the help.
Thanks
Sylvio
static testmethod void NovoDia_Test(){
Itinerario_Diario__c itinerarioDiario= new Itinerario_Diario__c();
insert itinerarioDiario;
ApexPages.StandardController sc = new ApexPages.StandardController(itinerarioDiario);
NovoDia cttr = new NovoDia (sc);
cttr.cloneWithItems();
}