How to override SO shipping address - acumatica

I attempt to override the SO Shipping address, in the SO entry graph extension. In this case, no additional locations are necessary. Here is my attempt & code, but no success.
SOAddress soAddr = new SOAddress();
soAddr.AddressID = null;
soAddr.CustomerID = 12345; //random customer BAccount ID
soAddr = Base.Shipping_Address.Insert(soAddr);
soAddr.OverrideAddress = true;
soAddr.IsDefaultAddress = false;
soAddr.Address1 = "123 Main Street";
//continue remaining address fields
Base.Shipping_Address.Update(soAddr);
Base.Actions.PressSave();
Unfortunately the Shipping address is pulled from the Location record, and no Override happens.
I am grateful for assistance.

Try this.
SOShippingAddress address = Base.Shipping_Address.Current = Base.Shipping_Address.Select();
address.OverrideAddress = true;
address = Base.Shipping_Address.Update(address);
if (address == null)
{
address = Base.Shipping_Address.Current;
}
address.AddressLine1 = "201 Lower Notch Rd";
address.AddressLine2 = "Office Suite 1936";
address.City = "Little Falls";
address.CountryID = "US";
address = Base.Shipping_Address.Update(address);
address.State = "NJ";
address.PostalCode = "07425";
Base.Shipping_Address.Update(address);
Base.Actions.PressSave();

Related

Creating Customer Location from Sales Order Screen

I want to create Customer Location from Sales Order Ship to Contact and Address. The following code works fine when order is saved and a new location is created.
The problem is: After I created a new order with order type “SO” and save the location, I go back to the Order Entry point screen, then click add new order. In new order screen, I select order type “QT” and select the same customer, the ADDRESS tab info are all blank. If I click save button, I got the error message “Error: ‘CustomerID’cannot be empty”. It seems the Customer is not selected. I have to select Customer again.
This only happens when location is saved, and create a new order with different order type and same customer. If I don't go back to the Order Entry point screen, and click + from Sales Order screen directly, it works fine.
namespace PX.Objects.SO
{
// Acuminator disable once PX1016 ExtensionDoesNotDeclareIsActiveMethod extension should be constantly active
public class SOOrderEntry_CBIZExtension : PXGraphExtension<PX.Objects.SO.SOOrderEntry>
{
#region Event Handlers
public delegate void PersistDelegate();
[PXOverride]
public void Persist(PersistDelegate baseMethod)
{
SOShippingContact shippingContact = Base.Shipping_Contact.Select();
SOShippingAddress shippingAddress = Base.Shipping_Address.Select();
SOOrder order = Base.CurrentDocument.Select();
SOOrderExt orderExt = order.GetExtension<SOOrderExt>();
if (orderExt != null && orderExt.UsrSaveLocation == true
&& !(string.IsNullOrEmpty(shippingContact.FullName)))
{
// get LOCATION segment length
Segment seg = SelectFrom<Segment>.Where<Segment.dimensionID.IsEqual<#P.AsString>>.View.
SelectSingleBound(Base, null, "LOCATION");
int locationLength = 10;
if (seg != null)
locationLength = seg.Length.Value;
// Get Location Name
string[] nameList = shippingContact.FullName.Split(' ');
string locationFirstName = nameList[0];
if (locationFirstName.Length > locationLength)
locationFirstName = locationFirstName.Substring(0, locationLength);
// Check if Customer location already exist
Location location = SelectFrom<Location>.Where<Location.bAccountID.IsEqual<#P.AsInt>.
And<Location.locationCD.IsEqual<#P.AsString>>>.View.
SelectSingleBound(Base, null, Base.Document.Current.CustomerID, locationFirstName);
if (location == null)
{
// New Customer location
// Create Location Instance
LocationMaint locationMaint = PXGraph.CreateInstance<CustomerLocationMaint>();
var loc = (Location) locationMaint.Location.Cache.CreateInstance();
loc.BAccountID = Base.Document.Current.CustomerID;
locationMaint.Location.Cache.SetValueExt<Location.locationCD>(loc, locationFirstName);
loc.LocType = LocTypeList.CustomerLoc;
loc = locationMaint.Location.Insert(loc);
loc.Descr = shippingContact.FullName;
loc = locationMaint.Location.Update(loc);
if (shippingContact.OverrideContact == true)
{
loc.OverrideContact = true;
loc = locationMaint.Location.Update(loc);
string firstName = nameList[0];
string lastName = "";
if (nameList.Length > 1)
lastName = nameList[1];
Contact cont = locationMaint.Contact.Current;
cont.FullName = shippingContact.FullName;
cont.FirstName = firstName;
cont.LastName = lastName;
cont.Attention = shippingContact.Attention;
cont.Phone1 = shippingContact.Phone1;
cont.Phone1Type = shippingContact.Phone1Type;
cont.EMail = shippingContact.Email;
cont = locationMaint.Contact.Update(cont);
}
if (shippingAddress.OverrideAddress == true)
{
loc.OverrideAddress = true;
loc = locationMaint.Location.Update(loc);
var addr = locationMaint.Address.Current;
addr.AddressLine1 = shippingAddress.AddressLine1;
addr.AddressLine2 = shippingAddress.AddressLine2;
addr.City = shippingAddress.City;
addr.CountryID = shippingAddress.CountryID;
addr.State = shippingAddress.State;
addr.PostalCode = shippingAddress.PostalCode;
addr = locationMaint.Address.Update(addr);
}
// Save the customer location
locationMaint.Actions.PressSave();
}
}
// Call bas method
baseMethod();
Base.Shipping_Contact.Cache.Clear();
Base.Shipping_Address.Cache.Clear();
Base.Document.View.RequestRefresh();
Base.Document.Cache.IsDirty = false;
}
#endregion
}
}

Creating Customer Location

My requirement is to create a customer location part of downloading order from 3rd party shopping cart.
I have tried this below code and It is not saving any location and also not raising any error.
private static void CreateCustomerLocation(Customer cust, string locationcode, OrderDTO ord, OrderDownloadActivityEntry grp)
{
try
{
LocationMaint graph = CustomerLocationMaint.CreateInstance<CustomerLocationMaint>();
SelectedLocation loc = new SelectedLocation();
loc.BAccountID = cust.BAccountID;
loc.LocationCD = locationcode;
loc.Descr = ord.CustomerLocationName;
loc.IsContactSameAsMain = false;
loc.IsAddressSameAsMain = false;
graph.Location.Insert(loc);
Contact contact = new Contact();
contact.Attention = ord.OrderCustomerContactName;
contact.Phone1 = ord.OrderCustomerContactPhone;
contact.DisplayName = ord.CustomerLocationName;
contact.LastName = ord.OrderCustomerContactName;
contact = graph.Contact.Update(contact);
Address address = new Address();
address.AddressLine1 = ord.OrderShippingLocationAddress1;
address.AddressLine2 = ord.OrderShippingLocationAddress2;
address.City = ord.OrderShippingLocationCity;
address.State = ord.OrderShippingLocationState;
address.PostalCode = ord.OrderShippingLocationZip;
address.CountryID = "US";
contact = graph.Contact.Update(contact);
address = graph.Address.Update(address);
loc.DefAddressID = address.AddressID;
loc.DefContactID = contact.ContactID;
graph.Location.Update(loc);
graph.Save.Press();
}
catch(Exception e)
{
grp.AddLogData(SessionID, "Create Location", "Create Location falied", null, null, e.StackTrace);
}
}
I am not able to figure out where i am making mistake. any suggestion for this issue?
Update
I have tried the following code and I am getting the following error
CARAccountLocationID' cannot be empty.
private static void CreateCustomerLocation(Customer cust, string locationcode, OrderDTO ord, OrderDownloadActivityEntry grp)
{
try
{
LocationMaint graph = PXGraph.CreateInstance<CustomerLocationMaint>();
graph.BusinessAccount.Current = PXSelect<BAccount, Where<BAccount.bAccountID, Equal<Required<BAccount.bAccountID>>>>.Select(graph, cust.BAccountID);
var newLocation = (Location)graph.Location.Cache.CreateInstance();
var locType = LocTypeList.CustomerLoc;
newLocation.LocType = locType;
graph.Location.Insert(newLocation);
var loc = (Location)graph.Location.Cache.CreateCopy(graph.Location.Current);
Contact contact = graph.Contact.Cache.CreateCopy(graph.Contact.Current) as Contact;
contact.Attention = ord.OrderCustomerContactName;
contact.Phone1 = ord.OrderCustomerContactPhone;
contact.DisplayName = ord.CustomerLocationName;
contact.LastName = ord.OrderCustomerContactName;
contact = graph.Contact.Update(contact);
Address address = graph.Address.Cache.CreateCopy(graph.Address.Current) as Address;
address.AddressLine1 = ord.OrderShippingLocationAddress1;
address.AddressLine2 = ord.OrderShippingLocationAddress2;
address.City = ord.OrderShippingLocationCity;
address.State = ord.OrderShippingLocationState;
address.PostalCode = ord.OrderShippingLocationZip;
address.CountryID = "US";
contact = graph.Contact.Update(contact);
address = graph.Address.Update(address);
contact.DefAddressID = address.AddressID;
loc.IsAddressSameAsMain = false;
loc.IsContactSameAsMain = false;
loc.IsAPAccountSameAsMain = true;
loc.IsAPPaymentInfoSameAsMain = true;
loc.IsARAccountSameAsMain = true;
loc.LocationCD = locationcode;
loc.Descr = ord.CustomerLocationName;
loc = graph.Location.Update(loc);
loc.BAccountID = cust.BAccountID;
graph.Location.Cache.RaiseFieldUpdated<Location.isARAccountSameAsMain>(loc, null);
if (loc.CARAccountLocationID == null)
loc.CARAccountLocationID = cust.DefLocationID;
graph.Location.Update(loc);
graph.Save.Press();
}
catch(Exception e)
{
grp.AddLogData(SessionID, "Create Location", "Create Location falied", null, null, e.StackTrace);
}
}
CARAccountLocationID is the LocationID of the MAIN location for a given BAccount/Customer. It is used by the business logic when setting GLAccounts.SameAsDefaultLocationS on screen AR303020.
I've seen the "'CARAccountLocationID' cannot be empty." error when creating a location without first setting the Customer.
The resolution was to first set the customer, then set SameAsDefaultLocationS, then set the rest of the fields.
In the screen API order of operations matters.
In your case you might need to directly set loc.CARAccountLocationID to the LocationID of the customer's MAIN location.

Add note to custom object

I have tried everything I can find on the net and in the existing code, but I cannot get a note added to the notes table and attached to my custom table row. I am in a real bind trying to get this note attached. Any help will be greatly appreciated.
Here is the note id def:
#region NoteID
public abstract class noteID : PX.Data.IBqlField { }
protected Guid? _NoteID;
[PXNote()]
public virtual Guid? NoteID { get; set; }
#endregion
Here is the code to insert the row and attach the note:
//Retrieve EDI Document remittance
foreach (LingoSearchResults ediRemit in docRemits)
{
resRemit = lingo.RetrieveRemit(ediRemit.documentId, docType);
partnerCustomerMap pcmap = lstPartnerCustomer.Find(delegate (partnerCustomerMap pcm)
{ return pcm.partner == resRemit.DataRemit.partner; });
int newRemittanceId = 0;
var remittance = new EDRemittance();
//Set all field values
remittance.Status = "A";
remittance.Type = resRemit.DataRemit.type;
remittance.DocumentId = resRemit.DataRemit.documentId;
remittance.RecordId = resRemit.DataRemit.recordId;
remittance.TagId = resRemit.DataRemit.tagId;
remittance.Account = resRemit.DataRemit.account;
remittance.PartnerId = resRemit.DataRemit.partner;
remittance.DocumentNumber = resRemit.DataRemit.documentNumber;
remittance.SenderType = resRemit.DataRemit.senderType;
remittance.PaymentNumber = resRemit.DataRemit.paymentNumber;
remittance.PaymentFormat = resRemit.DataRemit.paymentFormat;
remittance.PaymentReason = resRemit.DataRemit.paymentReason;
strDate = resRemit.DataRemit.remitDate.ToString();
if (DateTime.TryParseExact(strDate, "yyyyMMdd",
System.Globalization.CultureInfo.InvariantCulture,
System.Globalization.DateTimeStyles.None, out tempDate))
remittance.RemitDate = tempDate;
else
remittance.RemitDate = DateTime.Today;
remittance.CurrencyEntity = resRemit.DataRemit.currencyEntity;
remittance.DepartmentNumber = resRemit.DataRemit.departmentNumber;
if (DateTime.TryParse(strDate, out tempDate))
remittance.ReceiveDate = tempDate;
else
remittance.ReceiveDate = DateTime.Today;
remittance.HandlingCode = resRemit.DataRemit.handlingCode;
remittance.RemitTotal = resRemit.DataRemit.remitTotal;
remittance.DetailLineCount = resRemit.DataRemit.detailLineCount;
remittance.BatchNumber = resRemit.DataRemit.batchNumber;
remittance.ReceiverType = resRemit.DataRemit.receiverType;
remittance.BatchStatus = resRemit.DataRemit.batchStatus;
remittance.PaymentMethod = resRemit.DataRemit.paymentMethod;
remittance.CurrencyCode = resRemit.DataRemit.currencyCode;
remittance.PaymentStatus = resRemit.DataRemit.paymentStatus;
remittance.Vendor = resRemit.DataRemit.vendor;
remittance.RemitNumber = resRemit.DataRemit.remitNumber;
//Insert new row, save, and retrieve new Id value
remitGraph.Remittance.Insert(remittance);
remitGraph.Persist();
newRemittanceId = (int)remitGraph.Remittance.Current.RemittanceNbr;
//Add notes for remittance
noteText = "Remit level note";
foreach (EdiNote note in resRemit.DataRemit.notes)
{
noteText += note.type + ": " + note.note + '\n';
}
if (noteText != "")
{
PXNoteAttribute.GetNoteID<EDRemittance.noteID>(remitGraph.Remittance.Cache, remittance);
PXNoteAttribute.SetNote(remitGraph.Remittance.Cache, remittance, noteText);
//remitGraph.Persist();
}
I would try the following changes
remittance = remitGraph.Remittance.Insert(remittance);
//this saves the object to the cache and gets things like Noteid generated. On the
//return trip this data is available
//remitGraph.Persist();
//PXNoteAttribute.GetNoteID<EDRemittance.noteID>(remitGraph.Remittance.Cache, remittance);
PXNoteAttribute.SetNote(remitGraph.Remittance.Cache, remittance, noteText);
remittance = remitGraph.Remittance.Update(remittance)
//at the end do an Actions.PressSave();

Closing Case in Acumatica through API

I want to close the case in Partners Portal remotely using Web API, whenever I close the case in my (client) side. I was able to implement the code but ran into below issue.
It is changing the status and resolution of the case in Partners Portal but Close Case button is enabled and it is visible in My Open Case bucket. Please let me know if I can close the case remotely using Web API or if I am missing anything.
protected virtual void CRCase_RowPersisting(PXCache cache, PXRowPersistingEventArgs e)
{
var caseRow = (CRCase)e.Row;
if (caseRow != null)
{
if (caseRow.Status == "C") // Closed
{
string cloud9CaseCD = null;
cloud9CaseCD = CRCaseForCreate.Current.CaseCD;
string acumaticaCaseCD = string.Empty;
CSAnswers aCCaseNoAttribute = PXSelect<CSAnswers,
Where<CSAnswers.refNoteID, Equal<Required<CSAnswers.refNoteID>>,
And<CSAnswers.attributeID, Equal<Required<CSAnswers.attributeID>>>>>.Select(new PXGraph(), CRCaseForCreate.Current.NoteID, "ACCASENO");
if (aCCaseNoAttribute != null)
{
acumaticaCaseCD = aCCaseNoAttribute.Value;
if(!string.IsNullOrEmpty(acumaticaCaseCD))
{
SP203000WS.Screen context = new SP203000WS.Screen();
context.CookieContainer = new System.Net.CookieContainer();
context.AllowAutoRedirect = true;
context.EnableDecompression = true;
context.Timeout = 1000000;
context.Url = "https://sso.acumatica.com/Soap/SP203000.asmx";
PartnerPortalCreds loginCreds = GetCreds();
string username = loginCreds.PARTPRTUSE;
string password = loginCreds.PARTPRTPAS;
SP203000WS.LoginResult result = context.Login(username, password);
SP203000WS.Content CR306000 = context.GetSchema();
context.Clear();
SP203000WS.Content[] CR306000Content = context.Submit
(
new SP203000WS.Command[]
{
new SP203000WS.Value
{
Value = acumaticaCaseCD,
LinkedCommand = CR306000.Case.CaseID
},
new SP203000WS.Value
{
Value = "C",
LinkedCommand = new SP203000WS.Field { FieldName="Status", ObjectName="Case"}
},
new SP203000WS.Value
{
Value = "RD",
LinkedCommand = new SP203000WS.Field { FieldName="Resolution", ObjectName="Case"}
},
CR306000.Actions.Submit,
CR306000.Case.CaseID
}
);
context.Logout();
}
}
}
}
}
Tried below code using CloseCase Action: -
protected virtual void CRCase_RowPersisting(PXCache cache, PXRowPersistingEventArgs e)
{
var caseRow = (CRCase)e.Row;
if (caseRow != null)
{
if (caseRow.Status == "C") // Closed
{
string cloud9CaseCD = null;
cloud9CaseCD = CRCaseForCreate.Current.CaseCD;
string acumaticaCaseCD = string.Empty;
CSAnswers aCCaseNoAttribute = PXSelect<CSAnswers,
Where<CSAnswers.refNoteID, Equal<Required<CSAnswers.refNoteID>>,
And<CSAnswers.attributeID, Equal<Required<CSAnswers.attributeID>>>>>.Select(new PXGraph(), CRCaseForCreate.Current.NoteID, "ACCASENO");
if (aCCaseNoAttribute != null)
{
acumaticaCaseCD = aCCaseNoAttribute.Value;
if (!string.IsNullOrEmpty(acumaticaCaseCD))
{
SP203010WS.Screen context = new SP203010WS.Screen();
context.CookieContainer = new System.Net.CookieContainer();
context.AllowAutoRedirect = true;
context.EnableDecompression = true;
context.Timeout = 1000000;
context.Url = "https://sso.acumatica.com/Soap/SP203010.asmx";
PartnerPortalCreds loginCreds = GetCreds();
string username = loginCreds.PARTPRTUSE;
string password = loginCreds.PARTPRTPAS;
SP203010WS.LoginResult result = context.Login(username, password);
SP203010WS.Content CR306000 = context.GetSchema();
context.Clear();
var commands1 = new SP203010WS.Command[]
{
new SP203010WS.Value
{
Value = acumaticaCaseCD,
LinkedCommand = CR306000.Case.CaseID
},
new SP203010WS.Value
{
Value = "Yes",
LinkedCommand = CR306000.Case.ServiceCommands.DialogAnswer, Commit = true
},
CR306000.Actions.CloseCase
};
var data = context.Submit(commands1);
context.Logout();
}
}
}
}
}
In the below image you can see that the case is already closed but Close Case menu button is still visible.
Close Case Confirmation Dialogbox on Partners Portal. How should I answer this dialogbox programatically while closing the case using Web API.
Have you tried to invoke Close action via Web API instead of changing values of the Status and Resolution fields? As far as I know, Close button on the Partner Portal updates support case Status to Open and Reason to Pending Closure. Then it's up to support personnel to manually close the case.
Finally found the solution. Updated the code for CloseCase (second code snippet). This will mark the case as Pending Closure in Partners Portal.

PXSelect returns null after record inserted

I am creating a customer in code. Straight after I create the customer I perform a PXSelect to retrieve the customer by the acctCd. But it returns null everytime. Even though I have checked to the database and verified it exists?
I'm guessing this is something to do with the cache how do I refresh this.
Here is my PXSelect
PXSelect<PX.Objects.AR.Customer, Where<PX.Objects.AR.Customer.acctCD, Equal<Required<PX.Objects.AR.Customer.acctCD>>>>.Select(this, id);
Here is my code that add customer
private PX.Objects.AR.Customer UpdateContact(ContactRead rexContact, PX.Objects.AR.Customer m, string customerClassID, bool insert = true)
{
PX.Objects.CR.Contact defContact = null;
PX.Objects.AR.CustomerMaintInherit graph = PXGraph.CreateInstance<PX.Objects.AR.CustomerMaintInherit>();
graph.Clear(PXClearOption.ClearAll);
//Add Customer and BAccount Records
graph.BAccount.Current = m;
m.AcctCD = "V" + rexContact._id;
m.AcctName = rexContact.system_search_key;
m.Type = "CU";
if (insert) {
m = graph.BAccount.Insert(m);
defContact = graph.DefContact.Current;
}
else {
defContact = PXSelect<PX.Objects.CR.Contact, Where<PX.Objects.CR.Contact.contactID, Equal<Required<PX.Objects.CR.Contact.contactID>>>>.Select(this, m.DefContactID);
graph.DefContact.Current = defContact;
}
//Update Default Contact Record
defContact.ContactType = "AP";
defContact.FullName = rexContact.system_search_key;
if (rexContact._related.contact_emails != null)
{
if (rexContact._related.contact_emails.Length > 0)
{
defContact.EMail = (from e in rexContact._related.contact_emails where e.email_primary == true select e.email_address).FirstOrDefault();
}
}
if (rexContact._related.contact_phones != null)
{
if (rexContact._related.contact_phones.Length > 0)
{
defContact.Phone1 = (from e in rexContact._related.contact_phones where e.phone_primary == true select e.phone_number).FirstOrDefault();
}
}
defContact = graph.DefContact.Update(defContact);
//Change customer class to vendor
m.CustomerClassID = customerClassID;
m = (PX.Objects.AR.Customer)graph.BAccount.Update(m);
graph.Actions.PressSave();
return m;
}
Consider usage PXSelectReadonly. It will try to retrieve value directly from db without usage of cache. Another option is to create instance of graph, with needed view, and through that graph ask db with PXSelect

Resources