OBJECT Table 91 User Setup { OBJECT-PROPERTIES { Date=26-11-15; Time=07:00:00; Modified=Yes; Version List=NAVW19.00,WebService-Example; } PROPERTIES { OnDelete=VAR NotificationSetup@1000 : Record 1512; BEGIN NotificationSetup.SETRANGE("User ID","User ID"); NotificationSetup.DELETEALL(TRUE); END; CaptionML=ENU=User Setup; LookupPageID=Page119; DrillDownPageID=Page119; } FIELDS { { 1 ; ;User ID ;Code50 ;TableRelation=User."User Name"; OnValidate=VAR UserMgt@1000 : Codeunit 418; BEGIN UserMgt.ValidateUserID("User ID"); END; OnLookup=VAR UserMgt@1000 : Codeunit 418; BEGIN UserMgt.LookupUserID("User ID"); END; CaptionML=ENU=User ID; NotBlank=Yes } { 2 ; ;Allow Posting From ;Date ;CaptionML=ENU=Allow Posting From } { 3 ; ;Allow Posting To ;Date ;CaptionML=ENU=Allow Posting To } { 4 ; ;Register Time ;Boolean ;CaptionML=ENU=Register Time } { 10 ; ;Salespers./Purch. Code;Code10 ;TableRelation=Salesperson/Purchaser.Code; OnValidate=VAR UserSetup@1000 : Record 91; BEGIN IF "Salespers./Purch. Code" <> '' THEN BEGIN UserSetup.SETCURRENTKEY("Salespers./Purch. Code"); UserSetup.SETRANGE("Salespers./Purch. Code","Salespers./Purch. Code"); IF UserSetup.FINDFIRST THEN ERROR(Text001,"Salespers./Purch. Code",UserSetup."User ID"); END; END; ValidateTableRelation=No; TestTableRelation=No; CaptionML=ENU=Salespers./Purch. Code } { 11 ; ;Approver ID ;Code50 ;TableRelation="User Setup"."User ID"; OnValidate=BEGIN IF "Approver ID" = "User ID" THEN FIELDERROR("Approver ID"); END; OnLookup=VAR UserSetup@1000 : Record 91; BEGIN UserSetup.SETFILTER("User ID",'<>%1',"User ID"); IF PAGE.RUNMODAL(PAGE::"Approval User Setup",UserSetup) = ACTION::LookupOK THEN VALIDATE("Approver ID",UserSetup."User ID"); END; CaptionML=ENU=Approver ID } { 12 ; ;Sales Amount Approval Limit;Integer;OnValidate=BEGIN IF "Unlimited Sales Approval" AND ("Sales Amount Approval Limit" <> 0) THEN ERROR(Text003,FIELDCAPTION("Sales Amount Approval Limit"),FIELDCAPTION("Unlimited Sales Approval")); IF "Sales Amount Approval Limit" < 0 THEN ERROR(Text005); END; CaptionML=ENU=Sales Amount Approval Limit; BlankZero=Yes } { 13 ; ;Purchase Amount Approval Limit;Integer; OnValidate=BEGIN IF "Unlimited Purchase Approval" AND ("Purchase Amount Approval Limit" <> 0) THEN ERROR(Text003,FIELDCAPTION("Purchase Amount Approval Limit"),FIELDCAPTION("Unlimited Purchase Approval")); IF "Purchase Amount Approval Limit" < 0 THEN ERROR(Text005); END; CaptionML=ENU=Purchase Amount Approval Limit; BlankZero=Yes } { 14 ; ;Unlimited Sales Approval;Boolean ;OnValidate=BEGIN IF "Unlimited Sales Approval" THEN "Sales Amount Approval Limit" := 0; END; CaptionML=ENU=Unlimited Sales Approval } { 15 ; ;Unlimited Purchase Approval;Boolean;OnValidate=BEGIN IF "Unlimited Purchase Approval" THEN "Purchase Amount Approval Limit" := 0; END; CaptionML=ENU=Unlimited Purchase Approval } { 16 ; ;Substitute ;Code50 ;TableRelation="User Setup"."User ID"; OnValidate=BEGIN IF Substitute = "User ID" THEN FIELDERROR(Substitute); END; OnLookup=VAR UserSetup@1000 : Record 91; BEGIN UserSetup.SETFILTER("User ID",'<>%1',"User ID"); IF PAGE.RUNMODAL(PAGE::"Approval User Setup",UserSetup) = ACTION::LookupOK THEN VALIDATE(Substitute,UserSetup."User ID"); END; CaptionML=ENU=Substitute } { 17 ; ;E-Mail ;Text100 ;ExtendedDatatype=E-Mail; CaptionML=ENU=E-Mail } { 19 ; ;Request Amount Approval Limit;Integer; OnValidate=BEGIN IF "Unlimited Request Approval" AND ("Request Amount Approval Limit" <> 0) THEN ERROR(Text003,FIELDCAPTION("Request Amount Approval Limit"),FIELDCAPTION("Unlimited Request Approval")); IF "Request Amount Approval Limit" < 0 THEN ERROR(Text005); END; CaptionML=ENU=Request Amount Approval Limit; BlankZero=Yes } { 20 ; ;Unlimited Request Approval;Boolean ;OnValidate=BEGIN IF "Unlimited Request Approval" THEN "Request Amount Approval Limit" := 0; END; CaptionML=ENU=Unlimited Request Approval } { 21 ; ;Approval Administrator;Boolean ;OnValidate=VAR UserSetup@1000 : Record 91; BEGIN IF "Approval Administrator" THEN BEGIN UserSetup.SETRANGE("Approval Administrator",TRUE); IF NOT UserSetup.ISEMPTY THEN FIELDERROR("Approval Administrator"); END; END; CaptionML=ENU=Approval Administrator } { 950 ; ;Time Sheet Admin. ;Boolean ;CaptionML=ENU=Time Sheet Admin. } { 5600; ;Allow FA Posting From;Date ;CaptionML=ENU=Allow FA Posting From } { 5601; ;Allow FA Posting To ;Date ;CaptionML=ENU=Allow FA Posting To } { 5700; ;Sales Resp. Ctr. Filter;Code10 ;TableRelation="Responsibility Center".Code; CaptionML=ENU=Sales Resp. Ctr. Filter } { 5701; ;Purchase Resp. Ctr. Filter;Code10 ;TableRelation="Responsibility Center"; CaptionML=ENU=Purchase Resp. Ctr. Filter } { 5900; ;Service Resp. Ctr. Filter;Code10 ;TableRelation="Responsibility Center"; CaptionML=ENU=Service Resp. Ctr. Filter } { 50000; ;Phone No. ;Text30 ;CaptionML=ENU=Phone No. } { 50001; ;Use Two Factor Authentication;Boolean } } KEYS { { ;User ID ;Clustered=Yes } { ;Salespers./Purch. Code } } FIELDGROUPS { } CODE { VAR Text001@1000 : TextConst 'ENU=The %1 Salesperson/Purchaser code is already assigned to another User ID %2.'; Text003@1002 : TextConst 'ENU="You cannot have both a %1 and %2. "'; Text005@1004 : TextConst 'ENU=You cannot have approval limits less than zero.'; BEGIN END. } } OBJECT Table 60004 BulkSMS Setup { OBJECT-PROPERTIES { Date=26-01-16; Time=23:49:49; Modified=Yes; Version List=WebService-Example; } PROPERTIES { } FIELDS { { 1 ; ;Primary Key ;Code10 } { 3 ; ;User Name ;Text250 } { 4 ; ;Password Key ;GUID } { 5 ; ;Credits ;Decimal ;Editable=No } { 6 ; ;Credits Checked At ;DateTime ;Editable=No } } KEYS { { ;Primary Key ;Clustered=Yes } } FIELDGROUPS { } CODE { VAR ExchangeAccountNotConfiguredErr@1000000001 : TextConst 'ENU=The Exchange account is not configured.;NLD=Het Exchange-account is niet geconfigureerd.'; Text001@1000000000 : TextConst 'ENU=Autodiscovery of Exchange Service failed.;NLD=Automatische detectie van Exchange service is mislukt.'; PROCEDURE SetPassword@4(PasswordText@1001 : Text); VAR ServicePassword@1000 : Record 1261; BEGIN IF ISNULLGUID("Password Key") OR NOT ServicePassword.GET("Password Key") THEN BEGIN ServicePassword.SavePassword(PasswordText); ServicePassword.INSERT(TRUE); "Password Key" := ServicePassword.Key; END ELSE BEGIN ServicePassword.SavePassword(PasswordText); ServicePassword.MODIFY; END; END; PROCEDURE GetPassword@1000000000() : Text; VAR ServicePassword@1000000000 : Record 1261; BEGIN IF NOT ISNULLGUID("Password Key") THEN IF ServicePassword.GET("Password Key") THEN EXIT(ServicePassword.GetPassword()); END; PROCEDURE GetCredits@1(); VAR SMSWebService@1000 : Codeunit 60004; BEGIN SMSWebService.GetCredits(Rec); END; BEGIN END. } } OBJECT Codeunit 60000 REST WS Management { OBJECT-PROPERTIES { Date=09-01-16; Time=17:00:00; Modified=Yes; Version List=WebService-Example; } PROPERTIES { OnRun=BEGIN END; } CODE { [TryFunction] PROCEDURE CallRESTWebService@1000000002(BaseUrl@1000000000 : Text;Method@1000000001 : Text;RestMethod@1000000004 : Text;VAR HttpContent@1000000005 : DotNet "'System.Net.Http, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'.System.Net.Http.HttpContent";VAR HttpResponseMessage@1000000006 : DotNet "'System.Net.Http, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'.System.Net.Http.HttpResponseMessage"); VAR HttpClient@1000000003 : DotNet "'System.Net.Http, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'.System.Net.Http.HttpClient"; Uri@1000000002 : DotNet "'System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'.System.Uri"; BEGIN HttpClient := HttpClient.HttpClient(); HttpClient.BaseAddress := Uri.Uri(BaseUrl); CASE RestMethod OF 'GET': HttpResponseMessage := HttpClient.GetAsync(Method).Result; 'POST': HttpResponseMessage := HttpClient.PostAsync(Method,HttpContent).Result; 'PUT': HttpResponseMessage := HttpClient.PutAsync(Method,HttpContent).Result; 'DELETE': HttpResponseMessage := HttpClient.DeleteAsync(Method).Result; END; HttpResponseMessage.EnsureSuccessStatusCode(); // Throws an error when no success END; BEGIN END. } } OBJECT Codeunit 60004 SMS Web Service { OBJECT-PROPERTIES { Date=26-01-16; Time=23:52:22; Modified=Yes; Version List=WebService-Example; } PROPERTIES { OnRun=BEGIN END; } CODE { PROCEDURE SendSMS@1000000006(PhoneNo@1000000000 : Text;MessageText@1000000001 : Text) ReturnValue : Boolean; VAR BulkSMSSetup@1000000004 : Record 60004; RESTWSManagement@1004 : Codeunit 60000; stringContent@1000000015 : DotNet "'System.Net.Http, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'.System.Net.Http.StringContent"; httpUtility@1000000005 : DotNet "'System.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'.System.Web.HttpUtility"; encoding@1000000006 : DotNet "'mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'.System.Text.Encoding"; result@1000000007 : DotNet "'mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'.System.String"; resultParts@1000000008 : DotNet "'mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'.System.Array"; separator@1000000009 : DotNet "'mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'.System.String"; HttpResponseMessage@1003 : DotNet "'System.Net.Http, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'.System.Net.Http.HttpResponseMessage"; JsonConvert@1002 : DotNet "'Newtonsoft.Json, Version=6.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed'.Newtonsoft.Json.JsonConvert"; null@1001 : DotNet "'mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'.System.Object"; Window@1000 : Dialog; data@1000000003 : Text; statusCode@1000000011 : Text; statusText@1000000012 : Text; BEGIN BulkSMSSetup.GET; BulkSMSSetup.TESTFIELD("User Name"); BulkSMSSetup.TESTFIELD("Password Key"); Window.OPEN('Sending SMS...'); data := 'username=' + httpUtility.UrlEncode(BulkSMSSetup."User Name",encoding.GetEncoding('ISO-8859-1')); data += '&password=' + httpUtility.UrlEncode(BulkSMSSetup.GetPassword(),encoding.GetEncoding('ISO-8859-1')); data += '&message=' + httpUtility.UrlEncode(MessageText,encoding.GetEncoding('ISO-8859-1')); data += '&msisdn=' + PhoneNo; data += '&want_report=0'; stringContent := stringContent.StringContent(data,encoding.UTF8,'application/x-www-form-urlencoded'); ReturnValue := RESTWSManagement.CallRESTWebService('https://bulksms.vsms.net/', 'eapi/submission/send_sms/2/2.0', 'POST', stringContent, HttpResponseMessage); Window.CLOSE; IF NOT ReturnValue THEN EXIT; result := HttpResponseMessage.Content.ReadAsStringAsync.Result; separator := '|'; resultParts := result.Split(separator.ToCharArray()); statusCode := resultParts.GetValue(0); statusText := resultParts.GetValue(1); IF NOT (statusCode IN ['0','1']) THEN ERROR('Sending SMS message failed!\Statuscode: %1\Description: %2',statusCode,statusText); END; PROCEDURE GetCredits@1(VAR BulkSMSSetup@1014 : Record 60004); VAR RESTWSManagement@1013 : Codeunit 60000; stringContent@1012 : DotNet "'System.Net.Http, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'.System.Net.Http.StringContent"; httpUtility@1011 : DotNet "'System.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'.System.Web.HttpUtility"; encoding@1010 : DotNet "'mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'.System.Text.Encoding"; result@1009 : DotNet "'mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'.System.String"; resultParts@1008 : DotNet "'mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'.System.Array"; separator@1007 : DotNet "'mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'.System.String"; HttpResponseMessage@1006 : DotNet "'System.Net.Http, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'.System.Net.Http.HttpResponseMessage"; JsonConvert@1005 : DotNet "'Newtonsoft.Json, Version=6.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed'.Newtonsoft.Json.JsonConvert"; null@1004 : DotNet "'mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'.System.Object"; Window@1003 : Dialog; data@1002 : Text; statusCode@1001 : Text; statusText@1000 : Text; BEGIN BulkSMSSetup.TESTFIELD("User Name"); BulkSMSSetup.TESTFIELD("Password Key"); RESTWSManagement.CallRESTWebService('https://bulksms.vsms.net/', STRSUBSTNO('eapi/user/get_credits/1/1.1?username=%1&password=%2',BulkSMSSetup."User Name",BulkSMSSetup.GetPassword()), 'GET', null, HttpResponseMessage); result := HttpResponseMessage.Content.ReadAsStringAsync.Result; separator := '|'; resultParts := result.Split(separator.ToCharArray()); statusCode := resultParts.GetValue(0); statusText := resultParts.GetValue(1); IF statusCode <> '0' THEN ERROR('GetCredits failed!\Statuscode: %1\Description: %2',statusCode,statusText); EVALUATE(BulkSMSSetup.Credits, statusText,9); BulkSMSSetup."Credits Checked At" := CURRENTDATETIME; BulkSMSSetup.MODIFY; END; BEGIN END. } } OBJECT Codeunit 60005 Two Factor Authentication Mgt. { OBJECT-PROPERTIES { Date=28-01-16; Time=21:59:25; Modified=Yes; Version List=WebService-Example; } PROPERTIES { OnRun=BEGIN END; } CODE { [EventSubscriber(Codeunit,1,OnBeforeCompanyOpen)] LOCAL PROCEDURE TwoFactorAuthenticationBeforeCompanyOpen@1(); VAR UserSetup@1000 : Record 91; SMSCode@1001 : Text; MessageText@1004 : Text; UserResponse@1003 : Text; EnterSMSCode@1002 : Page 60007; Counter@1005 : Integer; CodeIsValid@1006 : Boolean; TryAgain@1007 : Boolean; SMSWebService@1008 : Codeunit 60004; BEGIN IF NOT UserSetup.GET(USERID) THEN EXIT; IF NOT UserSetup."Use Two Factor Authentication" THEN EXIT; SMSCode := FORMAT(RANDOM(100000000)); MessageText := STRSUBSTNO('Use this code to login in %1: %2',COMPANYNAME,SMSCode); SMSWebService.SendSMS(UserSetup."Phone No.",MessageText); TryAgain := TRUE; WHILE TryAgain DO BEGIN CLEAR(EnterSMSCode); IF EnterSMSCode.RUNMODAL <> ACTION::OK THEN ERROR('You canceled the login procedure'); UserResponse := EnterSMSCode.GetSMSCode; CodeIsValid := UserResponse = SMSCode; Counter += 1; TryAgain := (NOT CodeIsValid) AND (Counter < 3); END; IF NOT CodeIsValid THEN ERROR('You entered an invalid code for 3 times'); END; BEGIN END. } } OBJECT Page 119 User Setup { OBJECT-PROPERTIES { Date=26-11-15; Time=07:00:00; Modified=Yes; Version List=NAVW17.00,WebService-Example; } PROPERTIES { CaptionML=ENU=User Setup; SourceTable=Table91; PageType=List; } CONTROLS { { 1900000001;0;Container; ContainerType=ContentArea } { 1 ;1 ;Group ; GroupType=Repeater } { 2 ;2 ;Field ; SourceExpr="User ID" } { 4 ;2 ;Field ; SourceExpr="Allow Posting From" } { 6 ;2 ;Field ; SourceExpr="Allow Posting To" } { 8 ;2 ;Field ; SourceExpr="Register Time" } { 15 ;2 ;Field ; SourceExpr="Sales Resp. Ctr. Filter" } { 17 ;2 ;Field ; SourceExpr="Purchase Resp. Ctr. Filter" } { 21 ;2 ;Field ; SourceExpr="Service Resp. Ctr. Filter" } { 3 ;2 ;Field ; SourceExpr="Time Sheet Admin." } { 7 ;2 ;Field ; SourceExpr="Phone No." } { 5 ;2 ;Field ; SourceExpr="Use Two Factor Authentication" } { 1900000007;0;Container; ContainerType=FactBoxArea } { 1900383207;1;Part ; Visible=FALSE; PartType=System; SystemPartID=RecordLinks } { 1905767507;1;Part ; Visible=FALSE; PartType=System; SystemPartID=Notes } } CODE { BEGIN END. } } OBJECT Page 60005 BulkSMS Setup { OBJECT-PROPERTIES { Date=28-01-16; Time=22:19:50; Modified=Yes; Version List=WebService-Example; } PROPERTIES { SourceTable=Table60004; PageType=Card; OnOpenPage=BEGIN RESET; IF NOT GET THEN BEGIN INIT; INSERT; END; END; OnAfterGetRecord=BEGIN PasswordTemp := ''; IF ("User Name" <> '') AND (NOT ISNULLGUID("Password Key")) THEN PasswordTemp := '**********'; END; ActionList=ACTIONS { { 3 ; ;ActionContainer; ActionContainerType=ActionItems } { 4 ;1 ;Action ; Name=GetCredits; CaptionML=ENU=Get Credits; Promoted=Yes; PromotedIsBig=Yes; Image=Currencies; PromotedCategory=Process; OnAction=BEGIN GetCredits; CurrPage.UPDATE; END; } } } CONTROLS { { 1000000000;0;Container; ContainerType=ContentArea } { 1000000001;1;Group ; Name=General; GroupType=Group } { 1000000002;2;Field ; SourceExpr="User Name" } { 1000000005;2;Field ; ExtendedDatatype=Masked; CaptionML=[ENU=Password; NLD=Wachtwoord Exchange-account]; SourceExpr=PasswordTemp; OnValidate=BEGIN SetPassword(PasswordTemp); COMMIT; CurrPage.UPDATE; END; } { 1 ;2 ;Field ; SourceExpr=Credits } { 2 ;2 ;Field ; SourceExpr="Credits Checked At" } } CODE { VAR PasswordTemp@1000000000 : Text; BEGIN END. } } OBJECT Page 60006 Send SMS Message { OBJECT-PROPERTIES { Date=28-01-16; Time=21:47:14; Modified=Yes; Version List=WebService-Example; } PROPERTIES { PageType=NavigatePage; ActionList=ACTIONS { { 1000000003; ;ActionContainer; ActionContainerType=ActionItems } { 1000000005;1 ;Action ; Name=Setup; RunObject=Page 60005; Promoted=Yes; PromotedIsBig=Yes; Image=XMLSetup; PromotedCategory=Process } { 1000000004;1 ;Action ; Name=Send SMS; Promoted=Yes; PromotedIsBig=Yes; Image=SendConfirmation; PromotedCategory=Process; OnAction=BEGIN IF (MobilePhoneNo <> '') AND (MessageText <> '') THEN IF NOT SMSWebService.SendSMS(MobilePhoneNo,MessageText) THEN; END; } } } CONTROLS { { 1000000000;;Container; ContainerType=ContentArea } { 1000000001;1;Field ; CaptionML=ENU=Mobile Phone No.; SourceExpr=MobilePhoneNo } { 1000000002;1;Field ; CaptionML=ENU=Message; SourceExpr=MessageText; MultiLine=Yes } } CODE { VAR MobilePhoneNo@1000000000 : Text; MessageText@1000000001 : Text; SMSWebService@1000000002 : Codeunit 60004; PROCEDURE SetPhoneNo@1000000000(value@1000000000 : Text); BEGIN MobilePhoneNo := value; END; BEGIN END. } } OBJECT Page 60007 Enter SMS Code { OBJECT-PROPERTIES { Date=26-01-16; Time=23:48:40; Modified=Yes; Version List=WebService-Example; } PROPERTIES { PageType=StandardDialog; } CONTROLS { { 1 ;0 ;Container ; ContainerType=ContentArea } { 2 ;1 ;Field ; CaptionML=ENU=Enter the code you received by SMS; SourceExpr=SMSCode } } CODE { VAR SMSCode@1000 : Text; PROCEDURE GetSMSCode@1() : Text; BEGIN EXIT(SMSCode); END; BEGIN END. } }