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

      • AI generated meeting notes associated to Account or Deal

        As our organization works to improve efficiency we are looking for a solution to leverage AI to generate meeting notes and then add those notes to a CRM record such as an Account or Deal. I see Zoho has a Notebook AI offering that talks about the ability
      • Stock count by bin location

        Is there a configuration to make a stock count by bin or area and not by product. these is useful to manage count by area Regards
      • Add Prebuilt "Partner Finder" Template with Native Zoho CRM Integration in Zoho Sites To: Zoho Sites Product Team

        Hi Zoho Team, We hope you're doing well. We would like to request a prebuilt "Partner Finder" template for Zoho Sites, modeled after your excellent implementation here: 🔗 https://www.zoho.com/partners/find-partner-results.html ✅ Use Case: Our organization
      • How Do I Refund a Customer Directly to Their Credit Card?

        Hi, I use books to auto-charge my customers credit card. But when I create a credit note there doesn't seem to be a way to directly refund the amount back to their credit card. Is the only way to refund a credit note by doing it "offline" - or manually-
      • How to share private Opportunities with whole org at an account level

        Opportunities are currently set to private, so our sales team only sees their own opportunities, along with their manager and upper leadership. The need is the ability for the rest of the Org to see the opportunities at an account level, not within the
      • Can we generate APK and IOS app?

        Dears, I want to know the availability to develop the app on zoho and after that .. generate the APK or IOS app  and after that I added them to play store or IOS store.. Is it possible to do this .. I want not to use zoho app or let my customers use it. thanks 
      • Limitation with Dynamic Email Attachment Capture

        I've discovered a flaw in how Zoho Creator handles email attachments when using the Email-to-Form feature, and I'm hoping the Zoho team can address this in a future update. The Issue According to the official documentation, capturing email attachments
      • Zoho Creator customer portal users

        Hi, I'm in a Zoho One subscription with our company. I'm running a project now that involves creating a Zoho Creater application and using the Zoho Creator Customer Portal.  At most we need 25 customer portal users. In our Zoho One plan we only get 3
      • Why is Zoho Meeting quality so poor?

        I've just moved from Office 365 to Zoho Workplace and have been generally really positive about the new platform -- nicely integrated, nice GUI, good and easy-to-understand control and customisation, and at a reasonable price. However, what is going on
      • Zoho Learn Course Completion Notifications/Triggers/API

        Zoho Learn works great and will suit our course creation needs, but it appears to be lacking a bit when it comes to integration with other Zoho services (creator etc.) when it comes to course completion. 1) Is there an API or Zoho Flow trigger for when
      • 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
      • Sorting a list of record acquired from the zoho.crm.searchRecords function.

        This is something for which I'm trying to figure out a straightforward way to do. The searchRecords does a great job fetching me the records that I want. However, in some cases, where it returns multiple records, I want it to sort the returned list by date of creation of that record, so that when I do records.get(0), I get the most recent record.  As an example, here's my sample pseudo code: records = zoho.crm.searchRecords("Clients", "Office_Number:equals:123456"); Now the "records" list above contains
      • Enhanced Recording Permission Controls for Zoho Cliq Meetings (Similar to Zoom)

        Hello Zoho Cliq Team, We hope you are doing well. We would like to request an enhancement to the recording permission functionality in Zoho Cliq Meetings. Current Limitation: in Zoho Cliq Only hosts and co-hosts can record a meeting. Participants cannot
      • Phone Connection

        When on a call the person on the other end complains that there is static, I am cutting in and out or they can't hear me all. This happens on the cell connection as well.
      • Ability to Edit YouTube Video Title, Description & Thumbnail After Publishing

        Hi Zoho Social Team, How are you? We would like to request an enhancement to Zoho Social that enables users to edit YouTube video details after the video has already been published. Your team confirmed that while Zoho Social currently allows editing the
      • Can't add a sender adress from zoho campaigns

        hi, I need to change the sender address for a campaign.  When i try to add it i get a message to say 'duplicated email address found while adding your sender address'.  This is the first campaign i'm sending so I don't understand why this message is displayed? Thanks Jane 
      • Zoho CRM Portal Field Level Permission Issue

        Hi Support Team, I am using the Zoho CRM Portal and configuring field-level editing permissions. However, we are unable to restrict portal users from editing certain fields. We have created a portal and provided View and Edit (Shared Only) access for
      • Admin asked me for Backend Details when I wanted to verify my ZeptoMail Account

        Please provide the backend details where you will be adding the SMTP/API information of ZeptoMail Who knows what this means?
      • This domain is not allowed to add. Please contact support-as@zohocorp.com for further details

        I am trying to setup the free version of Zoho Mail. When I tried to add my domain, theselfreunion.com I got the error message that is the subject of this Topic. I've read your other community forum topics, and this is NOT a free domain. So what is the
      • This user is not allowed to add in Zoho. Please contact support-as@zohocorp.com for further details

        Hello, Just signed up to ZOHO on a friend's recommendation. Got the TXT part (verified my domain), but whenever I try to add ANY user, I get the error: This user is not allowed to add in Zoho. Please contact support-as@zohocorp.com for further details I have emailed as well and writing here as well because when I searched, I saw many people faced the same issue and instead of email, they got a faster response here. My domain is: raisingreaderspk . com Hope this can be resolved.  Thank you
      • Need Faster Help? Try Live Chat Support

        Hello there, We understand that sometimes, whether you’re facing an issue, exploring a feature, or need quick clarification, sending an email and waiting for a response just doesn’t cut it. You need answers, and you need them now. That’s exactly why we
      • Export History timeline

        Hi, I have an idea, bout zoho desk history of the ticket it would be great if the agent or admin of the zoho desk can export the timeline of the ticket history for agent report or on other matter.
      • Desk fails to create a new ticket on Reply email

        When I send a direct email to support@mysite.com, Desk will create a new ticket as expected. When I REPLY to an email sent from support@mysite.com, Desk will NOT generate a new ticket. This is very bad. How can I fix this? Use case: In a separate system
      • Condition based aggregate fields in subforms

        Hello everyone, We're excited to inform you about the latest enhancements made to our aggregate field capabilities in subforms; create aggregate fields based on conditions! An aggregate field is a column on which a mathematical function has been applied.
      • Ask the Experts 25: Experience the full spectrum of Zoho Desk’s autumn and spring releases for 2025

        Hello Everyone, We’re on the 25th episode of our ATE series! It's a true milestone in our live community interactions! It’s been an amazing journey since we started in October 2018. Zoho Desk has come a long way, evolving with the support of a wonderful
      • Addin Support in Zoho Sheet

        Is there any addin support available in zoho sheet as like google marketplace to enhance productivity by connecting with other apps, providing AI data analysis, streamlining business processes, and more?
      • Mass Update of Lookup Fields not possible

        Hello List I've created a custom field for Leads and Contacts 'Current Campaign'. This is very Handy as I can filter leads and then related them to a campaign. Everything ready, but then I realized that mass update doesn't work for lookup fields... a
      • 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
      • Function #61: Automatically add free item to the invoice based on item quantity

        Hello everyone, and welcome back to another Custom Function Friday! During holiday seasons or special promotions, businesses offer deals like BOGO (Buy One, Get One), Buy 3 Get 1 Free, Buy 2 at 50% off, and much more to attract customers. These promotions
      • TArgets To Accounts (Modules)

        How can i set sale target to Customers (Accounts Module)
      • Profit on Sales order

        Hi, would it be possible to implement a column at the Sales order overview of Purchase amount? So a field with the amount of all purchase related to this Sales order? This is very usefull so you will see the profit you made on this deal. I tried to get
      • Notes for Items for Future Purchase Order

        Next time when I order an item, tau have to make some changes in it, that order has to be placed after 4-5 months, I want to save those changes or points somewhere in the item, how will that be possible..
      • Schemes of different tyoe

        How can easily apply hourly, day wise or month wise  schemes on Bill, Quantity, and other schemes. Like I want to apply a scheme  Form today to next 7 days .where i can mention in zoho books so scheme will implement automatically to all customers and
      • Alphabetically

        How can i arrange alphabetically - (Manage Manufacturer) Field in Item Master 
      • Clients not receiving emails

        I've been informed that my emails are not being received. Is there anything that I should look into to rectify this? Many thanks!
      • Custom validation in CRM schema

        Validation rules in CRM layouts work nicely, good docs by @Kiran Karthik P https://help.zoho.com/portal/en/kb/crm/customize-crm-account/validation-rules/articles/create-validation-rules I'd prefer validating data input 'closer to the schema'
      • Contact data removes Account data when creating a quote

        Hi, Our customer has address fields in their quote layout which should be the address of the Account. They prefill the information, adding the account name - the address data is populated as per what is in the account - great. However when they then add
      • Enterprise subscription support

        My organization sells subscription services to enterprise customers, which is a different model from the consumer subscription model that Zoho Billing has been designed to support and I beleve this capability should be added. An enterprise subscription
      • Recruit paid support?

        Hi all, Could anyone who has paid support package advise if it provides value for money with regards to support response times? Exploring the idea as unfortunately when we have faced issues with Recruit it has been a 7+ day timescale from reporting to
      • Free Plan mail accounts details

        In the zoho mail pricing there's a free plan that includes: FREE PLAN Up to 25 Users 5GB* /User, 25MB Attachment Limit Webmail access only. Single domain hosting. I need to make sure that I'm able to create multiple email accounts in the form of: name@domain.com
      • Next Page