Skip to content

Commit

Permalink
Merge pull request #79 from SanduDS/master
Browse files Browse the repository at this point in the history
Add item group record support for invoices
  • Loading branch information
LakshanSS authored Nov 4, 2022
2 parents aeb8c68 + fa539d5 commit e0e32ca
Show file tree
Hide file tree
Showing 11 changed files with 653 additions and 41 deletions.
2 changes: 1 addition & 1 deletion netsuite/Ballerina.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
distribution = "2201.2.1"
org = "ballerinax"
name = "netsuite"
version = "3.0.0"
version = "3.0.1"
authors = ["Ballerina"]
repository = "https://github.com/ballerina-platform/module-ballerinax-netsuite"
keywords = ["Business Management/ERP", "Cost/Paid"]
Expand Down
47 changes: 40 additions & 7 deletions netsuite/Invoice.bal
Original file line number Diff line number Diff line change
Expand Up @@ -16,24 +16,24 @@

import ballerina/http;

isolated function mapInvoiceRecordFields(Invoice invoice) returns string|error {
isolated function mapInvoiceRecordFields(Invoice invoice, boolean replaceAll = false) returns string|error {
string finalResult = EMPTY_STRING;
map<anydata>|error invoiceMap = invoice.cloneWithType(MapAnyData);
if (invoiceMap is map<anydata>) {
if invoiceMap is map<anydata> {
string[] keys = invoiceMap.keys();
int position = 0;
foreach var invoiceField in invoice {
if (invoiceField is string|decimal) {
if invoiceField is string|decimal {
finalResult += setSimpleType(keys[position], invoiceField, TRAN_SALES);
} else if (invoiceField is RecordRef) {
} else if invoiceField is RecordRef {
finalResult += getXMLRecordRef(<RecordRef>invoiceField);
} else if (invoiceField is Item[]) {
} else if invoiceField is Item[] {
string itemXMLList = EMPTY_STRING;
foreach Item item in invoiceField {
string itemElements = check buildInvoiceItemElement(item);
itemXMLList += itemElements;
}
finalResult += string`<itemList>${itemXMLList}</itemList>`;
finalResult += string`<itemList replaceAll="${replaceAll}">${itemXMLList}</itemList>`;
}
position += 1;
}
Expand Down Expand Up @@ -113,11 +113,44 @@ isolated function mapInvoiceRecord(xml response) returns Invoice|error {
status: extractStringFromXML(response/**/<tranSales:status>/*),
entity: extractRecordRefFromXML(response/**/<tranSales:entity>),
currency: extractRecordRefFromXML(response/**/<tranSales:currency>),
internalId: extractRecordInternalIdFromXMLAttribute(response/**/<'record>)
internalId: extractRecordInternalIdFromXMLAttribute(response/**/<'record>),
itemList: check mapItemListMemberRecord(response/**/<tranSales:itemList>/*)
};
return invoice;
}

isolated function mapItemListMemberRecord(xml itemMembersXml) returns Item[]|error {
xmlns "urn:sales_2020_2.transactions.webservices.netsuite.com" as tranSales;
Item[] itemMembers = [];
foreach xml element in itemMembersXml {
xml elementItem = element/*;
Item itemMember = {
subscription: extractRecordRefFromXML(elementItem/**/<tranSales:subscription>/*),
item: extractRecordRefFromXML(elementItem/**/<tranSales:item>),
quantityAvailable: extractDecimalFromXML(elementItem/**/<tranSales:quantityAvailable>/*),
quantityOnHand: extractDecimalFromXML(elementItem/**/<tranSales:quantityOnHand>/*),
quantity: extractDecimalFromXML(elementItem/**/<tranSales:quantity>/*),
units: extractRecordRefFromXML(elementItem/**/<tranSales:units>),
description: extractStringFromXML(elementItem/**/<tranSales:description>/*),
price: extractRecordRefFromXML(elementItem/**/<tranSales:price>),
rate: extractStringFromXML(elementItem/**/<tranSales:rate>/*),
amount: extractDecimalFromXML(elementItem/**/<tranSales:amount>/*),
location: extractRecordRefFromXML(elementItem/**/<tranSales:location>/*),
line: extractDecimalFromXML(elementItem/**/<tranSales:line>/*)
};
boolean|error value = extractBooleanValueFromXMLOrText(element/**/<tranSales:excludeFromRateRequest>/*);
if value is boolean {
itemMember.excludeFromRateRequest = value;
}
value = extractBooleanValueFromXMLOrText(element/**/<tranSales:isTaxable>/*);
if value is boolean {
itemMember.isTaxable = value;
}
itemMembers.push(itemMember);
}
return itemMembers;
}

isolated function getInvoiceResult(http:Response response) returns @tainted Invoice|error {
xml xmlValue = check formatPayload(response);
if (response.statusCode == http:STATUS_OK) {
Expand Down
234 changes: 232 additions & 2 deletions netsuite/account.bal
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,143 @@ isolated function mapNewAccountRecordFields(NewAccount account) returns string {
return finalResult;
}

isolated function mapNewItemGroupRecordFields(NewItemGroup itemGroup) returns string|error {
string finalResult = EMPTY_STRING;
map<anydata>|error itemGroupMap = itemGroup.cloneWithType(MapAnyData);
if itemGroupMap is map<anydata> {
string[] keys = itemGroupMap.keys();
int position = 0;
foreach var item in itemGroup {
if item is string|boolean|decimal {
finalResult += setSimpleType(keys[position], item, LIST_ACCT);
} else if item is RecordInputRef {
finalResult += getXMLRecordInputRef(<RecordInputRef>item);
} else if item is RecordRef {
finalResult += getXMLRecordRef(<RecordRef>item);
} else if item is RecordRef[] {
string recordRefList = check getRecordRefListInXML(<RecordRef[]>item);
finalResult += string `<${LIST_ACCT}:${keys[position]} xsi:type="nsCore:RecordRefList"
xmlns:nsCore="urn:core_2020_2.platform.webservices.netsuite.com">
${recordRefList}
</${LIST_ACCT}:${keys[position]}>`;
} else if item is ItemMember[] {
string itemMemberList = EMPTY_STRING;
foreach ItemMember itemMember in item {
itemMemberList += string `
<${LIST_ACCT}:itemMember xsi:type="${LIST_ACCT}:ItemMember">
${getItemMemberInXML(itemMember)}
</${LIST_ACCT}:itemMember>`;
}
finalResult += string `
<${LIST_ACCT}:memberList xsi:type="${LIST_ACCT}:ItemMemberList" replaceAll="false">
${itemMemberList}
</${LIST_ACCT}:memberList>`;
} else if item is Translation[] {
string translationList = EMPTY_STRING;
foreach Translation translation in item {
translationList += string `
<${LIST_ACCT}:translation xsi:type="${LIST_ACCT}:Translation">
${getTranslationOrHierarchyVRecordsInXML(translation)}
</${LIST_ACCT}:translation>`;
}
finalResult += string `
<${LIST_ACCT}:translationsList xsi:type="${LIST_ACCT}:TranslationsList">
${translationList}
</${LIST_ACCT}:translationsList>`;
} else if item is ItemGroupHierarchyVersions[] {
string hierarchyList = EMPTY_STRING;
foreach ItemGroupHierarchyVersions hVersion in item {
hierarchyList += string `
<${LIST_ACCT}:itemGroupHierarchyVersions xsi:type="${LIST_ACCT}:ItemGroupHierarchyVersions">
${getTranslationOrHierarchyVRecordsInXML(hVersion)}
</${LIST_ACCT}:itemGroupHierarchyVersions>`;
}
finalResult += string `
<${LIST_ACCT}:hierarchyVersionsList xsi:type="${LIST_ACCT}:ItemGroupHierarchyVersionsList">
${hierarchyList}
</${LIST_ACCT}:hierarchyVersionsList>`;
} else if item is CustomFieldList {
finalResult += check getCustomElementList(item, LIST_ACCT);
}
position += 1;
}
}
return finalResult;
}

isolated function getTranslationOrHierarchyVRecordsInXML(Translation translation) returns string {
string finalResult = EMPTY_STRING;
map<anydata>|error translationMap = translation.cloneWithType(MapAnyData);
if translationMap is map<anydata> {
string[] keys = translationMap.keys();
int position = 0;
foreach var item in translation {
if item is string|boolean|decimal {
finalResult += setSimpleType(keys[position], item, LIST_ACCT);
} else if item is RecordInputRef {
finalResult += getXMLRecordInputRef(<RecordInputRef>item);
} else if item is RecordRef {
finalResult += getXMLRecordRef(<RecordRef>item);
}
position += 1;
}
}
return finalResult;
}

isolated function getItemMemberInXML(ItemMember itemMember) returns string {
string finalResult = EMPTY_STRING;
map<anydata>|error itemMemberMap = itemMember.cloneWithType(MapAnyData);
if (itemMemberMap is map<anydata>) {
string[] keys = itemMemberMap.keys();
int position = 0;
foreach var item in itemMember {
if item is string|boolean|decimal {
if keys[position] == "vsoeDeferral" {
finalResult += string `<nsCommon:vsoeDeferral xsi:type="nsCommon:VsoeDeferral">
${item}</nsCommon:vsoeDeferral>`;
} else if keys[position] == "vsoePermitDiscount" {
finalResult += string `
<nsCommon:vsoePermitDiscount xsi:type="nsCommon:VsoePermitDiscount">
${item}
</nsCommon:vsoePermitDiscount>`;
} else if keys[position]== "itemSource" {
finalResult += string `
<nsCommon:itemSource xsi:type="nsCommon:ItemSource">
${item}
</nsCommon:itemSource>`;
} else {
finalResult += setSimpleType(keys[position], item, LIST_ACCT);
}
} else if item is RecordInputRef {
finalResult += getXMLRecordInputRef(<RecordInputRef>item);
} else if item is RecordRef {
finalResult += getXMLRecordRef(<RecordRef>item);
}
position += 1;
}
}
return finalResult;
}

isolated function getRecordRefListInXML(RecordRef[] records) returns string|error {
string recordListInXML = EMPTY_STRING;
foreach RecordRef ref in records {
recordListInXML += string `<nsCore:recordRef xsi:type="nsCore:RecordRef" type="${ref.'type.toString()}"
internalId="${check ref.internalId.ensureType(string)}"/>`;
}
return recordListInXML;
}

isolated function wrapItemGroupElements(string subElements) returns string {
return string `<urn:record xsi:type="listAcct:ItemGroup"
xmlns:listAcct="urn:accounting_2020_2.lists.webservices.netsuite.com"
xmlns:nsCore="urn:core_2020_2.platform.webservices.netsuite.com"
xmlns:nsCommon="urn:types.common_2020_2.platform.webservices.netsuite.com">
${subElements}
</urn:record>`;
}

isolated function wrapAccountElements(string subElements) returns string {
return string `<urn:record xsi:type="listAcct:Account"
xmlns:listAcct="urn:accounting_2020_2.lists.webservices.netsuite.com">
Expand Down Expand Up @@ -119,7 +256,7 @@ isolated function mapAccountFields(json accountTypeJson, Account account) return
return;
}

isolated function getAccountResult(http:Response response) returns @tainted Account|error {
isolated function getAccountResult(http:Response response) returns Account|error {
xml xmlValue = check formatPayload(response);
if (response.statusCode == http:STATUS_OK) {
xml output = xmlValue/**/<status>;
Expand All @@ -134,14 +271,107 @@ isolated function getAccountResult(http:Response response) returns @tainted Acco
}
}

isolated function getItemGroupResult(http:Response response) returns ItemGroup|error {
xml xmlValue = check formatPayload(response);
if response.statusCode == http:STATUS_OK {
xml output = xmlValue/**/<status>;
boolean isSuccess = check extractBooleanValueFromXMLOrText(output.isSuccess);
if isSuccess {
ItemGroup itemGroup = check mapItemGroupRecord(xmlValue);
return itemGroup;
} else {
fail error(NO_RECORD_CHECK);
}
} else {
fail error(NO_RECORD_CHECK);
}
}

isolated function mapItemMemberRecord(xml itemMembersXml) returns ItemMember[]|error {
xmlns "urn:accounting_2020_2.lists.webservices.netsuite.com" as listAcct;
ItemMember[] itemMembers = [];
foreach xml element in itemMembersXml {
ItemMember itemMember = {
memberDescr:extractStringFromXML(element/**/<listAcct:memberDescr>/*),
componentYield:extractDecimalFromXML(element/**/<listAcct:componentYield>/*),
bomQuantity:extractDecimalFromXML(element/**/<listAcct:bomQuantity>/*),
itemSource:extractStringFromXML(element/**/<listAcct:itemSource>/*),
quantity:extractDecimalFromXML(element/**/<listAcct:quantity>/*),
memberUnit:extractRecordRefFromXML(element/**/<listAcct:memberUnit>),
vsoeDeferral:extractStringFromXML(element/**/<listAcct:vsoeDeferral>/*),
vsoePermitDiscount:extractStringFromXML(element/**/<listAcct:vsoePermitDiscount>/*),
taxSchedule:extractRecordRefFromXML(element/**/<listAcct:taxSchedule>),
taxcode:extractStringFromXML(element/**/<listAcct:taxcode>/*),
item:extractRecordRefFromXML(element/**/<listAcct:item>),
taxrate:extractDecimalFromXML(element/**/<listAcct:taxrate>/*),
effectiveDate:extractStringFromXML(element/**/<listAcct:effectiveDate>/*),
obsoleteDate:extractStringFromXML(element/**/<listAcct:obsoleteDate>/*),
effectiveRevision:extractRecordRefFromXML(element/**/<listAcct:effectiveRevision>),
obsoleteRevision:extractRecordRefFromXML(element/**/<listAcct:obsoleteRevision>),
lineNumber:extractDecimalFromXML(element/**/<listAcct:lineNumber>/*),
memberKey:extractStringFromXML(element/**/<listAcct:memberKey>/*)
};
boolean|error value = extractBooleanValueFromXMLOrText(element/**/<listAcct:vsoeDelivered>/*);
if value is boolean {
itemMember.vsoeDelivered = value;
}
itemMembers.push(itemMember);
}
return itemMembers;
}

isolated function mapItemGroupRecord(xml response) returns ItemGroup|error {
xmlns "urn:accounting_2020_2.lists.webservices.netsuite.com" as listAcct;
ItemGroup itemGroup = {
internalId: extractRecordInternalIdFromXMLAttribute(response/**/<'record>),
createdDate: extractStringFromXML(response/**/<listAcct:createdDate>/*),
lastModifiedDate: extractStringFromXML(response/**/<listAcct:lastModifiedDate>/*),
customForm: extractRecordRefFromXML(response/**/<listAcct:customForm>),
defaultItemShipMethod: extractRecordRefFromXML(response/**/<listAcct:defaultItemShipMethod>),
itemId: extractStringFromXML(response/**/<listAcct:itemId>/*),
upcCode: extractStringFromXML(response/**/<listAcct:upcCode>/*),
displayName: extractStringFromXML(response/**/<listAcct:displayName>/*),
vendorName: extractStringFromXML(response/**/<listAcct:vendorName>/*),
issueProduct: extractRecordRefFromXML(response/**/<listAcct:issueProduct>),
parent: extractRecordRefFromXML(response/**/<listAcct:parent>),
description: extractStringFromXML(response/**/<listAcct:description>/*),
department: extractRecordRefFromXML(response/**/<listAcct:department>),
'class: extractRecordRefFromXML(response/**/<listAcct:'class>),
location: extractRecordRefFromXML(response/**/<listAcct:location>),
memberList: check mapItemMemberRecord(response/**/<listAcct:memberList>/*),
customFieldList: check extractCustomFiledListFromXML(response/**/<listAcct:customFieldList>/*)
};
boolean|error value = extractBooleanValueFromXMLOrText(response/**/<listAcct:includeStartEndLines>/*);
if value is boolean {
itemGroup.includeStartEndLines = value;
}
value = extractBooleanValueFromXMLOrText(response/**/<listAcct:isVsoeBundle>/*);
if value is boolean {
itemGroup.isVsoeBundle = value;
}
value = extractBooleanValueFromXMLOrText(response/**/<listAcct:availableToPartners>/*);
if value is boolean {
itemGroup.availableToPartners = value;
}
value = extractBooleanValueFromXMLOrText(response/**/<listAcct:isInactive>/*);
if value is boolean {
itemGroup.isInactive = value;
}
value = extractBooleanValueFromXMLOrText(response/**/<listAcct:printItems>/*);
if value is boolean {
itemGroup.printItems = value;
}
return itemGroup;
}

isolated function mapAccountRecord(xml response) returns Account|error {
xmlns "urn:accounting_2020_2.lists.webservices.netsuite.com" as listAcct;
Account account = {
internalId: extractRecordInternalIdFromXMLAttribute(response/**/<'record>),
acctType: extractStringFromXML(response/**/<listAcct:acctType>/*),
acctNumber: extractStringFromXML(response/**/<listAcct:acctNumber>/*),
acctName: extractStringFromXML(response/**/<listAcct:acctName>/*),
generalRate : extractStringFromXML(response/**/<listAcct:generalRate>/*),
generalRate: extractStringFromXML(response/**/<listAcct:generalRate>/*),
cashFlowRate: extractStringFromXML(response/**/<listAcct:cashFlowRate>/*),
currency:extractRecordRefFromXML(response/**/<listAcct:currency>)
};
Expand Down
Loading

0 comments on commit e0e32ca

Please sign in to comment.