Send a new invoice data from Books to local certified solution via API json due local compliance

Send a new invoice data from Books to local certified solution via API json due local compliance

Greetings,  
I hope you are doing well and staying safe.  

Due to local compliance regulations, I am required to issue invoices exclusively using locally certified software, which Zoho Books is not. However, we would like to continue using Zoho Books, so we need to send invoice data to an external certified solution each time a new invoice is issued. This external system should automatically generate a corresponding invoice, essentially mirroring the one created in Zoho Books.  

I have access to the API documentation for the external certified solution and have attempted to create a custom function to extract invoice data, format it in JSON, and send it to the external system. However, due to my limited knowledge, I have been unable to save the custom function successfully, as the Deluge editor consistently flags syntax errors.  

The API documentation for the external solution can be found here: https://api.factplus.co.ao/documentation/  

Below are some of the approaches I have attempted:  

===
void EnviarFctraParaFctpls( Map invoice, Map organization, Map user )
{
    // A função já recebe os detalhes da fatura e organização como 'invoice' e 'organization'
    // Não precisamos usar zoho.books.getRecordsByID para os dados básicos da fatura.
    // Usaremos 'invoice' diretamente.

    // 1. Extrair Detalhes da Fatura (diretamente do 'invoice' Map)
    invoiceData = invoice; // 'invoice' já é o mapa com os dados da fatura
    organizationId = organization.get("organization_id"); // ID da sua organização no Zoho Books

    invoiceNumber = invoiceData.get("invoice_number");
    invoiceDate = invoiceData.get("date"); // Formato 'YYYY-MM-DD'
    dueDate = invoiceData.get("due_date"); // Formato 'YYYY-MM-DD'
    reference = invoiceData.get("reference_number"); // Pode usar o número de referência do Zoho Books
    currency = invoiceData.get("currency_code");
    // observation = invoiceData.get("notes"); // Supondo que 'notes' seja para observações
    
    // ATENÇÃO: Verifique na documentação do Factplus como lidar com 'retention'.
    // Se o Zoho Books não tiver um campo direto para 'retention', você pode precisar de lógica extra
    // ou definir como "0" se não for aplicável no seu caso.
    retention_value = "0"; 
    
    // Dados do Cliente
    customerData = invoiceData.get("customer_details");
    clientName = customerData.get("customer_name");
    clientNIF = customerData.get("vat_reg_no"); // Assumindo que NIF seja o VAT Registration Number
    clientEmail = customerData.get("email");
    clientCity = customerData.get("city");
    clientAddress = customerData.get("billing_address").get("address"); // Endereço de fatura
    clientPostalCode = customerData.get("billing_address").get("zip"); // CEP de fatura
    clientCountry = customerData.get("billing_address").get("country"); // País de fatura

    // Itens da Fatura
    lineItems = invoiceData.get("line_items");
    factplusItems = collection(); // Coleção para armazenar os itens formatados para o Factplus

    for each item in lineItems
    {
        // Para itemcode, é ideal usar um ID que seja único e identificável no Factplus.
        // item.get("item_id") é o ID interno do Zoho Books, o que pode não ser ideal se o Factplus
        // espera um código de item de produto/serviço. Considere usar item.get("name") ou um campo personalizado.
        itemCode = item.get("item_id"); 
        description = item.get("description");
        price = item.get("rate");
        quantity = item.get("quantity");
        taxRate = item.get("tax_percentage"); // Taxa de imposto
        discount = item.get("discount"); // Desconto por linha de item
        
        // ATENÇÃO: exemption_code e retention por item precisam ser verificados na API do Factplus.
        exemptionCode = ""; // Valor padrão, ajuste se tiver campo correspondente
        itemRetention = "0"; // Valor padrão, ajuste se tiver campo correspondente

        factplusItem = Map();
        factplusItem.put("itemcode", itemCode);
        factplusItem.put("description", description);
        factplusItem.put("price", price);
        factplusItem.put("quantity", quantity);
        factplusItem.put("tax", taxRate);
        factplusItem.put("discount", discount);
        factplusItem.put("exemption_code", exemptionCode);
        factplusItem.put("retention", itemRetention);
        
        factplusItems.add(factplusItem);
    }
    
    // 2. Construir o Objeto JSON para a API do Factplus
    // ATENÇÃO: SUBSTITUA 'SUA_CHAVE_API_AQUI' PELA SUA CHAVE DE 32 DÍGITOS DO FACTPLUS
    factplusPayload = Map();
    factplusPayload.put("apicall", "CREATE");
    factplusPayload.put("apikey", "SUA_CHAVE_API_AQUI"); // <-- SUA CHAVE API DO FACTPLUS AQUI!

    documentMap = Map();
    documentMap.put("type", "factura"); // Tipo de documento, confirme se "factura" é o correto
    documentMap.put("date", invoiceDate);
    documentMap.put("duedate", dueDate);
    documentMap.put("vref", invoiceNumber); // Usando o número da fatura como referência. Verifique se o Factplus aceita este formato.
    // A "serie" é crucial. O exemplo do Factplus mostra "2020". Você precisa definir uma série apropriada.
    // Se o Zoho Books não tiver um campo para série, pode ser um valor fixo ou derivado.
    documentMap.put("serie", "2024"); // <-- ATENÇÃO: Defina a série correta para o Factplus (ex: "2024", "FS_A")
    documentMap.put("currency", currency);
    documentMap.put("exchange_rate", "0"); // Ajuste se houver taxa de câmbio
    // documentMap.put("observation", invoiceData.get("notes")); // Se usar campo de notas
    documentMap.put("retention", retention_value);

    clientMap = Map();
    clientMap.put("name", clientName);
    clientMap.put("nif", clientNIF);
    clientMap.put("email", clientEmail);
    clientMap.put("city", clientCity);
    clientMap.put("address", clientAddress);
    clientMap.put("postalcode", clientPostalCode);
    clientMap.put("country", clientCountry);
    
    factplusPayload.put("document", documentMap);
    factplusPayload.put("client", clientMap);
    factplusPayload.put("items", factplusItems);

    // Converter o mapa Deluge para string JSON
    jsonString = factplusPayload.toString();

    // 3. Fazer a Chamada HTTP POST para a API do Factplus
    // ATENÇÃO: Você PRECISA substituir "https://api.factplus.co.ao" pelo ENDPOINT COMPLETO
    // da API do Factplus para a criação de faturas.
    // Ex: "https://api.factplus.co.ao/v1/invoices" ou similar.
    factplusAPI_URL = "https://api.factplus.co.ao"; // <-- SUBSTITUIR PELO ENDPOINT ESPECÍFICO DE CRIAÇÃO DE FATURA

    // Cabeçalhos (Content-Type é essencial para JSON)
    headers = Map();
    headers.put("Content-Type", "application/json");

    // Executar a chamada API
    apiResponse = invokeurl
    [
        url : factplusAPI_URL
        type : POST
        headers: headers
        content : jsonString
    ];

    // 4. Tratar a Resposta da API
    info "Request sent to Factplus: " + jsonString; // Para depuração, mostre o que foi enviado
    info "Factplus API Response: " + apiResponse;

    // Adicione lógica para verificar a resposta aqui.
    // Ex: if (apiResponse.get("status") == "success") { ... }
    // ou if (apiResponse.get("code") == 200) { ... }
    // Logar erros se a resposta indicar falha e talvez enviar um email de alerta.
    if (apiResponse.get("status") == "success") // Supondo que a API retorne um campo 'status'
    {
        info "Fatura enviada com sucesso para o Factplus!";
        // Opcional: Atualizar a fatura no Zoho Books com um campo de status "Enviado para Factplus"
        // Ou armazenar o ID de retorno do Factplus.
    }
    else
    {
        error "Erro ao enviar fatura para o Factplus: " + apiResponse.get("message"); // Supondo campo 'message'
        // Opcional: Enviar email de erro para o cliente ou para o administrador
    }
}
===

And

===
// Função para enviar fatura do Zoho Books para o Factplus
// Parâmetro: invoice_id (ID da fatura criada)
invoice_id = input.invoice_id;

// Obter detalhes da fatura do Zoho Books
invoice = zoho.books.getRecordsByID("Invoices", organization_id, invoice_id);
invoice_data = invoice.get("invoice");

// Mapear dados do cliente
customer_id = invoice_data.get("customer_id");
customer = zoho.books.getRecordsByID("Contacts", organization_id, customer_id);
customer_data = customer.get("contact");
client_map = Map();
client_map.put("name", customer_data.get("contact_name"));
client_map.put("nif", customer_data.get("tax_reg_no", ""));
client_map.put("email", customer_data.get("email", ""));
client_map.put("city", customer_data.get("billing_address").get("city", ""));
client_map.put("address", customer_data.get("billing_address").get("address", ""));
client_map.put("postalcode", customer_data.get("billing_address").get("zip", ""));
client_map.put("country", customer_data.get("billing_address").get("country", "Angola"));

// Mapear itens da fatura
items_list = List();
for each item in invoice_data.get("line_items")
{
    item_map = Map();
    item_map.put("itemcode", item.get("item_id", "ITEM" + item.get("line_item_id")));
    item_map.put("description", item.get("name"));
    item_map.put("price", item.get("rate").toString());
    item_map.put("quantity", item.get("quantity").toString());
    item_map.put("tax", "14"); // Ajuste conforme a tributação aplicável
    item_map.put("discount", item.get("discount", "0").toString());
    item_map.put("exemption_code", "");
    item_map.put("retention", "");
    item_map.put("unit", "Unidade");
    items_list.add(item_map);
}

// Construir o corpo da requisição para o Factplus
payload = Map();
payload.put("apicall", "CREATE");
payload.put("apikey", "SUA_CHAVE_API_FACTPLUS"); // Substitua pela sua chave de API
document_map = Map();
document_map.put("type", "factura");
document_map.put("date", invoice_data.get("date"));
document_map.put("duedate", invoice_data.get("due_date"));
document_map.put("vref", invoice_data.get("invoice_number"));
document_map.put("serie", invoice_data.get("date").left(4)); // Ano da fatura
document_map.put("currency", "AOA");
document_map.put("exchange_rate", "0");
document_map.put("observation", "");
document_map.put("retention", "0");
payload.put("document", document_map);
payload.put("client", client_map);
payload.put("items", items_list);

// Enviar requisição para o Factplus
headers = Map();
headers.put("Content-Type", "application/json");
response = invokeurl
[
    type: POST,
    parameters: payload.toString(),
    headers: headers,
    connection: "FactplusAPI"
];

// Logar a resposta para depuração
info response;
===

Any help?
Thanks in advance.
    • Recent Topics

    • Calls undetected

      Zoho is not reading calls made.
    • Multi-currency and Products

      One of the main reasons I have gone down the Zoho route is because I need multi-currency support.  However, I find that products can only be priced in the home currency, We sell to the US and UK.  However, we maintain different price lists for each. 
    • Archiving Contacts

      How do I archive a list of contacts, or individual contacts?
    • How to add to Subforms via Zapier with Zoho Writer?

      I have the following layout for a Zoho Writer Document. As you can see there is a repeating subform taking in "Items". I am trying to make a Zapier integration with it, and I can see there is 1 field saying: "Items", but it does not specify how I'm supposed
    • Zoho Books | Product updates | November 2025

      Hello users, We’ve rolled out new features and enhancements in Zoho Books. From translating email notification templates to the new transaction locking restrictions, explore the updates designed to enhance your bookkeeping experience. Making Tax Digital
    • Missing information data Zoho inventory

      there some missing data in Zoho inventory connection. pick list stock counts bin location we have requested it via mail and the support team doesn’t gove feedback. has anyone achieve to get these info or to ask other ya les
    • Calendar Events Issues

      Not able to view scheduled events on my calendar
    • Extensions 101 webinar series: Build, integrate, and monetize with extensions

      Attention developers! Are you ready to take your extension development skills to the next level? We're excited to bring back the Extensions 101 webinar series with an expanded lineup of Zoho products and an introduction to more platform features. Last
    • Custom Related List Inside Zoho Books

      Hello, We can create the Related list inside the zoho books by the deluge code, I am sharing the reference code Please have a look may be it will help you. //..........Get Org Details organizationID = organization.get("organization_id"); Recordid = cm_g_a_data.get("module_record_id");
    • Where are recordings stored?

      I have hosted a couple of test meeting, used the "record" button to start and stop the recording but I am unable to find where are those recordings saved?  Can anybody help? Thanks
    • Zoho Desk's integration with Microsoft PowerBI delivers advanced analytics insights

      Hello everyone, Gaining advanced insights through reports and dashboards is one of the critical requirements of every business. In addition to key metrics tracked in Zoho Desk, such as agent performance, SLA adherence, and ticket lifecycle, businesses
    • Create static subforms in Zoho CRM: streamline data entry with pre-defined values

      Last modified on (9 July, 2025): This feature was available in early access and is currently being rolled out to customers in phases. Currently available for users in the the AU, CA, and SA DCs. It will be enabled for the remaining DCs in the next couple
    • IMAP error message in Zoho mail

      I cannot send emails today. Everything fine for years until today. Get a message: "You are yet to enable IMAP for your account. Please contact your administrator". Does anyone know how to correct this?
    • Enhancements to Zoho Map integration tasks

      Hello everyone, We're excited to announce enhancements to the Zoho Map integration tasks in Deluge, which will boost its performance. This post will walk you through the upcoming changes, explain why we're making them, and detail the steps you need to
    • IMAP stopped working today

      Hello! I've been a paid customer for more than 10 years, IMAP was always working fine. But today this is the error I've got on my iPhone: I've tried toggling the IMAP for my account (Mail -> Settings -> Mail accounts) off and on again, but that did not
    • Duplicating report but custom layout does not

      Dear Zoho Creator, I need to duplicate a report into 10 copies, but unfortunately the custom layout (detail view) doesn’t copy along with it. I tried exporting and importing the custom layout, but the field mappings are incorrect. I believe everyone are
    • Are custom portals accessible on the Zoho learn smartphone app?

      In other words, can users external to my organisation, once signed up, use the app in the same way as internal users? Thanks
    • When will Zoho Learn be able to support SCORM files on the mobile app?

      When I click the SCORM content, I just get a message saying it's not possible yet. Yet implies that it will be coming soon. All I'm asking for is a realistic timeline so I know whether or not to invest my time in using it. If it will be soon, then I will
    • Zoho Books/Inventory - Update Marketplace Sales Order via API

      Hi everyone, Does anyone know if there is a way to update Sales Orders created from a marketplace intigration (Shopify in this case) via API? I'm trying to cover a scenario where an order is changed on the Shopify end and the changes must be reflected
    • Conditional Layouts On Multi Select Field

      How we can use Conditional Layouts On Multi Select Field field? Please help.
    • Multiple columns in a form

      I am evaluating Zoho Creator. However, I am seeing almost no layout control on a form.  Just a basic 1 or 2 column format that is then imposed on the entire form.  That's not going to work for many, many real world cases. We need multiple columns per line, and we need each line/section to occupy a single column or be able to span the columns.   Someone please tell me that I'm missing something and the capability is actually there.  
    • Global search

      Hi! I think it would be great to have a global search that would give you results from all records of a database, no only for a single field of a single form as we have now. Thanks!
    • Any insights about API/v2? Having problem for a while.

      I don't know why it is throwing a 404 error, my report name is correct. Has someone had this issue and how you fix it?
    • Edit QR code with redirect to form

      Guten morgen, wir haben ein Formular Reklamation_erstellen. Dort soll ein QR Code erstellt werden, der im Lieferschein angezeigt wird. Beim Scannen auf dem soll das jeweilige Formular zum BEARBEITEN geöffnet werden. Leider bekomme ich es nur so hin, dass
    • Getting all the ingredients together for baking an app

      Good day everyone. After reading a lot of the help docs and watching videos, I now started on my app. To prevent hours and hours wasted on going down the wrong track, I would like some clarification on the following. But first some background: I have
    • Help Needed with Configuring ZC Microservice

      I'm attempting to create a simple microservice, but am running into problems with scope and auth. Using Custom API Builder, here's my setup: 1. Method: GET 2. Auth: OAuth2 3. User Scope: All users 4. Response: Standard 5. Function: A function that returns
    • Creator Simplified #10: Predefine Form Field Values and Make Them Read-Only for Users

      Hey Creators, Ready for this week's tip in the Creator Simplified series? Today, we will explore how to have read only fields in a form. Use Case: Assume a scenario where the default value for a Department field needs to be English Literature, but you
    • Direct link to Record Summary

      Hi everyone, In one of my reports, I have built a Record Summary template to display the details of one record. I would like to be able to link directly to this Record Summary once I submit a new record, without having to go to the list of records first and click on View. Is there a possibility to do so ?  Should I use the URL by passing some parameters ? Thank you very much for your help ! Guillaume
    • To Assign a genrated pdf to a file upload field using delug

      content = "<html><body>HTML Content on page One <div style='page-break-after:always'></div> HTML Content on page Two </body></html>"; file = zoho.file.convertToPDF(content); file.setFileName("Name of the file"); <variableName> = <FormLinkName>[ID == input.ID];
    • Zoho Mail : Email Outgoing Blocked

      I suddenly received the following message yesterday. I cannot send any mail. Please resolve as soon as possible, I cannot work without sending email. Dear User, We regret to inform you that your email outgoing has been blocked and you will not be able
    • Creator and Tables

      Good day. I am trying to create my first application. I have imported my data into Tables and am creating my app in Creator. I do not see my tables and cannot see how to write forms data to a table. Even the Workflow just uses the form. In one of the
    • Calendar week view: Today + 6

      Is there anyway to have the calendar change dynamically based on the date? Due to the amount of events, we only display a week at a time, but towards the end of the week, we can no longer see ahead to next week (without changing it manually every time).
    • customer Name and address details

      i created one application there is no customer details in that . how to add customer details and
    • Recalculate every row in the subform

      Hello, Can anyone help me with a script, please? I have an issue. Sometimes it happens, that in a multi row subform one of the rows show an incorrect row total value. Not really understand how it can happen, if I have a 20 row subform, 19 rows show correct
    • Creating Repeat Forms that remove redundancies

      I wanted to understand if you can make multi-layer forms that reduce the need for users to input information in again and again. We want a form that our suppliers fill out per ingredient they sell, and the end result should have the Ingredient (Section
    • What is the difference between the free plan and the mail lite plan?

      What is the difference between the free plan and the mail lite plan? How many emails can I send per day?
    • Unblock email

      Hi The outgoing mail from a client of me is blocked. I already made tickets and tickets are send to the EU desk but nobody is responding. The problem is already 4 days! There is absolutely no help from the support. I am really not satisfied at all! Can
    • Domain verification failure

      Hello Zoho Support, I purchased my domain directly through Zoho Mail, but the domain verification keeps failing with the message “TXT verification failed.” I’ve already waited and retried several times, but it still won’t verify. Could you please manually
    • Unable to send message;Reason:554 5.1.8 Email Outgoing Blocked.

      My email account is unable to send emails, and I urgently need to use it. How can I resolve this?If there is anything we have done wrong, please let us know in advance so we can actively cooperate to improve. User ID: 850482493
    • URGENT: Email stopped workin - can't access admin panel

      For some reason email sending stopped working. When I try to send an email it fails with "Unable to send message;Reason:451 4.7.1 Temporary system error" I can receive email just fine I see in my notifications some errors about the MX records, however
    • Next Page