Вызов OData ActionImport из SAPUI5 - PullRequest
       60

Вызов OData ActionImport из SAPUI5

1 голос
/ 01 марта 2020

** Я могу присудить награду, даже если она решит мою проблему! **

Я хочу вызвать ActionImport из SAPUI5 с использованием API OData v4.

Моим бизнес-требованием является отправка «идентификатора студента» для обновления / создания «TeachingSession». Когда пользователь выбирает «студент» из поля со списком и нажимает кнопку «Начать сеанс», я хочу отправить идентификатор выбранного студента. При нажатии этой кнопки я вызываю функцию «startSession» в контроллере.

Но я не могу запустить ActionImport из-за неправильного кодирования.

Я вижу ошибку ниже, когда я выполняю код ниже .

Не удалось выполнить / TeachingSessions ('3') / OnlineTeaching.UpdateTeachingSession (...) - ошибка: ожидается одна перегрузка, но найдено 0 для / TeachingSessions ('3') / OnlineTeaching .UpdateTeachingSession (...)

Ниже приведена схема OData:

<?xml version='1.0' encoding='UTF-8'?>
<edmx:Edmx Version="4.0"
    xmlns:edmx="http://docs.oasis-open.org/odata/ns/edmx">
    <edmx:DataServices>
        <Schema xmlns="http://docs.oasis-open.org/odata/ns/edm"
            Namespace="OnlineTeaching">

            <EntityType Name="Student">
                <Key>
                    <PropertyRef Name="id" />
                </Key>
                <Property Name="id" Type="Edm.Int32" />
                <Property Name="name" Type="Edm.String" />
                <Property Name="email" Type="Edm.String" />
                <Property Name="skypeid" Type="Edm.String" />

                <NavigationProperty Name="Schedules" Type="Collection(OnlineTeaching.Schedule)" Partner="Student" />
                <NavigationProperty Name="TeachingSessions" Type="Collection(OnlineTeaching.TeachingSession)" Partner="Student" />
            </EntityType>

            <EntityType Name="Schedule">
                <Key>
                    <PropertyRef Name="id" />
                </Key>
                <Property Name="id" Type="Edm.Int32" />
                <Property Name="weekday" Type="Edm.String" />
                <Property Name="time" Type="Edm.String" />
                <Property Name="timezone" Type="Edm.String" />

                <NavigationProperty Name="Student" Type="OnlineTeaching.Student" Partner="Schedules" />
            </EntityType>

            <EntityType Name="TeachingSession">
                <Key>
                    <PropertyRef Name="id" />
                </Key>
                <Property Name="id" Type="Edm.Int32" />

                <Property Name="date" Type="Edm.Date" />                
                <Property Name="startTime" Type="Edm.String" />
                <Property Name="endTime" Type="Edm.String" />
                <Property Name="timezone" Type="Edm.String" />

                <NavigationProperty Name="Student" Type="OnlineTeaching.Student" Partner="TeachingSessions" />
            </EntityType>

            <Action Name="UpdateTeachingSession">
                <Parameter Name="session_id" Type="Edm.Int32" />
                <Parameter Name="student_id" Type="Edm.Int32" />
            </Action>

            <EntityContainer Name="Container">
                <ActionImport Name="UpdateTeachingSession" Action="UpdateTeachingSession"/>

                <EntitySet Name="Students" EntityType="OnlineTeaching.Student">
                    <NavigationPropertyBinding Path="Schedules" Target="Schedules" />
                    <NavigationPropertyBinding Path="TeachingSessions" Target="TeachingSessions" /> 
                </EntitySet>

                <EntitySet Name="Schedules" EntityType="OnlineTeaching.Schedule">
                    <NavigationPropertyBinding Path="Student" Target="Students" />                  
                </EntitySet>

                <EntitySet Name="TeachingSessions" EntityType="OnlineTeaching.TeachingSession">
                    <NavigationPropertyBinding Path="Student" Target="Students" />                  
                </EntitySet>

            </EntityContainer>
        </Schema>
    </edmx:DataServices>
</edmx:Edmx>

SAPUI5 Просмотр кода:

    <Table
                id="teachingSessionsTable"
                growing="true"
                growingThreshold="3"
                items="{
                        path: '/TeachingSessions',
                        parameters: {
                            $count: true
                            ,'expand': 'Student'
                        }
                    }"
                mode="SingleSelectLeft">
                <!--  ,$$updateGroupId : 'peopleGroup' 
                // inside item aggregation
                , 
                        events:{
                            change: '.onChangeHandler'
                        }
                -->
            <headerToolbar>
                <OverflowToolbar>
                    <content>
                        <ToolbarSpacer/>
                        <SearchField
                            id="searchField"
                            width="20%"
                            placeholder="{i18n>searchFieldPlaceholder}"
                            enabled="{= !${appView>/hasUIChanges}}"
                            search=".onSearch"/>
                        <Button
                            id="addTeachingSessionButton"
                            icon="sap-icon://add"
                            tooltip="Create TeachingSession"
                            press=".onCreate">
                            <layoutData>
                                <OverflowToolbarLayoutData priority="NeverOverflow"/>
                            </layoutData>
                        </Button>
                        <Button
                            id="deleteTeachingSessionButton"
                            icon="sap-icon://delete"
                            tooltip="Delete TeachingSession"
                            press=".onDelete">
                            <layoutData>
                                <OverflowToolbarLayoutData priority="NeverOverflow"/>
                            </layoutData>
                        </Button>
                        <Button
                            id="refreshTeachingSessionsButton"
                            icon="sap-icon://refresh"
                            enabled="{= !${appView>/hasUIChanges}}"
                            tooltip="Refresh TeachingSession"
                            press=".onRefresh"/>
                        <Button
                            id="sortTeachingSessionsButton"
                            icon="sap-icon://sort"
                            enabled="{= !${appView>/hasUIChanges}}"
                            tooltip="Sort by Name/Description (placeholder)"
                            press=".onSort"/>
                    </content>
                </OverflowToolbar>
            </headerToolbar>
            <columns>
                <Column id="idColumn">
                    <Text text="Id"/>
                </Column>
<!--                    <Text text="{i18n>idLabelText}"/> -->
                <Column id="dateColumn">
                    <Text text="Date"/>
                    <!-- <Text text="{i18n>dateLabelText}"/> -->
                </Column>
                <Column id="startTimeColumn">
                    <Text text="StartTime"/>
                    <!-- <Text text="{i18n>startTimeLabelText}"/> -->
                </Column>
                <Column id="endTimeColumn">
                    <Text text="EndTime"/>
                    <!-- <Text text="{i18n>endTimeLabelText}"/> -->
                </Column>
                <Column id="timezoneColumn">
                    <Text text="Timezone"/>
                    <!-- <Text text="{i18n>timezoneLabelText}"/> -->
                </Column>
                <Column>
                    <Text text="Id (Student)"/>
                </Column>

                <Column>
                    <Text text="Action"/>
                </Column> 
            </columns>
            <items>
                <ColumnListItem id="table_col">
                    <cells>
                        <Input
                            value="{id}"
                            visible="false"
                            valueLiveUpdate="true"
                            liveChange=".onInputChange"/>
                    </cells>
                    <cells>
                        <Input value="{date}"
                            valueLiveUpdate="true"
                            />  <!-- liveChange=".onInputChange" -->
                    </cells>
                    <cells>
                        <Input
                            id="startTime"
                            value="{startTime}"
                            valueLiveUpdate="true"
                            liveChange=".onInputChange"/>
                    </cells>
                    <cells>
                        <Input
                            id="endTime"
                            value="{endTime}"
                            valueLiveUpdate="true"
                            liveChange=".onInputChange"/>
                    </cells>
                    <cells>
                        <Input
                            value="{timezone}"
                            valueLiveUpdate="true"
                            liveChange=".onInputChange"/>
                    </cells>
                    <!-- 
                    <cells>
                        <Text id="TeachingSession_Student_id_source" text="{Student/id}" visible="true" />
                    </cells>
                    -->             
                    <cells>
                        <ComboBox id="student_id_combo_box"
                            showSecondaryValues= "true"
                            filterSecondaryValues= "true"
                            items="{
                                path: '/Students',
                                sorter: { path: 'name' },
                                templateShareable: true 
                            }"
                            change=".handleStudentSelection"
                            >
                            <core:ListItem key="{id}" text="{name}" additionalText="{skypeid}"/>
                        </ComboBox>
                    </cells>

                    <cells>
                        <Button text="Start Session" press=".startSession" />
                    </cells>

                </ColumnListItem>
            </items>
        </Table>

Мой код контроллера SAPUI5 - как показано ниже:

sap.ui.define([
    "sap/ui/core/mvc/Controller",
    "sap/m/MessageToast",
    "sap/m/MessageBox",
    "sap/ui/model/Sorter",
    "sap/ui/model/Filter",
    "sap/ui/model/FilterOperator",
    "sap/ui/model/FilterType",
    "sap/ui/model/json/JSONModel",
    "sap/base/Log"
], function (Controller, MessageToast, MessageBox, Sorter, Filter, FilterOperator, FilterType, JSONModel, Log) {
    "use strict";

    return Controller.extend("sap.ui.core.tutorial.odatav4.controller.TeachingSession", {
        /**
         *  Hook for initializing the controller
         */
        onInit : function () {
            var oMessageManager = sap.ui.getCore().getMessageManager(),
                oMessageModel = oMessageManager.getMessageModel(),
                oMessageModelBinding = oMessageModel.bindList("/", undefined, [],
                    new Filter("technical", FilterOperator.EQ, true)),
                oViewModel = new JSONModel({
                    busy : false,
                    hasUIChanges : false,
                    usernameEmpty : true,
                    order : 0
                });
            this.getView().setModel(oViewModel, "appView");
            this.getView().setModel(oMessageModel, "message_layers");

            oMessageModelBinding.attachChange(this.onMessageBindingChange, this);
            this._bTechnicalErrors = false;
            //this.getView().getModel().setDefaultBindingMode(BindingMode.OneWay);
        },


        /* =========================================================== */
        /*           begin: event handlers                             */
        /* =========================================================== */



        onChangeHandler: function(oEvent){
            var eventName = oEvent.getParameter("reason");
            console.log("Change: Event raised: " + eventName + ", timestamp = " + new Date().getTime());

        },

        onSelect_tier_id: function(oEvt){
            var selectedTierId = oEvt.getSource().getSelectedKey();
            this._selectRowOfChange( oEvt );
            var selectedItem = this.byId( "teachingSessionsTable" ).getSelectedItem(); // row is same as item here
            var oCells = selectedItem.getCells();
            for( var i=0; i < oCells.length; i++ ){
                if( oCells[i].getId().match( "tier_id_selected" ) ){
                    oCells[i].setValue( selectedTierId );
                }
            }

            this.onInputChange( oEvt );
        },

        fnFormatter: function(text, key) {
            var sText = "";

            if (text && key) {
                sText += (text + " (" + key + ")");
            } else if (text) {
                sText += text;
            } else if (key) {
                sText += key;
            }

            return sText;
        },

        _getDateStringToday: function(){
            var today = new Date();
            const year = today.getFullYear();
            const month = today.getMonth();
                    month = month + 1;
            const day = today.getDate();
            var dateString = year + "/" + month + "/" + day;

            return dateString;
        },

        handleStudentSelection: function(oEvent){
            var oValidatedComboBox = oEvent.getSource(),
            sSelectedKey = oValidatedComboBox.getSelectedKey(),
            sValue = oValidatedComboBox.getValue();

            if (!sSelectedKey && sValue) {
                oValidatedComboBox.setValueState("Error");
                oValidatedComboBox.setValueStateText("Select from existing Student list! If the student does not exist, you may have to add the student first");
            } else {
                oValidatedComboBox.setValueState("None");
                this.byId("selectedStudentId").setValue( sSelectedKey );
            }
        },

        startSession: function(oEvt){
            this._selectRowOfChange( oEvt );
            var selectedItem = this.byId( "teachingSessionsTable" ).getSelectedItem();
            var cells = selectedItem.getCells();
            /* Will be uncommented after action import resolution
            // 1. Update the Start Time for the session row
            var now = new Date();
            var startTime = now.getHours() + ":" + now.getMinutes();
            cells[2].setValue( startTime );
            this._setUIChanges(true);
             */

            // 2. Update the selected student id for this session row
            var operation = this.getView().getModel().bindContext("/TeachingSessions('"+ cells[0].getValue() + "')/OnlineTeaching.UpdateTeachingSession(...)");
            //var operation = this.getView().getModel().bindContext("/UpdateTeachingSession(...)");

            operation.setParameter( "OnlineTeaching.UpdateTeachingSession.session_id", cells[0].getValue() );
            operation.setParameter( "OnlineTeaching.UpdateTeachingSession.student_id", this.byId("selectedStudentId").getValue() );

            operation.execute('$direct');
            /*
                .then(function () {
                            //oModel.refresh();
                            MessageToast.show("submitted action but need to see the response");
                        }.bind(this), function (oError) {
                            MessageBox.error(oError.message);
                        }
                    );
            */
            /*
            var oBinding = this.byId( "teachingSessionsTable" ).getSelectedItem().getBindingContext(); //this.byId("teachingSessionsTable").getBinding();
                oBinding.setParameter("OnlineTeaching.UpdateTeachingSession.session_id", cells[0].getValue());
                oBinding.setParameter("OnlineTeaching.UpdateTeachingSession.student_id", this.byId("selectedStudentId").getValue());

                oBinding.setParameter("session_id", cells[0].getValue());
                oBinding.setParameter("student_id", this.byId("selectedStudentId").getValue());
                //oEvt.getSource().getParent().getBindingContext()
                var oList = this.byId( "teachingSessionsTable" );
                var oBinding = oList.getBinding("items");
                //oContext = oBinding.
            oBinding.execute();
                */
            //this._setUIChanges(true);
        },

        /**
         * Create a new entry.
         */
        onCreate : function () {
            var oList = this.byId( "teachingSessionsTable" );
            //var dateString = this._getDateStringToday();
            var oBinding = oList.getBinding("items"),
                // Create a new entry through the table's list binding
                // You may need to change the column name in place of "description"
                oContext = oBinding.create({
                        "date" : null,
                        "startTime" : null ,
                        "endTime" : null ,
                        "timezone" : null 
                ,
                 "Student@odata.bind": 1                });
            this._setUIChanges(true);
            this.getView().getModel("appView").setProperty("/usernameEmpty", true);

            // Select and focus the table row that contains the newly created entry
            oList.getItems().some(function (oItem) {
                if (oItem.getBindingContext() === oContext) {
                    oItem.focus();
                    oItem.setSelected(true);
                    return true;
                }
            });
        },

        /**
         * Delete an entry.
         */
        onDelete : function () {
            var oSelected = this.byId( "teachingSessionsTable" ).getSelectedItem();

            if (oSelected) {
                oSelected.getBindingContext().delete("$direct").then(function () {
                    MessageToast.show(this._getText("deletionSuccessMessage"));
                }.bind(this), function (oError) {
                    MessageBox.error(oError.message);
                });
            }
        },

        /**
         * Copies tier_id value from placeholder column to actual column
         */
        _copyToInputField: function( oCells, value ){
            for( var i=0; i < oCells.length; i++ ){
                if( oCells[i].getId().match( "tier_id_actual" ) ){
                    oCells[i].setValue( value );
                }
            }
        },

        /**
         * Selects the row of a table in which the user is making change of any field
         */
        _selectRowOfChange: function(oEvt){
            // Select the row of input change
            var oFieldId = oEvt.getSource().getParent().getId();
            this.byId( "teachingSessionsTable" ).setSelectedItemById( oFieldId, true);
        },

        /**
         * Lock UI when changing data in the input controls
         * @param {sap.ui.base.Event} oEvt - Event data
         */
        onInputChange : function (oEvt) {
            this._selectRowOfChange( oEvt );

            if (oEvt.getParameter("escPressed")) {
                this._setUIChanges();
            } else {
                this._setUIChanges(true);
                // Check if the id in the changed table row is empty and set the appView property accordingly
                if (oEvt.getSource().getParent().getBindingContext().getProperty("id")) {
                    this.getView().getModel("appView").setProperty("/usernameEmpty", false);
                }
            }

        },



        /**
         * Refresh the data.
         */
        onRefresh : function () {
            var oBinding = this.byId( "teachingSessionsTable" ).getBinding("items");

            if (oBinding.hasPendingChanges()) {
                MessageBox.error(this._getText("refreshNotPossibleMessage"));
                return;
            }
            oBinding.refresh();
            MessageToast.show(this._getText("refreshSuccessMessage"));
        },

        /**
         * Reset any unsaved changes.
         */
        onResetChanges : function () {
            this.byId( "teachingSessionsTable" ).getBinding("items").resetChanges();
            this._bTechnicalErrors = false; // If there were technical errors, cancelling changes resets them.
            this._setUIChanges(false);
        },

        /**
         * Reset the data source.
         */
        onResetDataSource : function () {
            var oModel = this.getView().getModel(),
                oOperation = oModel.bindContext("/ResetDataSource(...)");

            oOperation.execute().then(function () {
                    oModel.refresh();
                    MessageToast.show(this._getText("sourceResetSuccessMessage"));
                }.bind(this), function (oError) {
                    MessageBox.error(oError.message);
                }
            );
        },

        /**
         * Save changes to the source.
         */
        onSave : function () {
            var fnSuccess = function () {
                this._setBusy(false);
                MessageToast.show(this._getText("changesSentMessage"));
                this._setUIChanges(false);
            }.bind(this);

            var fnError = function (oError) {
                this._setBusy(false);
                this._setUIChanges(false);
                MessageBox.error(oError.message);
            }.bind(this);

            this._setBusy(true); // Lock UI until submitBatch is resolved.
            this.getView().getModel().submitBatch("peopleGroup").then(fnSuccess, fnError);
            this._bTechnicalErrors = false; // If there were technical errors, a new save resets them.
        },

        /**
         * Search for the term in the search field.
         */
        onSearch : function () {
            var oView = this.getView(),
                sValue = oView.byId("searchField").getValue(),
                oFilter = new Filter("description", FilterOperator.Contains, sValue);

            oView.byId( "teachingSessionsTable" ).getBinding("items").filter(oFilter, FilterType.Application);
        },

        /**
         * Sort the table according to the Description.
         * Cycles between the three sorting states "none", "ascending" and "descending"
         */
        onSort : function () {
            var oView = this.getView(),
                aStates = [undefined, "asc", "desc"],
                aStateTextIds = ["sortNone", "sortAscending", "sortDescending"],
                sMessage,
                iOrder = oView.getModel("appView").getProperty("/order");

            // Cycle between the states
            iOrder = (iOrder + 1) % aStates.length;
            var sOrder = aStates[iOrder];

            oView.getModel("appView").setProperty("/order", iOrder);
            // below column name "description" should be changed as per the requirement
            oView.byId( "teachingSessionsTable" ).getBinding("items").sort(sOrder && new Sorter("description", sOrder === "desc"));

            sMessage = this._getText("sortMessage", [this._getText(aStateTextIds[iOrder])]);
            MessageToast.show(sMessage);
        },

        onMessageBindingChange : function (oEvent) {
            var aContexts = oEvent.getSource().getContexts(),
                aMessages,
                bMessageOpen = false;

            if (bMessageOpen || !aContexts.length) {
                return;
            }

            // Extract and remove the technical messages
            aMessages = aContexts.map(function (oContext) {
                return oContext.getObject();
            });
            sap.ui.getCore().getMessageManager().removeMessages(aMessages);

            this._setUIChanges(true);
            this._bTechnicalErrors = true;
            MessageBox.error(aMessages[0].message, {
                id : "serviceErrorMessageBox_TeachingSessions",
                onClose : function () {
                    bMessageOpen = false;
                }
            });

            bMessageOpen = true;
        },


        /* =========================================================== */
        /*           end: event handlers                               */
        /* =========================================================== */


        /**
         * Convenience method for retrieving a translatable text.
         * @param {string} sTextId - the ID of the text to be retrieved.
         * @param {Array} [aArgs] - optional array of texts for placeholders.
         * @returns {string} the text belonging to the given ID.
         */
        _getText : function (sTextId, aArgs) {
            return this.getView().getModel("i18n").getResourceBundle().getText(sTextId, aArgs);
        },

        /**
         * Set hasUIChanges flag in View Model
         * @param {boolean} [bHasUIChanges] - set or clear hasUIChanges
         * if bHasUIChanges is not set, the hasPendingChanges-function of the OdataV4 model determines the result
         */
        _setUIChanges : function (bHasUIChanges) {
            if (this._bTechnicalErrors) {
                // If there is currently a technical error, then force 'true'.
                bHasUIChanges = true;
            } else if (bHasUIChanges === undefined) {
                bHasUIChanges = this.getView().getModel().hasPendingChanges();
            }
            var oModel = this.getView().getModel("appView");
            oModel.setProperty("/hasUIChanges", bHasUIChanges);
        },

        /**
         * Set busy flag in View Model
         * @param {boolean} bIsBusy - set or clear busy
         */
        _setBusy : function (bIsBusy) {
            var oModel = this.getView().getModel("appView");
            oModel.setProperty("/busy", bIsBusy);
        }

    });
});
...