Technical Information
Teknisk informasjon for Semine integrasjonen
Installasjon og oppsett
Installasjon av .app fil:
Velge .app fil for Semine integrasjon, Aksepter og Deploy. Så blir integrasjonen publisert til BC.
Husk også å sette opp rettigheter for alle brukere. Finn en brukergruppe som dekker alle og legg inn tillatelsessettet:
Deretter må det gjøres et lite oppsett (søk i BC etter Semine setup eller Semine oppsett):
Når Organisasjon og Selskap er opprettet med tilgang i Semine, så må informasjon om api’et for Semine legges inn. Feltene: Url API,User API, Password API, ClientID, Client secret for API: Dette er informasjon som leveres av Semine, når disse er utfylt må det kjøres en Initialize funksjon som henter Semine Organisasjonsid’er og Semine Client Id’er. Velg så ønsket organsisasjonsid og klientid fra listen. Dersom ingenting vises så er noe av API informasjonen feil eller ikke satt opp riktig på Semine siden.
Dersom feltet Get Token URL er blank, angi denne:
https://osbazurefunc.azurewebsites.net/api/OsebergAPI/GetAPIAccessToken
Før data synkroniseres til Semine så må Dimensjoner markeres med Eksporter til Semine for de som skal være med i integrasjonen. Søk fram Dimensjoner og finn feltet til høyre i Dimensjonlisten. Huk av for de som skal være med.
Siste ledd som må kjøres er å synkronisere data ut til Semine:
Når alle data er synkronisert og dere ser data i Semine, så kan faktura opprettes og hentes til BC:
Alle fakturaer vil legge seg i listen her og om noe feiler ved oppretting av faktura i BC, så vil status angi dette. Alle med Success, har blitt overført og er klar for bokføring.
Henting av fakturaer kan gjøres automatisk ved å opprette/bruke Jobbkøen. Ved installasjon så skal det ha blitt opprettet en post automatisk:
Velg rediger for posten som står oppsatt med Codeunit: 83136. Andre poster for samme Codeunit kan slettes. Det er behov for kun 1. For å få den til å hente automatisk i perioder, så kan det defineres om du velger Rediger på posten:
Her angir du at det skal være et Gjentakende prosjekt, hvilke dager den skal kjøre på og hvor lang tid det skal være mellom hver kjøring. Når du lagrer dette og jobben har status Klar, så skal fakturaer bli hentet automatisk fra Semine, de vil da enten havne i en Kjøpskladd eller Kjøpsfaktura liste, avhengig av hva som er angitt i Semine oppsettet. Dersom jobben feiler, så bør Semine fakturalisten sjekkes for å se om det ligger noen fakturaer med status: Venter. Dersom det ikke gjør det, så kommer feil før faktura blir hentet. Kontakt da Semine for bistand. Når feilen er korrigert, så må status for jobben settes til Klar igjen.
Spesifikasjon av felter for entiteter som synkroniseres
Leverandør (Vendor):
Sent to api method (POST):
'api/v1.0/organizations/' + OrganizationId + '/clients/' + ClientId + '/suppliers'
StatusObject := 'Active'; //Set to InActive if Blocked:All or Blocked::Payment
JsObjectContact.Add('name', ContactLoop.Name);
JsObjectContact.Add('designation', '');
JsObjectContact.Add('phone', ContactLoop."Phone No.");
JsObjectContact.Add('email', ContactLoop."E-Mail");
JsArrayContact.Add(JsObjectContact);
JsObject.Add('code', Vendor."No.");
JsObject.Add('name', Vendor.Name);
JsObject.Add('organizationNumber', VatRegNo);
JsObject.Add('organizationAuthorityCode', VatRegNo);
JsObjectAddress.Add('street', Vendor.Address);
JsObjectAddress.Add('city', Vendor.City);
JsObjectAddress.Add('zipcode', Vendor."Post Code");
JsObjectAddress.Add('phone', Vendor."Phone No.");
JsObjectAddress.Add('email', Vendor."E-Mail");
JsObjectAddress.Add('country', CountryRegion.Code); //If empty set to 'NO'
JsObject.Add('address', JsObjectAddress);
JsObjectBankAccount.Add('bankName', 'Bank');
JsObjectBankAccount.Add('accountNumber', Vendor."Recipient Bank Account No.");
JsObjectBankAccount.Add('status', 'Active');
JsArrayBankAcocunt.Add(JsObjectBankAccount);
JsObjectBankAccount.Add('bankName', VendorBankAccount.Name) //If empty set to 'Bank'
JsObjectBankAccount.Add('accountNumber', VendorBankAccount."Bank Account No.");
//If Bank Account No = '' and IBAN <> '' then use IBAN
JsObjectBankAccount.Add('ibanAccountNumber', VendorBankAccount.IBAN);
JsObjectBankAccount.Add('swiftCode', VendorBankAccount."SWIFT Code");
JsObjectBankAccount.Add('status', 'Active');
JsArrayBankAcocunt.Add(JsObjectBankAccount);
JsObject.Add('bankAccounts', JsArrayBankAcocunt);
JsObject.Add('status', StatusObject);
GL Account (Finanskonto):
Api.SetMethod('api/v1.0/organizations/' + OrganizationId + '/clients/' + ClientId + '/accountingcodes');
Api.SetMethodRest('POST');
StatusObject := 'active'; // if Blocked then 'inActive'
JsObject.Add('status', StatusObject);
JsObject.Add('code', GLAccount."No.");
JsObjectChanges.Add('languageCode', 'Norwegian');
JsObjectChanges.Add('description', GLAccount.Name);
JArrayChanges.Add(JsObjectChanges);
JsObject.Add('description', JArrayChanges);
Operation := 'Optional';
if 'Code Mandatory' then Operation := 'AnyValue';
if 'Same Code' then Operation := 'AnyValue';
if 'No Code' then Operation := 'NotApplicable';
IF ("Dimension Value Code" <> '') and (Operation = 'AnyValue') then Operation := 'Requirement';
Clear(JsObjectDimension);
JsObjectDimension.Add('type', 'Dimension');
JsObjectDimension.Add('typeCode', DefaultDimension."Dimension Code");
JsObjectDimension.Add('operation', Operation);
JsObjectDimension.Add('code', DefaultDimension."Dimension Value Code")
JArrayDimension.Add(JsObjectDimension);
JsObject.Add('relations', JArrayDimension);
VAT Codes (Mva koder):
Api.SetMethod('api/v1.0/organizations/' + OrganizationId + '/clients/' + ClientId + '/vatcodes');
Api.SetMethodRest('POST');
JsObject.Add('status', 'Active');
JsObject.Add('code', VATPostingSetup."VAT Code");
Desc := VatCode.Description;
JsObjectChanges.Add('languageCode', 'Norwegian');
JsObjectChanges.Add('description', Desc);
JArrayChanges.Add(JsObjectChanges);
JsObject.Add('description', JArrayChanges);
JVatRate.Add('validFrom', TODAY);
JVatRate.Add('ratePercentage', VATPostingSetup."VAT %");
JVatRates.Add(JVatRate);
JsObject.Add('vatRates', JVatRates);
JCostRate.Add('validFrom', TODAY);
JCostRate.Add('ratePercentage', (100 - VATPostingSetup."Proportional Deduction VAT %"));
JCostRates.Add(JCostRate);
JsObject.Add('costRates', JCostRates); If VATPostingSetup."Proportional Deduction VAT %" > 0
Currency (Valuta):
Api.SetMethod('api/v1.0/organizations/' + OrganizationId + '/clients/' + ClientId + '/currency');
Api.SetMethodRest('POST');
JsObject.Add('currencyCode', Currency.Code);
JsObject.Add('baseCurrency', GeneralLedgerSetup."LCY Code");
JsObject.Add('validFrom', ExchangeRateDate);
JsObject.Add('conversionRate', ExchangeRateAmt);
JsObject.Add('numberOfUnits', Currency."Units to NOK"); //If Currency."Units to NOK" = 0 then set to 1
Dimension (Dimensjoner):
Api.SetMethod('api/v1.0/organizations/' + OrganizationId + '/clients/' + ClientId + '/dimensions');
Api.SetMethodRest('POST');
JsObject.Add('status', 'Active'); //if Dimension.Blocked then set to 'InActive'
JsObject.Add('code', Dimension.Code);
JsObjectDesc.Add('languageCode', 'Norwegian');
JsObjectDesc.Add('description', Dimension.Name);
JArrayDesc.Add(JsObjectDesc);
JsObjectDesc.Add('languageCode', 'English');
JsObjectDesc.Add('description', DimTrans.Name);
JArrayDesc.Add(JsObjectDesc);
JsObject.Add('description', JArrayDesc);
Dimension values (Dimensjonsverdier):
'api/v1.0/organizations/' + OrgId + '/clients/' + ClientId + '/dimensions/' + "Dimension" + '/values/'
Api.SetMethodRest('POST');
JsObject.Add('dimensionCode', DimensionValue."Dimension Code");
JsObject.Add('status', 'Active'); //IF DimensionValue.Blocked then set to 'Inactive';
JsObject.Add('code', DimensionValue.Code);
JsObjectDesc.Add('languageCode', 'Norwegian');
JsObjectDesc.Add('description', DimensionValue.Name);
JArrayDesc.Add(JsObjectDesc);
JsObjectDesc.Add('languageCode', 'English');
JsObjectDesc.Add('description', DimTrans.Name); //DimTrans = "Dimension Translate"
JArrayDesc.Add(JsObjectDesc);
JsObject.Add('description', JArrayDesc);
Fixed Assets (Aktivakonto):
Api.SetMethod('api/v1.0/organizations/' + OrganizationId + '/clients/' + ClientId + '/fixedassets/');
Api.SetMethodRest('POST');
StatusObject := 'active'; // if Blocked then 'inActive'
JsObject.Add('status', StatusObject);
JsObject.Add('code', FixedAsset."No.");
JsObjectChanges.Add('languageCode', 'Norwegian');
JsObjectChanges.Add('description', FixedAsset.Name);
JArrayChanges.Add(JsObjectChanges);
JsObject.Add('description', JArrayChanges);
Operation := 'Optional';
if 'Code Mandatory' then Operation := 'AnyValue';
if 'Same Code' then Operation := 'AnyValue';
if 'No Code' then Operation := 'NotApplicable';
IF ("Dimension Value Code" <> '') and (Operation = 'AnyValue') then Operation := 'Requirement';
Clear(JsObjectDimension);
JsObjectDimension.Add('type', 'Dimension');
JsObjectDimension.Add('typeCode', DefaultDimension."Dimension Code");
JsObjectDimension.Add('operation', Operation);
JsObjectDimension.Add('code', DefaultDimension."Dimension Value Code")
JArrayDimension.Add(JsObjectDimension);
JsObject.Add('relations', JArrayDimension);
Transaction types (Transaksjonstyper):
Api.SetMethod('api/v1.0/organizations/' + OrgId + '/clients/' + ClientId + '/transactiontypes');
Api.SetMethodRest('POST');
JsObject.Add('status', 'Active');
JsObject.Add('code', TransactionCode); //Values is hard coded and fixed from BC
JsObjectChanges.Add('languageCode', 'Norwegian');
JsObjectChanges.Add('description', TransactionDescription); //Values is hard coded and fixed from BC
JArrayChanges.Add(JsObjectChanges);
JsObject.Add('description', JArrayChanges);
Invoice field specification (reading from Json, returned from Semine API)
InvoiceId := GetJsonToken(JsObject, 'invoiceId');
InvoiceNumber := GetJsonToken(JsObject, 'invoiceNumber');
DocType := GetJsonToken(JsObject, 'documentType');
VoucherNo := GetJsonToken(JsObject, 'voucherNumber');
InvoiceDateText := GetJsonToken(JsObject, 'invoiceDate');
InvoiceDueDateText := GetJsonToken(JsObject, 'dueDate');
OnHold := GetJsonToken(JsObject, 'doNotPay');
InvoiceTypeText := GetJsonToken(JsObject, 'invoiceType');
//under invoiceAmount:
AmountText := JsTokenInvoiceAmount.AsObject().SelectToken('totalAmount', JsTotalAmountInfo)
VatAmountText := JsTokenInvoiceAmount.AsObject().SelectToken('vatAmount', JsTotalAmountInfo)
NETAmountText := JsTokenInvoiceAmount.AsObject().SelectToken('netAmount', JsTotalAmountInfo)
exRateText := JsTokenInvoiceAmount.AsObject().SelectToken('conversionRate', JsTotalAmountInfo)
numUnitsText := SelectToken('conversionNumberOfUnits', JsTotalAmountInfo)
RoundingAmountText := SelectToken('roundingAmount', JsTotalAmountInfo) //if not is null
AttachmentURL := GetJsonToken(JsObject, 'semineUrl');
Currency := GetJsonToken(JsObject, 'invoiceCurrency');
KID := GetJsonToken(JsObject, 'kidNumber') //if not is null
InvoiceDueDateText := GetJsonToken(JsObject, 'dueDate');
//from supplierParty
VatNumber := SelectToken('vatNumber', JsTokenVendorId)
OrgNumber := SelectToken('organizationNumber', JsGenToken)
Name := SelectToken('name', JsTokenVendorName)
attachmentId := GetJsonToken(JsObjectLine, 'id');
isInvoicePdf := GetJsonToken(JsObjectLine, 'isInvoicePdf');
attachFileName := GetJsonToken(JsObjectLine, 'fileName');
//if DocType.ToLower() = 'poinvoice' then begin
//if JsObject.SelectToken('purchaseInvoiceLines', JsTokenResultLine) then
LineType := 'PurchaseInvoiceLine';
if 'purchaseOrderLineQuantityMatched' IsNull then
LineType := GetJsonToken(JsObjectLine, 'invoiceLineCategoryCode');
purchaseOrderNumber := GetJsonToken(JsObjectLine, 'purchaseOrderNumber');
LineId := GetJsonToken(JsObjectLine, 'invoiceLineId');
LineNumber := GetJsonToken(JsObjectLine, 'purchaseOrderLineNumber');
TotAmountLineText := GetJsonToken(JsObjectLine, 'invoiceLineTotalAmount');
NetAmountLineText := GetJsonToken(JsObjectLine, 'invoiceLineNetAmount');
UnitPriceText := GetJsonToken(JsObjectLine, 'invoiceLineUnitPrice');
invQuantityText := GetJsonToken(JsObjectLine, 'invoiceLineQuantity');
ReceiptHeaderNo := GetJsonToken(JsObjectLine, 'goodsReceiptNumber');
PostedDateText := GetJsonToken(JsObjectLine, 'postingDate');
//if JsObjectLine.SelectToken('invoiceLineAccountingParameterValues', JsTokenDimensions) then
DimensionType := GetJsonToken(JsObjectLineDimension, 'parameterTypeCode');
DimensionCode := GetJsonToken(JsObjectLineDimension, 'parameterCode');
DimensionValue := GetJsonToken(JsObjectLineDimension, 'parameterValueCode');
if (DimensionValue <> '') and (DimensionType = 'Dimension') then begin
if (DimensionValue <> '') and (DimensionType = 'Vat') then begin
//JsObject.SelectToken('invoiceAccountingLines', JsTokenResultLine)
PostedDateText := GetJsonToken(JsObjectLine, 'postingDate');
LineId := GetJsonToken(JsObjectLine, 'lineNumber');
desc := GetJsonToken(JsObjectLine, 'description');
LineType := GetJsonToken(JsObjectLine, 'lineType');
AmountLineText := GetJsonToken(JsObjectLine, 'totalAmount');
NetAmountLineText := GetJsonToken(JsObjectLine, 'netAmount');
VatAmountLineText := GetJsonToken(JsObjectLine, 'vatAmount');
exRate := GetJsonToken(JsObjectLine, 'exchangeRate');
numUnits := GetJsonToken(JsObjectLine, 'numberOfUnits');
debitType := GetJsonToken(JsObjectLine, 'debitLedgerType');
creditType := GetJsonToken(JsObjectLine, 'creditLedgerType');
voucherType := GetJsonToken(JsObjectLine, 'voucherTypeCode');
periodizeStartYear := GetJsonToken(JsObjectLine, 'periodStartYear');
periodizeStartMonth := GetJsonToken(JsObjectLine, 'periodStartMonth');
periodizeNumOfPeriods := GetJsonToken(JsObjectLine, 'periodCount');
CurrencyLine := GetJsonToken(JsObjectLine, 'currency');
//if JsObjectLine.SelectToken('invoiceAccountingLineParameters', JsTokenDimensions) then
DimensionType := GetJsonToken(JsObjectLineDimension, 'type');
DimensionCode := GetJsonToken(JsObjectLineDimension, 'parentCode');
DimensionValue := GetJsonToken(JsObjectLineDimension, 'code');
if (DimensionValue <> '') and (DimensionType = 'Dimension') then begin
if (DimensionValue <> '') and (DimensionType = 'Supplier') then begin
payableType := GetJsonToken(JsObjectLineDimension, 'payableType');
if (DimensionValue <> '') and (DimensionType = 'AccountingCode') then begin
if (DimensionValue <> '') and (DimensionType = 'Interim') then begin
if (DimensionValue <> '') and (DimensionType = 'VatCode') then begin
payableType := GetJsonToken(JsObjectLineDimension, 'payableType');
vatCode := GetJsonToken(JsObjectLineDimension, 'code');