BLVCKFX
3/11/2020 - 6:51 PM

Import electronic invoices

Custom RunBaseBatch class to import electronic invoices.#SADA => A_ImportEInvoiceA_ImportEInvoice.PNG

// This is a framework class. Customizing this class may cause problems with future upgrades to the software.
class A_ImportEInvoice extends RunBaseBatch
{
    // Packed variables
    UserName    user;
    str         password;
    str         access_token,user_id;
    FromDate    fromDate;
    ToDate      toDate;

    // Dialog fields
    DialogField     dlgUser;
    DialogField     dlgPassword;

    DialogField     dlgFromDate;
    DialogField     dlgToDate;

    #define.CurrentVersion(2)
    #define.Version1(2)
    #localmacro.CurrentList
        user,
        password,
        fromDate,
        toDate
    #endmacro
}


/// <summary>
///    Indicates whether the class is shown in the list of <c>Journal</c> types.
/// </summary>
/// <returns>
///    true if the class is shown in the list of <c>Journal</c> types; otherwise, false.
/// </returns>
/// <remarks>
///    A class that can be used in a batch journal is a class where the same parameters can be used
///    repeatedly. The dialog box can be shown and the parameters can be changed, but parameters of some
///    classes might build on data that is only valid for a short time. Running a class two times with the
///    same parameters is not always possible. If the <c>RunBaseBatch.canGoBatch</c> method is false, this
///    method will not have any effect.
/// </remarks>
public boolean canGoBatchJournal()
{
    return true;
}


private System.String connect()
{
    System.Net.WebRequest   requestlogin;
    System.Net.WebResponse  responseLogin;
    System.String           postDataLogin, stringResponseLogin;
    System.Byte[]           byteArrayLogin;
    System.Text.Encoding    utf8;
    System.IO.Stream        requestStreamLogin, responseStreamLogin;
    System.IO.StreamReader  streamReaderLogin;
    str                     strRequestLogin;
    strRequestLogin         = A_RquestImportEinvoiceFileParameters::find().URLLogin;//"https://e-invoice7.conserva.cloud/api/v1/auth/";
    requestlogin            = System.Net.WebRequest::Create(strRequestLogin);

    requestlogin.set_Method("POST");

    postDataLogin           = strFmt(A_RquestImportEinvoiceFileParameters::find().StrLogin,user,Password);
    //postDataLogin           = "{\"username\":\"alteanet\",\"password\":\"Acitorio1234\"}";

    utf8                    =   System.Text.Encoding::get_UTF8();
    byteArrayLogin          =   utf8.GetBytes(postDataLogin);

    requestlogin.set_ContentType("application/json");
    requestlogin.set_ContentLength(byteArrayLogin.get_Length());

    requestStreamLogin      =  requestlogin.GetRequestStream();

    requestStreamLogin.Write(byteArrayLogin,0,byteArrayLogin.get_Length());


    responseLogin           =   requestlogin.GetResponse();

    responseStreamLogin     =   responseLogin.GetResponseStream();
    streamReaderLogin       =   new System.IO.StreamReader(responseStreamLogin);
    stringResponseLogin     =   streamReaderLogin.ReadToEnd();
    return stringResponseLogin;

}


/// <summary>
///    Returns a class that contains the methods that are described by the <c>RunBaseDialogable</c>
///    interface.
/// </summary>
/// <returns>
///    A class that contains the methods that are described by the <c>RunBaseDialogable</c> interface.
/// </returns>
/// <remarks>
///    A dialog box can be either built by using the <c>Dialog</c> class or by using a class that is
///    created in the Application Object Tree (AOT).
/// </remarks>
public Object dialog()
{
    DialogRunbase       dialog = super();
    DialogGroup         dlgGroup;
    #resAppl
    ;
    dlgGroup = dialog.addGroup("Credenziali di accesso");
    dlgGroup.columns(3);

    dialog.addImage(#ImageEmployee);


    dlgUser = dialog.addField(extendedTypeStr(UserName));
    dlgPassword = dialog.addField(extendedTypeStr(Password));

    dlgGroup = dialog.addGroup("Data ricevimento files");
    dlgGroup.columns(3);

    dialog.addImage(#ImageProfileCalendar);


    dlgFromDate = dialog.addField(extendedTypeStr(FromDate));
    dlgToDate = dialog.addField(extendedTypeStr(ToDate));

    return dialog;
}


public void dialogPostRun(DialogRunbase dialog)
{
;
    super(dialog);
}


private void findAcces(System.String _stringResponseLogin)
{
    container               conResponseLogin, testCont;
    str                     conLineValue;
    int                     positionFind,conLength,conLengthLine,i;
    str                     strRequestLogin, test;

    conResponseLogin = str2con(_stringResponseLogin);


    for (i = 1 ; i <= conLen(conResponseLogin) ; i++)
    {
        conLineValue    = conPeek(conResponseLogin, i);
        conLengthLine   = strLen(conLineValue);

        if(subStr(conLineValue,1,23) == '"data":{"access_token":')
        {
            access_token = substr(conLineValue,24,conLengthLine);
            access_token = strRem(access_token,'"');
            continue;
        }

        if(subStr(conLineValue,1,10) == '"user_id":')
        {
            user_id = substr(conLineValue,11,conLengthLine);
        }

        if(access_token && user_id)
        {
            break;
        }
    }
}


public boolean getFromDialog()
{
;
    user        = dlgUser.value();
    password    = dlgPassword.value();

    fromDate    = dlgFromDate.value();
    toDate      = dlgToDate.value();

    return super();
}


private void importInvoice()
{
    System.Net.WebRequest   requestInvoiceList;
    System.Net.WebResponse  responseInvoiceList;
    System.String           postDataInvoiceList, stringResponseInvoiceList;
    System.Byte[]           byteArrayInvoiceList;
    System.IO.Stream        requestStreamInvoiceList, responseStreamInvoiceList;
    System.IO.StreamReader  streamReaderInvoiceList;

    System.Net.WebHeaderCollection  headerInvoiceList = new System.Net.WebHeaderCollection();

    container               conResponseInvoiceList,conResponseInvoices;
    str                     strRequestInvoiceList;
    CLRObject               CLRObject;
    System.Exception        e;
    Map                     getData, dataMap;
    container               data,operationSet, operation, dataCont,conNumRows, conData, conInvoice,conFileDownloaded,conFileNotDownloaded;
    str                     result,invoiceID,fileName,originalFilename;
    Filename                filepath;
    Filename                fileExt;
    int                     num, num2, pos = 1,numRow, numData, endData,FileDownloaded,FileNotDownloaded,i;
    #file
    str convertDate(InvoiceDate _date)
    {
        return date2str(_date,321,2,DateSeparator::Hyphen,2,DateSeparator::Hyphen,4)  ;
    }
    ;
    headerInvoiceList.Add('einvauth', access_token);
    strRequestInvoiceList         = strfmt('https://e-invoice7.conserva.cloud/api/v1/users/%1/invoices/p?lastKeyVal=&pageSize=12&pagination=true&page=1&searchFilter={"metadata":[{"index":0,"name":"DataRicezione","label":"Data Ricezione","data_type":"d","input_type":"text","options_list":[],"value":["2019-10-01T00:00:00.000Z","2019-12-01T00:00:00.000Z"],"required":false,"id":1}],"workflow_id":"","workflow_state_code":[""]}',user_id);
    strRequestInvoiceList         = strfmt(A_RquestImportEinvoiceFileParameters::find().URLInvoiceList,user_id,convertdate(fromDate),convertdate(toDate));
    //strRequestInvoiceList         = strfmt('https://e-invoice7.conserva.cloud/api/v1/users/%1/invoices/p?lastKeyVal=&pageSize=12&pagination=true&page=1',user_id);

    CLRObject = System.Net.WebRequest::Create(strRequestInvoiceList);
    requestInvoiceList = CLRObject;

    requestInvoiceList.set_Headers(headerInvoiceList);
    requestInvoiceList.set_Method("GET");


    requestInvoiceList.set_ContentType("application/json");
    responseInvoiceList = requestInvoiceList.GetResponse();

    requestStreamInvoiceList     = responseInvoiceList.GetResponseStream();

    streamReaderInvoiceList      =   new System.IO.StreamReader(requestStreamInvoiceList);
    stringResponseInvoiceList     =   streamReaderInvoiceList.ReadToEnd();

    getData = RetailCommonWebAPI::getMapFromJsonString(stringResponseInvoiceList);

    if (getData.exists('data'))
    {
        operationSet    = getData.lookup('data');
    }


    numRow = A_ImportEinvoice::recuperaValore(operationSet, "totalRows");
    conData = A_ImportEinvoice::recuperaContainer(operationSet, "data");
    endData = conLen(conData);

    info(strFmt("@SAD504",numRow));

    for(num = 1 ; num<=numRow ; num++)
    {
        conInvoice          = conPeek(conData,endData);
        invoiceID           = A_ImportEinvoice::recuperaValore(conInvoice, "id");
        fileName            = A_ImportEinvoice::recuperaValore(conInvoice, "file_name");
        originalFilename    = fileName;

        fileExt     = strMin();

        while (fileExt != #xml)
        {
            [filepath,fileName,fileExt] = fileNameSplit(fileName);
        }

        fileName = fileName + #xml;

        try
        {
            this.importSingleInvoice(invoiceID,fileName);
            conFileDownloaded = conIns(conFileDownloaded,1,originalFilename);
            FileDownloaded++;
            endData--;
        }
        catch
        {
            conFileNotDownloaded = conIns(conFileNotDownloaded,1,originalFilename);
            FileNotDownloaded++;
            endData--;
            continue;
        }
    }

    i = 1;

    if(conLen(conFileDownloaded))
    {
        setPrefix(strFmt("%1 file scaricati"));

        for (i = 1 ; i <= conLen(conFileDownloaded) ; i++)
        {
            info(conPeek(conFileDownloaded,i));
        }

    }

    i = 1;

    if(conLen(conFileNotDownloaded))
    {
        setPrefix(strFmt("%1 file non scaricati"));

        for (i = 1 ; i <= conLen(conFileNotDownloaded) ; i++)
        {
            info(conPeek(conFileNotDownloaded,i));
        }

    }
}


private void importSingleInvoice(str _invoiceID, str _fileName)
{
    System.Net.WebRequest   requestInvoiceList;
    System.Net.WebResponse  responseInvoiceList;
    System.String           postDataInvoiceList, stringResponseInvoiceList;
    System.Byte[]           byteArrayInvoiceList;
    System.IO.Stream        requestStreamInvoiceList, responseStreamInvoiceList;
    System.IO.StreamReader  streamReaderInvoiceList;

    System.Net.WebHeaderCollection  headerInvoiceList = new System.Net.WebHeaderCollection();

    container               conResponseInvoiceList,conResponseInvoices;
    str                     strRequestInvoiceList;
    CLRObject               CLRObject;
    System.Exception        e;

    Map                     getData, dataMap;
    container               data,operationSet, operation, dataCont,conNumRows, conData, conInvoice;
    str                     result;
    int                     num, num2, pos = 1,numRow, numData, endData ;

    str                     strBase64;

    DocuValueFile           docuValueFile;
    DocuRef                 docuRef;
    DocuValue               docuValue;
    BinData                 binData     = new BinData();
        System.Exception ex;
    container               content;



    headerInvoiceList.Add('einvauth', access_token);

    strRequestInvoiceList   =   strFmt(A_RquestImportEinvoiceFileParameters::find().URLSingleInvoiceList,user_id,_invoiceID);

    CLRObject = System.Net.WebRequest::Create(strRequestInvoiceList);
    requestInvoiceList = CLRObject;

    requestInvoiceList.set_Headers(headerInvoiceList);
    requestInvoiceList.set_Method("GET");


    requestInvoiceList.set_ContentType("application/json");
    responseInvoiceList = requestInvoiceList.GetResponse();

    requestStreamInvoiceList     = responseInvoiceList.GetResponseStream();

    streamReaderInvoiceList      =   new System.IO.StreamReader(requestStreamInvoiceList);

    stringResponseInvoiceList     =   streamReaderInvoiceList.ReadToEnd();
    //this.strunz(stringResponseInvoiceList);

    //content = RetailCommonWebAPI::
    //content = str2con(stringResponseInvoiceList,":");
    //this.strunz(conPeek(content,5));
    try
    {
        getData = RetailCommonWebAPI::getMapFromJsonString(stringResponseInvoiceList);
    }
    //SN_IDALMASSO: Questa roba qui funziona, catcha l'eccezione SOLO rimuovendo il ttsbegin/ttscommit in metodo run.
    //(In realtà secondo me quel ttsbegin/commit è un po' un eccesso di zelo, probabilmente si può cambiare di posizione e metterlo più all'interno nella classe)
    //Però ci permette di capire dove sta l'errore nel caso
    catch (Exception::CLRError)
    {
         ex = ClrInterop::getLastException();
         if (ex != null)
         {
            ex = ex.get_InnerException();
            if (ex != null)
            {
                error(ex.ToString());
            }
        }
    }

    if (getData.exists('data'))
    {
        operationSet    = getData.lookup('data');
    }

    strBase64 = A_ImportEInvoice::recuperaValore(operationSet,"content");

    AifUtil::saveBase64ToFile(A_PurchEinvoiceParameters::find().PathUploadInvoice + _fileName, strBase64);

}


public boolean init()
{
    return true;
}


protected void new()
{
    super();
}


public container pack()
{
    return [#CurrentVersion,#CurrentList];
}


/// <summary>
///    Contains the code that does the actual job of the class.
/// </summary>
public void run()
{
    System.String   stringResponseLogin;
    #OCCRetryCount
    if (! this.validate())
        throw error("");

    try
    {
        ttsbegin;
        stringResponseLogin = this.connect();
        this.findAcces(stringResponseLogin);
        this.importInvoice();
        ttscommit;
    }
    catch (Exception::Deadlock)
    {
        retry;
    }
    catch (Exception::UpdateConflict)
    {
        if (appl.ttsLevel() == 0)
        {
            if (xSession::currentRetryCount() >= #RetryNum)
            {
                throw Exception::UpdateConflictNotRecovered;
            }
            else
            {
                retry;
            }
        }
        else
        {
            throw Exception::UpdateConflict;
        }
    }

}


public boolean runsImpersonated()
{
    return true;
}


public boolean unpack(container packedClass)
{
    Version version = RunBase::getVersion(packedClass);
;
    switch (version)
    {
        case #CurrentVersion:
            [version,#CurrentList] = packedClass;
            break;
        default:
            return false;
    }

    return true;
}


public boolean validate(Object _calledFrom = null)
{
    if(!fromDate || !toDate)
    {
        return checkFailed("Entrambe le date sono obbligatorie");
    }

    if(fromDate > toDate)
    {
        return checkFailed("Date non valide");
    }

    return true;
}


server static A_ImportEInvoice construct()
{
    return new A_ImportEInvoice();
}


// Here goes a description of the class
static ClassDescription description()
{
    return "Importazione fatture fornitore da web";
}


static void main(Args args)
{
    A_ImportEinvoice    A_ImportEinvoice;
;
    A_ImportEinvoice = A_ImportEinvoice::construct();

    if (A_ImportEinvoice.prompt())
        A_ImportEinvoice.run();
}


server static anytype recuperaContainer(container _con,str _label)
{
    int         posLocal;
    container   conLocal;
    posLocal = conFind(_con, _label);
    return conPeek(_con,posLocal+1);
}


server static anytype recuperaValore(container _con,str _label)
{
    int         posLocal;
    container   conLocal;
    posLocal = conFind(_con, _label);
    conLocal = conPeek(_con,posLocal+1);
    return conPeek(conLocal,1);
}