[DataContractAttribute]
class GOD_CustomerCreateContract
{
str accountNum; // Optional; if blank, a number sequence will be used
str name; // Required
str custGroup; // Required
str currency; // Optional; will fall back to company defaults if you handle that logic
str email; // Optional (see note below)
str phone; // Optional (see note below)
str street; // Optional
str city; // Optional
str state; // Optional
str zipCode; // Optional
str country; // Optional but recommended if address is sent
str company; // Optional; if set, code runs under this company
// When true, creates a Person party; otherwise Organization
boolean isPerson;
[DataMemberAttribute("AccountNum"), AifCollectionTypeAttribute('NONE', Types::String)]
public str parmAccountNum(str _accountNum = accountNum)
{
accountNum = _accountNum;
return accountNum;
}
[DataMemberAttribute("Name")]
public str parmName(str _name = name)
{
name = _name;
return name;
}
[DataMemberAttribute("CustGroup")]
public str parmCustGroup(str _custGroup = custGroup)
{
custGroup = _custGroup;
return custGroup;
}
[DataMemberAttribute("Currency")]
public str parmCurrency(str _v = currency)
{
currency = _v;
return currency;
}
[DataMemberAttribute("Email")]
public str parmEmail(str _v = email)
{
email = _v;
return email;
}
[DataMemberAttribute("Phone")]
public str parmPhone(str _v = phone)
{
phone = _v;
return phone;
}
[DataMemberAttribute("Street")]
public str parmStreet(str _v = street)
{
street = _v;
return street;
}
[DataMemberAttribute("City")]
public str parmCity(str _v = city)
{
city = _v;
return city;
}
[DataMemberAttribute("State")]
public str parmState(str _v = state)
{
state = _v;
return state;
}
[DataMemberAttribute("ZipCode")]
public str parmZipCode(str _v = zipCode)
{
zipCode = _v;
return zipCode;
}
[DataMemberAttribute("Country")]
public str parmCountry(str _v = country)
{
country = _v;
return country;
}
[DataMemberAttribute("Company")]
public str parmCompany(str _v = company)
{
company = _v;
return company;
}
[DataMemberAttribute("IsPerson")]
public boolean parmIsPerson(boolean _v = isPerson)
{
isPerson = _v;
return isPerson;
}
}
[DataContractAttribute]
class GOD_CustomerCreateResponse
{
boolean success;
str message;
str accountNum;
str partyNumber;
RecId custRecId;
RecId partyRecId;
[DataMemberAttribute("Success")]
public boolean parmSuccess(boolean _v = success)
{
success = _v;
return success;
}
[DataMemberAttribute("Message")]
public str parmMessage(str _v = message)
{
message = _v;
return message;
}
[DataMemberAttribute("AccountNum")]
public str parmAccountNum(str _v = accountNum)
{
accountNum = _v;
return accountNum;
}
[DataMemberAttribute("PartyNumber")]
public str parmPartyNumber(str _v = partyNumber)
{
partyNumber = _v;
return partyNumber;
}
[DataMemberAttribute("CustRecId")]
public RecId parmCustRecId(RecId _v = custRecId)
{
custRecId = _v;
return custRecId;
}
[DataMemberAttribute("PartyRecId")]
public RecId parmPartyRecId(RecId _v = partyRecId)
{
partyRecId = _v;
return partyRecId;
}
}
class GOD_CustomerCreateService
{
private GOD_CustomerCreateResponse buildResponse(boolean _success, str _message, str _accountNum = '', RecId _custRecId = 0, RecId _partyRecId = 0)
{
GOD_CustomerCreateResponse resp = new GOD_CustomerCreateResponse();
DirPartyTable party;
resp.parmSuccess(_success);
resp.parmMessage(_message);
resp.parmAccountNum(_accountNum);
resp.parmCustRecId(_custRecId);
resp.parmPartyRecId(_partyRecId);
if (_partyRecId)
{
party = DirPartyTable::findRec(_partyRecId);
resp.parmPartyNumber(party.PartyNumber);
}
return resp;
}
/// <summary>
/// Creates a customer with party, and optionally a postal address.
/// </summary>
/// <param name="_cust">Data contract with customer details.</param>
/// <returns>Response contract with result info.</returns>
[SysEntryPointAttribute(true)]
public GOD_CustomerCreateResponse createCustomer(GOD_CustomerCreateContract _cust)
{
GOD_CustomerCreateResponse response;
str targetCompany = _cust.parmCompany();
// Simple validation
if (!_cust.parmName())
{
return this.buildResponse(false, "Name is required.");
}
if (!_cust.parmCustGroup())
{
return this.buildResponse(false, "CustGroup is required.");
}
// Validate customer group
if (!CustGroup::exist(_cust.parmCustGroup()))
{
return this.buildResponse(false, strFmt("CustGroup %1 does not exist.", _cust.parmCustGroup()));
}
// Run in the specified company, if any
if (targetCompany)
{
changecompany(targetCompany)
{
response = this.createCustomerInCurrentCompany(_cust);
}
}
else
{
response = this.createCustomerInCurrentCompany(_cust);
}
return response;
}
private GOD_CustomerCreateResponse createCustomerInCurrentCompany(GOD_CustomerCreateContract _cust)
{
CustTable custTable;
NumberSeq numSeq;
boolean generatedAccount = false;
str accountNum = _cust.parmAccountNum();
RecId partyRecId;
GOD_CustomerCreateResponse resp;
DirParty dirParty;
DirPartyPostalAddressView dirPartyPostalAddressView;
DirPartyContactInfoView dirPartyContactInfo;
try
{
ttsbegin;
// If caller supplied AccountNum and it already exists, return success (idempotent)
if (accountNum && CustTable::exist(accountNum))
{
custTable = CustTable::find(accountNum, true);
ttscommit;
return this.buildResponse(true, "Customer already exists; no action taken.", accountNum, custTable.RecId, custTable.Party);
}
// Generate account from number sequence if not provided
if (!accountNum)
{
NumberSequenceReference nsRef = CustParameters::numRefCustAccount();
if (!nsRef)
{
throw error("Customer account number sequence reference is not configured.");
}
numSeq = NumberSeq::newGetNum(nsRef);
accountNum = numSeq.num();
generatedAccount = true;
}
// Create Party (Organization or Person)
DirPartyType partyType = _cust.parmIsPerson() ? DirPartyType::Person : DirPartyType::Organization;
//partyRecId = DirParty::createParty(partyType, _cust.parmName());
// Create the customer
custTable.clear();
custTable.initValue(); // defaults
custTable.AccountNum = accountNum;
custTable.CustGroup = _cust.parmCustGroup();
custTable.PaymTermId = CustGroup::find(custTable.CustGroup).PaymTermId;
//custTable.Party = partyRecId;
if (_cust.parmCurrency())
{
custTable.Currency = _cust.parmCurrency();
}
custTable.insert(partyType,_cust.parmName());
// Mark number sequence as used if we generated it
if (generatedAccount && numSeq)
{
numSeq.used();
}
// Optional: create postal address if provided
dirParty = DirParty::constructFromCommon(custTable);
dirPartyPostalAddressView.city = _cust.parmCity();
dirPartyPostalAddressView.Street = _cust.parmStreet();
dirPartyPostalAddressView.State = _cust.parmState();
dirPartyPostalAddressView.County = _cust.parmCountry();
dirPartyPostalAddressView.IsPrimary = NoYes::Yes;
dirParty.createOrUpdatePostalAddress(dirPartyPostalAddressView);
//
//if (_cust.parmStreet() || _cust.parmCity() || _cust.parmZipCode() || _cust.parmCountry())
//{
// this.createPrimaryPostalAddress(partyRecId,
// _cust.parmStreet(),
// _cust.parmCity(),
// _cust.parmState(),
// _cust.parmZipCode(),
// _cust.parmCountry());
//}
dirPartyContactInfo.LocationName = "Email address";
dirPartyContactInfo.Locator = "abc@gmail.com";
dirPartyContactInfo.Type = LogisticsElectronicAddressMethodType::Email;
dirPartyContactInfo.IsPrimary = NoYes::Yes;
dirParty.createOrUpdateContactInfo(dirPartyContactInfo);
// Optional: add electronic addresses (email/phone)
// NOTE: There are multiple helper APIs; uncomment and adapt as per your standard.
/*
if (_cust.parmEmail())
{
DirPartyContactInfo::addElectronicAddress(partyRecId,
LogisticsElectronicAddressMethodType::Email,
_cust.parmEmail(),
true, // isPrimary
"Primary email");
}
if (_cust.parmPhone())
{
DirPartyContactInfo::addElectronicAddress(partyRecId,
LogisticsElectronicAddressMethodType::Phone,
_cust.parmPhone(),
false, // isPrimary
"Main phone");
}
*/
ttscommit;
resp = this.buildResponse(true, "Customer created successfully.", accountNum, custTable.RecId, partyRecId);
}
catch (Exception::Error)
{
// Rollback handled automatically by the runtime on exception
resp = this.buildResponse(false, infolog.text(), accountNum);
}
catch
{
resp = this.buildResponse(false, "Unknown error creating customer.", accountNum);
}
return resp;
}
/// <summary>
/// Creates a primary postal address for the specified party.
/// </summary>
/*
private void createPrimaryPostalAddress(RecId _partyRecId, str _street, str _city, str _state, str _zip, str _country)
{
// Use logistics location framework
LogisticsLocation loc = LogisticsLocation::construct();
RecId locationRecId;
LogisticsPostalAddress postal = LogisticsPostalAddress::construct();
DirPartyLocation partyLocation = DirPartyLocation::construct();
// Create a location
locationRecId = loc.createLocation();
// Create postal address record
postal.parmLocation(locationRecId);
postal.parmIsPrimary(true);
postal.parmStreet(_street);
postal.parmCity(_city);
postal.parmState(_state);
postal.parmZipCode(_zip);
postal.parmCountryRegionId(_country);
postal.create();
// Link the location to the party
partyLocation.parmParty(_partyRecId);
partyLocation.parmLocation(locationRecId);
partyLocation.parmIsPostalAddress(true);
partyLocation.parmIsPrimary(true);
partyLocation.create();
}
*/
}
internal final class GOD_CustomerCreateTestingJob
{
/// <summary>
/// Class entry point. The system will call this method when a designated menu
/// is selected or when execution starts and this class is set as the startup class.
/// </summary>
/// <param name = "_args">The specified arguments.</param>
public static void main(Args _args)
{
GOD_CustomerCreateContract contract = new GOD_CustomerCreateContract();
GOD_CustomerCreateService customerCreateService = new GOD_CustomerCreateService();
contract.parmAccountNum('US-104');
contract.parmCompany('USMF');
contract.parmName('TestCust');
contract.parmCustGroup('90');
contract.parmStreet('KPHB');
contract.parmCity('Chennai');
contract.parmStreet('Adayar');
contract.parmCountry('India');
contract.parmState('TamilNadu');
customerCreateService.createCustomer(contract);
}
}
{
"_cust": {
"Company": "USMF",
"Name": "Contoso Retail Pvt Ltd",
"CustGroup": "10",
"Currency": "USD",
"Street": "1 Microsoft Way",
"City": "Redmond",
"State": "WA",
"ZipCode": "98052",
"Country": "US",
"IsPerson": false
}
}