ContaInvoicePayments
Back to ListDescription: Import Payments from Conta and link it to Orders in FM system
FileMaker Prototype:
Set Variable [$res; ACF_Run("ContaInvoicePayments"; date_fromDate)]
Category: CONTA API
Dependencies
- getContaBaseURL: Get the CONTA API base URL, Sandbox or production URLs
- getContaApiKeyandNumber: Retrieve the Conta credentials used in the API
- ContaVerifyAPIresponce: Look for error message in Conta API responce
- find_in_arrayInt: Look up value in an INT array
NOTE: This function serves as a reference template. To use it effectively, you may need to adjust certain parts of the code, such as field names, database structures, and specific data lists to fit the requirements of your system. This customization allows the function to work seamlessly within your environment.
Function source:
function ContaInvoicePayments ( date fromDate )
date toDate = date(now());
string apiParams = "?page=%d&fromDate=%s&toDate=%s";
array int pContaID, pInvoiceID, pInvoiceNo;
array date pPaymentDate;
int pageNo = 0;
// Get the payments we allready have, so we can skip them when getting data from the API
string sql = "SELECT ContaID, InvoiceID, InvoiceNo, PaymentDate FROM Payments
WHERE PaymentDate >= :fromDate AND PaymentDate <= :toDate
INTO :pContaID, :pInvoiceID, :pInvoiceNo, :pPaymentDate";
string res = ExecuteSQL ( sql ) ;
if ( res != "OK") then
throw "SQL Select Error: in " + sql + "\n"+res;
end if
int origCount = sizeof (pInvoiceID);
// Prepare doing the request
JSON apidata = getContaApiKeyandNumber();
if ( apidata["APIkey"] == "") then
alert ("No API key found");
return "ERROR: Missing APIkey";
end if
string APIkey = apidata["APIkey"];
bool production = (apidata["Production"]=="1");
int compOrg = int(apidata["CompNo"]);
string hdr = 'apiKey:'+APIkey;
string dateFormat = "%Y-%m-%d";
// /invoice/organizations/{opContextOrgId}/invoice-payments
string url,pre;
int i,x, apiHits,apiPages, hits, hitID, hitCuID, hitInvID, hitInvNo;
float hitAm;
date hitPayDateD;
string hitPayDate;
JSON apiRes;
// Start of the SQL insert statement, values part is added later in the function.
string insertSQL = "INSERT INTO Payments (ContaID,InvoiceID, InvoiceNo, PaidAmount, PaymentDate, CustomerID) ";
array string insValues;
float sumImported = 0.0;
apiPages = 0;
// The API returns a certain number of
repeat // All pages in the query-result.
url = getContaBaseURL(production)+"/invoice/organizations/"+compOrg+"/invoice-payments"
+ format (apiParams, pageNo, string(fromDate, dateFormat), string (toDate, dateFormat));
print "\n"+url+"\n";
res = HTTP_GET ( url, hdr);
print "\n"+res;
// Verify the result-
clear(apiRes);
apiRes = res;
if (ContaVerifyAPIresponce(apiRes)) then
apiHits = int(apiRes["hitCount"]);
apiPages = int(apiRes["pageCount"])-1;
if ( apiHits == 0) then
break;
end if
print format("\nPages %d, hits %d\n", apiHits, apiPages);
hits = sizeof (apiRes["hits"]);
for (i=1, hits)
pre = format ("hits[%d].", i);
hitID = int ( apiRes[pre+"id"]);
hitCuID = int ( apiRes[pre+"customerId"]);
hitInvID = int ( apiRes[pre+"invoiceId"]);
hitInvNo = int ( apiRes[pre+"invoiceNo"]);
hitPayDate = apiRes[pre+"date"];
hitPayDateD = date(hitPayDate,"%Y-%m-%d");
hitAm = float (apiRes[pre+"amount"]);
x = find_in_arrayInt (pContaID, hitID );
if ( x < 0) then
sumImported += hitAm;
insValues[] = format("(%d, %d, %d, %f, DATE '%s', %d)", hitID,hitInvID, hitInvNo,hitAm,hitPayDate, hitCuID);
pContaID[] = hitID;
else
// Verify the stored occurence with the found.
if (x<=origCount) then
if (hitInvID != pInvoiceID[x] || hitInvNo != pInvoiceNo[x] || hitPayDateD != pPaymentDate[x]) then
alert ( format("Stored payment does not match retrieved, invoiceNo: %d, amount=%.2f", hitInvNo,hitAm));
end if
end if
end if
end for
pageNo++;
end if
until (pageNo>apiPages);
// Should we add any ?
if ( sizeof (insValues)>0) then
sql = insertSQL+"VALUES " + implode (",", insValues);
print "\n" + sql;
res = ExecuteSQL (sql);
if ( res != "") then
throw "Error Insert SQL: " + res;
end if
end if
// Do the Update of the OrderFK field.
// We use a subquery in this construct as FileMaker SQL does not allow JOIN in UPDATE.
sql = "UPDATE Payments
SET OrderFK = (SELECT PrimaryKey FROM Orders WHERE Orders.InvoiceNo = Payments.InvoiceNo)
WHERE Payments.OrderFK IS NULL OR Payments.OrderFK = ''";
res = executeSQL (sql );
if ( res != "") then
print sql + "\n";
throw "Error Update relations SQL: " + res;
end if
return format ( "OK: %d payments imported, Sum %.2f", sizeof (insValues), sumImported);
end
The ContaInvoicePayments function retrieves payments from the Conta Accounting system and adds records to the Payments table in the FileMaker solution. The API returns payments registered within a specified date range, set here to go back 35 days.
Before collecting new payments, the function queries the Payments table to compile a list of previously imported payments within the same date range. As it processes the payments, it checks against this list to skip any already-imported entries, importing only new ones into the Payments table. Finally, the function links all retrieved payments to the Orders table to ensure accurate calculations. This setup enables a portal showing registered payments within the system.
While managing and updating payment data in Conta remains crucial, the ability to view orders and track which ones are paid is essential when accepting new orders.
Example
Set Variable [$res; ACF_Run("ContaInvoicePayments"; Get(CurrentDate)-35)]
This retrieves and processes all payments from the past 35 days, skipping any that have already been imported.
A little special remark regarding the last linking of the payments to the orders. Suppose we have a OrderFK field in the payments table, but we also have InvoiceNo in both tables. We could have the relation on InvoiceNo, and that would work great. As we are accustomed to use the PrimaryKey in relations, there is a good idea to use that instead. For this to work, we do a final SQL Update to ensure the relational linking work between the Orders table and the Payments table.
UPDATE Payments
SET OrderFK = (SELECT PrimaryKey FROM Orders WHERE Orders.InvoiceNo = Payments.InvoiceNo)
WHERE Payments.OrderFK IS NULL OR Payments.OrderFK = ''
The SQL processes all records in the Payments table where the OrderFK is null or has an empty value. For each, we use a subquery to select the PrimaryKey in the Orders table and set it to OrderFK.
Some SQL dialects allow us to use relations when updating instead, but not FileMaker SQL. This method works OK.
