I am trying to update the AmoutMicros of Budget but I don't receive error, just not update the budget:
CampaignBudget budget = new CampaignBudget()
{
ResourceName = ResourceNames.CampaignBudget(customerId, budgetId),
AmountMicros = (price + amount) * 100000,
Id = budgetId
};
CampaignBudgetOperation budgetOperation = new CampaignBudgetOperation()
{
Create = budget,
UpdateMask = FieldMasks.AllSetFieldsOf(budget),
};
try
{
MutateCampaignBudgetsResponse responseBudget =
budgetService.MutateCampaignBudgets(
customerId.ToString(), new CampaignBudgetOperation[] { budgetOperation
});
foreach(MutateCampaignBudgetResult result in responseBudget.Results)
{
updateResponse.CampignId = campaignId;
updateResponse.Updated = true;
Console.WriteLine(result);
}
return updateResponse;
}
catch (GoogleAdsException e)
{
Console.WriteLine("Failure:");
Console.WriteLine($"Message: {e.Message}");
Console.WriteLine($"Failure: {e.Failure}");
Console.WriteLine($"Request ID: {e.RequestId}");
return updateResponse;
throw;
}
This code don't show me a exception, apparently it was update, but, when I go at Google Ads Dashboard, the amout still the same.
I read the documentation but I didn't find an update of a budget.
My working code is PHP but you can refer this.
private static function updateCampaignBudget(GoogleAdsClient $googleAdsClient, int $customerId,int $campaign_budget,string $budget_resource_name){
// Creates a campaign budget.
$budget = new CampaignBudget([
'resource_name' => $budget_resource_name,
//'delivery_method' => BudgetDeliveryMethod::STANDARD,
'amount_micros' => $campaign_budget
//'explicitly_shared' => false
]);
// Creates a campaign budget operation.
$campaignBudgetOperation = new CampaignBudgetOperation();
$campaignBudgetOperation->setUpdate($budget);
$campaignBudgetOperation->setUpdateMask(FieldMasks::allSetFieldsOf($budget));
// Issues a mutate request.
$campaignBudgetServiceClient = $googleAdsClient->getCampaignBudgetServiceClient();
$response = $campaignBudgetServiceClient->mutateCampaignBudgets(
$customerId,
[$campaignBudgetOperation]
);
/** #var CampaignBudget $addedBudget */
$updatedBudget = $response->getResults()[0];
//printf("Added budget named '%s'%s", $addedBudget->getResourceName(), PHP_EOL);
return $updatedBudget->getResourceName();
}
you can use ResourceNames::forCampaignBudget(customerId, budgetId) instead of $budget_resource_name
Related
Trying to make up a function that takes a list of redis keys, and outputs a list of timespans for the time to live (TTL) of the keys. I'm not familiar with Lua Scripting though. I've tried following other guides online for this, but am unable to get something to work for this situation. Any insight would be super helpful and very reusable.
public async Task<TimeSpan?[]> GetTTLManyAsync(string[] keySet)
{
try
{
var db = await this.GetDatabaseAsync();
string script = #"...";
...
var keysCasted = keySet.Select(k => new RedisKey(k)).ToArray();
var result = await db.ScriptEvaluateAsync(script, keysCasted);
...
return ...[array of timespans];
}
catch (Exception e)
{
WriteLogException(e);
return null;
}
}`
Here is a rough solution I worked out.
public async Task<List<TimeSpan?>> GetTTLManyAsync(IEnumerable<string> keys)
{
List<string> returnList = new List<string>();
try
{
var db = await this.GetDatabaseAsync();
string script = #"local result = {}
for i,key in ipairs(KEYS) do
local ttl = tonumber(redis.call('ttl', key))
result[i] = ttl
end
return result";
var result = await db.ScriptEvaluateAsync(script, keys.Select(k => new RedisKey(k)).ToArray());
var arrResult = ((double[])result).Select(ttl =>
{
if (ttl == -2) return default(TimeSpan?); // Key does not exist
else if (ttl == -1) return default(TimeSpan?); // No expiration set.
else return TimeSpan.FromSeconds(ttl);
}).ToList();
return arrResult;
}
catch (Exception e)
{
WriteLogException(e);
}
// Fill w/ empty values
return new List<TimeSpan?>(new TimeSpan?[keys.Count()]);
}
I am trying to PAUSE the Ads with the AdId and AdGroupID. I have successfully paused an AdGroup but i want to pause Ads individually. Is this possible on Adwords API. I tried the code below but It seems it only works on AdGroup level. Also checked the AdService but seems that there is no option to edit the Status.
I am using Ads.AdWords.v201809
Thanks in advance
public void googleEnableDisableAds(AdWordsUser user, long adGroupId, long AdID, AdGroupAdStatus AdStatus)
{
using (AdGroupAdService adGroupAdService =
(AdGroupAdService)user.GetService(AdWordsService.v201809.AdGroupAdService))
{
List<AdGroupAdOperation> operations = new List<AdGroupAdOperation>();
// Create the expanded text ad.
ExpandedTextAd expandedTextAd = new ExpandedTextAd
{
//CR[i].
id = AdID
};
AdGroupAd expandedTextAdGroupAd = new AdGroupAd
{
adGroupId = adGroupId,
ad = expandedTextAd,
// Optional: Set the status.
status = AdStatus
};
// Create the operation.
AdGroupAdOperation operation = new AdGroupAdOperation
{
#operator = Operator.SET,
operand = expandedTextAdGroupAd
};
operations.Add(operation);
AdGroupAdReturnValue retVal = null;
try
{
if (operations.Count > 0)
{
// Create the ads.
retVal = adGroupAdService.mutate(operations.ToArray());
// Display the results.
if (retVal != null && retVal.value != null)
{
foreach (AdGroupAd adGroupAd in retVal.value)
{
ExpandedTextAd newAd = adGroupAd.ad as ExpandedTextAd;
Console.WriteLine(
"Expanded text ad with ID '{0}' and headline '{1} - {2}' " +
"was added.", newAd.id, newAd.headlinePart1, newAd.headlinePart2);
//adGroupId
}
}
else
{
Console.WriteLine("No expanded text ads were created.");
}
}
adGroupAdService.Close();
}
catch (Exception e)
{
throw new System.ApplicationException("Failed to create expanded text ad.", e);
}
}
}
Here is an example from API docs https://developers.google.com/adwords/api/docs/samples/csharp/basic-operations#pause-an-ad
The key idea is to set status property to PAUSED
AdGroupAdStatus status = AdGroupAdStatus.PAUSED
I'm hoping someone can help me with this issue. I have two methods that insert a document into a Cosmos DB. One works each and every time I run it. The other gets as far as CreateDatabaseIfNotExistsAsync and kicks out of the method and returns to the calling method. The ItemReponse objects Status property says "WaitingForActivation".
I will say that this logic did work once and now (with no changes) it does not. Below is the code that dies. First the Unit test:
public void AddPerson()
{
var logger = Mock.Of<ILogger<Person>>();
var appset = Mock.Of<IAppSettings>();
appset.DatabaseName = "PersonsDB";
appset.ContainerName = "PersonsContainer";
appset.EndpointUrl = "https://localhost:8081";
appset.AuthorizationKey = "somesecretkey";
Person person = new Person()
{
id = Guid.NewGuid().ToString(),
Address_line_1 = "1932 Alakea St",
Address_line_2 = "",
Birth_Date = "2020-01-01",
Gender = "m",
Patient_First_Name = "John",
Patient_Last_Name = "Ridley",
Hospital_Code = "Queens Med",
Rec_ID = "1111111111",
VER_CRM_ID = "22222222",
VER_EMAIL = "JR#noemail.com",
};
PersonCosmos personCosmos = new PersonCosmos(logger, appset);
var myresult = personCosmos.PutPersonData(person);
Assert.True(myresult.Exception == null, "Row added");
}
Let me add that I am running the Cosmos Emulator hence the localhost url. Now for the code that dies.
public async Task<ItemResponse<Person>> PutPersonData(Person persondata)
{
this.cosmosClient = new CosmosClient(EndpointUri, PrimaryKey);
this.database = await this.cosmosClient.CreateDatabaseIfNotExistsAsync(DatabaseName);
this.container = await this.database.CreateContainerIfNotExistsAsync(ContainerName, "/Hospital_Code");
ItemResponse<Person> PutResponse = null;
try
{
// Read the item to see if it exists.
PutResponse = await this.container.ReadItemAsync<Person>(persondata.id.ToString(), new PartitionKey(persondata.Hospital_Code ));
return PutResponse;
}
catch (CosmosException ex) when (ex.StatusCode == HttpStatusCode.NotFound)
{
// Create an item in the container representing the Appointment. Note we provide the value of the partition key for this item, which is "Hospital_Code"
PutResponse = await this.container.CreateItemAsync<Person>(persondata, new PartitionKey(persondata.Hospital_Code));
return PutResponse;
}
catch (Exception ex)
{
// Create an item in the container representing the object. Note we provide the value of the partition key for this item, which is "Hospital_Code"
_logger.LogError($"Error in {0} at {1} " + ex.Message, System.Reflection.MethodBase.GetCurrentMethod().Name, DateTime.UtcNow.ToLongTimeString());
return PutResponse;
}
}
You are mixing sync and async in your code here.
Use await on this line.
var myresult = **await** personCosmos.PutPersonData(person);
and also this calling function should be async as well
public void AddPerson()
I am trying to update EmploymentEndDate in Contract in D365 Finance and Operation with oData using DataServiceCollection.
There is no error and it seems everything went well, but in the Contract EmploymentEndDate has no changes.
Similar code working well for other entities as Workers, Employee etc...
Has anyone experienced a similar situation, or to suggest other solution for this problem?
Thank You
public bool UpdateContractNG(string pPersonnelNumber, DateTime pEndEmploymentDate)
{
try
{
Resources _contextUpd = Queries365.CreateErpContext();
var queryUpd = from Employment
in _contextUpd.Employments
where Employment.PersonnelNumber == pPersonnelNumber
orderby Employment.EmploymentStartDate descending
select Employment;
DataServiceCollection<Employment> employmentCollection = new DataServiceCollection<Employment>(queryUpd);
if (employmentCollection != null)
{
foreach (Employment emp in employmentCollection)
{
Console.WriteLine($"OLD EMPLOYMENT: {JsonConvert.SerializeObject(emp)}");
emp.EmploymentEndDate = pEndEmploymentDate.ToUniversalTime();
_contextUpd.UpdateObject(emp);
Console.WriteLine($"IN MEMORY CHANGED EMPLOYMENT: {JsonConvert.SerializeObject(emp)}");
break;
}
}
DataServiceResponse response = _contextUpd.SaveChanges(SaveChangesOptions.PostOnlySetProperties);
// for testing (same context Check)
Employment emp2 = Queries365.GetContract(_contextUpd, pPersonnelNumber);
Console.WriteLine($"FROM SAME CONTEXT EMPLOYMENT: {JsonConvert.SerializeObject(emp2)}");
// new context refreshed data
Resources _newContext = Queries365.CreateErpContext();
Employment empAfterNew = Queries365.GetContract(_newContext, pPersonnelNumber);
Console.WriteLine($"AFTER UPDATE NEW CONTEXT: {JsonConvert.SerializeObject(empAfterNew)}");
return true;
}
catch (Exception ex)
{
Console.WriteLine($"Error updating contract with Id {pPersonnelNumber} with Exception: {ex} ");
return false;
}
}
public static Resources CreateErpContext()
{
// Resource
string ODataEntityPath = ClientConfiguration.Default.UriString + "data";
Uri oDataUri = new Uri(ODataEntityPath, UriKind.Absolute);
Resources context = new Resources(oDataUri);
context.SendingRequest2 += new EventHandler<SendingRequest2EventArgs>(delegate (object sender, SendingRequest2EventArgs e)
{
var authenticationHeader = OAuthHelper.GetAuthenticationHeader(useWebAppAuthentication: true);
e.RequestMessage.SetHeader(OAuthHelper.OAuthHeader, authenticationHeader);
});
return context;
}
public static Employment GetContract(Resources context, string personnelNumber)
{
Employment emp = context.Employments.Where(x => x.PersonnelNumber == personnelNumber)
.OrderByDescending(x => x.EmploymentStartDate).FirstOrDefault();
return emp;
}
The output line:
Console.WriteLine($"AFTER UPDATE NEW CONTEXT {JsonConvert.SerializeObject(empAfterNew)}");
returns unexpected value for end date: "EmploymentEndDate":"2019-12-31T23:00:00+00:00".
And it is not updated in the system D365 for Finance and Opereations
I have a scenario in CRM where I need to update existing accounts with their Vat and Registration number. There is well over 30 thousand accounts in the system. I am trying to update using the CRM SDK API but I am battling to figure out how to perform the actual update. The vat number and reg have been provided to me in a spreadsheet with their corresponding number, please note that the accounts are already in CRM so I just need to update the correct account with its Vat and Reg number, How can I do this in CRM, please advice on my code below:
public static void UpdateAllCRMAccountsWithVATAndRegistrationNumber(IOrganizationService service)
{
QueryExpression qe = new QueryExpression();
qe.EntityName = "account";
qe.ColumnSet = new ColumnSet("account", "new_vatno", "new_registrationnumber");
qe.Criteria.AddCondition("accountnumber", ConditionOperator.In,"TA10024846", "TA10028471", "TA20014015", "TA4011652", "TA4011557");
EntityCollection response = service.RetrieveMultiple(qe);
foreach (var acc in response.Entities)
{
acc.Attributes["new_vatno"] = //this is where I am struggling to figure out how I am gong to match the records up,
acc.Attributes["new_registrationnumber"] = //this is where I am struggling to figure out how I am gong to match the records up,
service.Update(acc);
}
}
How am I going to ensure that I update the correct records. I have the vat and reg numbers for the accounts in a spreadsheet, please see example image below. Can I please get advised here. Thanks.
I would load the list of VAT updates from the spreadsheet into a dictionary and then load the 30k record from CRM into memory. Then I would match them up and use ExecuteMultipleRequest to do the updates. Alternatively, you could query CRM using the account numbers (if the list is small enough.) I made the assumption you had thousands of updates to do across the record set of 30k. Note, if the Account record size was very large and couldn't be loaded into memory you would need to do account number queries.
Here is the rough code for the basic solution (I haven't tested, method should be split up, and there is minimal error handling):
public class VatInfo
{
public string RegistrationNumber;
public string TaxNumber;
public static Dictionary<string, VatInfo> GetVatList()
{
//TODO: Implement logic to load CSV file into a list. Dictionary key value should be Account Number
throw new NotImplementedException();
}
}
public class UpdateVatDemo
{
public const int maxBatchSize = 100;
public static void RunVatUpdate(IOrganizationService conn)
{
var vats = VatInfo.GetVatList();
var pagingQuery = new QueryExpression("account");
pagingQuery.ColumnSet = new ColumnSet("accountnumber");
Queue<Entity> allEnts = new Queue<Entity>();
while (true)
{
var results = conn.RetrieveMultiple(pagingQuery);
if (results.Entities != null && results.Entities.Any())
results.Entities.ToList().ForEach(allEnts.Enqueue);
if (!results.MoreRecords) break;
pagingQuery.PageInfo.PageNumber++;
pagingQuery.PageInfo.PagingCookie = results.PagingCookie;
}
ExecuteMultipleRequest emr = null;
while (allEnts.Any())
{
if (emr == null)
emr = new ExecuteMultipleRequest()
{
Settings = new ExecuteMultipleSettings()
{
ContinueOnError = true,
ReturnResponses = true
},
Requests = new OrganizationRequestCollection()
};
var ent = allEnts.Dequeue();
if (vats.ContainsKey(ent.GetAttributeValue<string>("accountnumber")))
{
var newEnt = new Entity("account", ent.Id);
newEnt.Attributes.Add("new_vatno", vats[ent.GetAttributeValue<string>("accountnumber")].TaxNumber);
newEnt.Attributes.Add("new_registrationnumber", vats[ent.GetAttributeValue<string>("accountnumber")].RegistrationNumber);
emr.Requests.Add(new UpdateRequest() { Target = newEnt });
}
if (emr.Requests.Count >= maxBatchSize)
{
try
{
var emResponse = (ExecuteMultipleResponse) conn.Execute(emr);
foreach (
var responseItem in emResponse.Responses.Where(responseItem => responseItem.Fault != null))
DisplayFault(emr.Requests[responseItem.RequestIndex],
responseItem.RequestIndex, responseItem.Fault);
}
catch (Exception ex)
{
Console.WriteLine($"Exception during ExecuteMultiple: {ex.Message}");
throw;
}
emr = null;
}
}
}
private static void DisplayFault(OrganizationRequest organizationRequest, int count,
OrganizationServiceFault organizationServiceFault)
{
Console.WriteLine(
"A fault occurred when processing {1} request, at index {0} in the request collection with a fault message: {2}",
count + 1,
organizationRequest.RequestName,
organizationServiceFault.Message);
}
}
Updating the fetched entity is bound to fail because of its entity state, which would not be null.
To update the fetched entities, you need to new up the entity:
foreach (var acc in response.Entities)
{
var updateAccount = new Entity("account") { Id = acc.Id };
updateAccount .Attributes["new_vatno"] = null; //using null as an example.
updateAccount .Attributes["new_registrationnumber"] = null;
service.Update(acc);
}
Code below shows how I managed to get it righy. forst let me explain. I imported my records into a seperate SQL table, in my code I read that table into a list in memory, I then query CRM accounts that need to be updated, I then loop though each account and check if the account number in CRM matches the account number from my sql database, if it matches, I then update the relevant Reg no and Vat no, See code below:
List<Sheet1_> crmAccountList = new List<Sheet1_>();
//var crmAccount = db.Sheet1_.Select(x => x).ToList().Take(2);
var crmAccounts = db.Sheet1_.Select(x => x).ToList();
foreach (var dbAccount in crmAccounts)
{
CRMDataObject modelObject = new CRMDataObject()
{
ID = dbAccount.ID,
Account_No = dbAccount.Account_No,
Tax_No = dbAccount.Tax_No.ToString(),
Reg_No = dbAccount.Reg_No
//Tarsus_Country = dbAccount.Main_Phone
};
}
var officialDatabaseList = crmAccounts;
foreach (var crmAcc in officialDatabaseList)
{
QueryExpression qe = new QueryExpression();
qe.EntityName = "account";
qe.ColumnSet = new ColumnSet("accountnumber", "new_vatno", "new_registrationnumber");
qe.Criteria.AddCondition("accountnumber", ConditionOperator.In,'list of account numbers go here'
EntityCollection response = service.RetrieveMultiple(qe);
foreach (var acc in response.Entities)
{
if (crmAcc.Account_No == acc.Attributes["accountnumber"].ToString())
{
//acc.Attributes["new_vatno"] = crmAcc.VAT_No.ToString();
acc.Attributes["new_registrationnumber"] = crmAcc.Reg_No.ToString();
service.Update(acc);
}
}
}