cancel
Showing results for 
Search instead for 
Did you mean: 
Read only

Duplicate item on binding in SAPUI5 Application

WG23
Explorer
0 Kudos
1,705

Hi everyone, I am facing issues with my SAPUI5 application; the data is duplicated in the binding. I am using OData v4 created from my CDS. I've created CDS in Eclipse to get Journal Entry Items based on G/l Line Items. I'm using I_GLAccountLineItem and I_JournalEntryItem to get the data, below is my CDS code:

### CDS in Eclipse

@AbapCatalog.sqlViewName: 'ZGLITEMS'
@AbapCatalog.compiler.compareFilter: true
@AccessControl.authorizationCheck: #NOT_REQUIRED
@EndUserText.label: 'General Ledger Line Items'
@Metadata.ignorePropagatedAnnotations: true
define root view ZGL_LINE_ITEMS
as select distinct from I_GLAccountLineItem as GlLineItem

association [0..1] to I_JournalEntryItem as _toJournalEntryItem
on GlLineItem.AccountingDocument = _toJournalEntryItem.AccountingDocument
and GlLineItem.FiscalYear = _toJournalEntryItem.FiscalYear
and GlLineItem.Ledger = _toJournalEntryItem.Ledger
and GlLineItem.GLAccount <> _toJournalEntryItem.GLAccount
and GlLineItem.DebitCreditCode <> _toJournalEntryItem.DebitCreditCode

association [0..1] to I_User as _toUser
on GlLineItem.AccountingDocCreatedByUser = _toUser.UserID

{
key GlLineItem.CompanyCode as CompanyCode,
key GlLineItem.AccountingDocument as AccDoc,
GlLineItem.PostingDate as PostingDate,
GlLineItem.FiscalPeriod as Period,
GlLineItem.FiscalYear as FisYear,
GlLineItem.Ledger as Ledger,
GlLineItem.GLAccount as GlAccount,
GlLineItem.DocumentItemText as Description,
_toJournalEntryItem.GLAccount as OpposingGLAccount,
GlLineItem.DebitCreditCode as DebitCreditCode,
GlLineItem.CompanyCodeCurrency as Currency,

@Semantics.amount.currencyCode: 'Currency'
GlLineItem.AmountInCompanyCodeCurrency as AmountInGlLineItem,

// Summing amounts for the GL account
@Semantics.amount.currencyCode: 'Currency'
sum(_toJournalEntryItem.AmountInCompanyCodeCurrency) as AmountInJournalEntry,

GlLineItem.AccountingDocCreatedByUser as CreatedBy,
_toUser.UserDescription as CreatedByDesc,

// Associations
_toJournalEntryItem,
_toUser
}
where
GlLineItem.Ledger = '0L'
group by
GlLineItem.CompanyCode,
GlLineItem.AccountingDocument,
GlLineItem.PostingDate,
GlLineItem.FiscalPeriod,
GlLineItem.FiscalYear,
GlLineItem.Ledger,
GlLineItem.GLAccount,
GlLineItem.DocumentItemText,
_toJournalEntryItem.GLAccount,
GlLineItem.DebitCreditCode,
GlLineItem.CompanyCodeCurrency,
GlLineItem.AmountInCompanyCodeCurrency,
GlLineItem.AccountingDocCreatedByUser,
_toUser.UserDescription;

### Main.view.xml

<mvc:View controllerName="laporankas.laporankas.controller.Main"
    xmlns="sap.m"
    xmlns:uxap="sap.uxap"
    xmlns:mvc="sap.ui.core.mvc"
    xmlns:core="sap.ui.core"
    height="100%">
    <uxap:ObjectPageLayout
        id="idObjectPageLayout"
        showHeaderContent="true"
        toggleHeaderOnTitleClick="true"
        upperCaseAnchorBar="false"
        showFooter="true">
        <uxap:headerTitle>
            <uxap:ObjectPageDynamicHeaderTitle id="idObjectPageDynamicHeaderTitle">
                <uxap:expandedHeading>
                    <Title text="Laporan Kas" wrapping="true" />
                </uxap:expandedHeading>
                <uxap:snappedHeading>
                    <Title text="Laporan Kas" wrapping="true" />
                </uxap:snappedHeading>
                <uxap:expandedContent>
                    <Text text="{glRange>/glAccountFrom} - {glRange>/glAccountTo}" />
                </uxap:expandedContent>
                <uxap:snappedContent>
                    <Text text="{glRange>/glAccountFrom} - {glRange>/glAccountTo}" />
                </uxap:snappedContent>
            </uxap:ObjectPageDynamicHeaderTitle>
        </uxap:headerTitle>
        <uxap:headerContent>
            <HBox alignItems="End">
                <VBox>
                    <Label text="G/L Account" />
                    <ComboBox
                        id="idGlDataSetComboBox"
                        items="{glModel>/glDataSet}"
                        selectionChange="onGlDataSetComboBoxSelectionChange"
                        placeholder="Select GL Account">
                        <core:Item key="{glModel>gl}" text="{glModel>gl}" />
                    </ComboBox>
                </VBox>
                <VBox class="sapUiSmallMarginBegin">
                    <Label text="Posting Date" />
                    <DateRangeSelection change="onDateRangeSelectionChange" />
                </VBox>
                <VBox class="sapUiSmallMarginBegin">
                    <Label text="Created By" />
                    <ComboBox
                        id="idUserDataSetComboBox"
                        items="{userModel>/userDataSet}"
                        selectionChange="onUserDataSetComboBoxSelectionChange"
                        placeholder="Select Created By">
                        <core:Item key="{userModel>user}" text="{userModel>user}" />
                    </ComboBox>
                </VBox>
                <VBox class="sapUiSmallMarginBegin">
                    <Button type="Emphasized" text="Go" press="onGoButtonPress" />
                </VBox>
            </HBox>
        </uxap:headerContent>
        <uxap:sections>
            <uxap:ObjectPageSection
                showTitle="false"
                class="sapUiLargeMarginTopBottom">
                <uxap:subSections>
                    <uxap:ObjectPageSubSection>
                        <VBox>
                            <Table
                                sticky="ColumnHeaders"
                                id="idZglLineItemsTable"
                                items="{
                                    path: '/ZGL_LINE_ITEMS',
                                    filters: [
                                        {
                                            path: 'CreatedBy',
                                            operator: 'NE',
                                            value1: 'SAP_SYSTEM'
                                        },
                                        {
                                            path: 'GlAccount',
                                            operator: 'EQ',
                                            value1: '10010000'
                                        }
                                    ],
                                    sorter: {
                                        path: 'PostingDate',
                                        descending: true
                                    }
                                }"
                                growing="true"
                                growingThreshold="200"
                                alternateRowColors="true"
                                growingTriggerText="Load More"
                                noDataText="No data found"
                                mode="SingleSelectMaster"
                                updateFinished="onTableUpdateFinished">
                                <columns>
                                    <Column>
                                        <Text text="Date" />
                                    </Column>
                                    <Column>
                                        <Text text="Journal Entry" />
                                    </Column>
                                    <Column>
                                        <Text text="G/L Acc." />
                                    </Column>
                                    <Column>
                                        <Text text="Description" />
                                    </Column>
                                    <Column>
                                        <Text text="Opp. G/L Acc." />
                                    </Column>
                                    <Column>
                                        <Text text="Amount" />
                                    </Column>
                                    <Column>
                                        <Text text="CreatedBy" />
                                    </Column>
                                </columns>
                                <items>
                                    <ColumnListItem>
                                        <cells>
                                            <Text text="{PostingDate}" />
                                            <Text text="{AccDoc}" />
                                            <Text text="{GlAccount}" />
                                            <Text text="{Description}" />
                                            <Text text="{OpposingGLAccount}" />
                                            <Text text="{AmountInJournalEntry}" />
                                            <Text text="{CreatedByDesc}" />
                                        </cells>
                                    </ColumnListItem>
                                </items>
                            </Table>

                        </VBox>
                    </uxap:ObjectPageSubSection>
                </uxap:subSections>
            </uxap:ObjectPageSection>
        </uxap:sections>
        <uxap:footer>
            <OverflowToolbar>
                <ToolbarSpacer />
                <Button
                    type="Emphasized"
                    text="Export PDF"
                    press="onExportPDFButtonPress" />
            </OverflowToolbar>
        </uxap:footer>
    </uxap:ObjectPageLayout>
</mvc:View>

### Main.controller.js

sap.ui.define(
    [
        'sap/ui/core/mvc/Controller',
        'sap/ui/model/json/JSONModel',
        'sap/ui/model/Filter',
        'sap/ui/model/FilterOperator',
    ],
    function (Controller, JSONModel, Filter, FilterOperator, PdfmakeMin, vfs_fonts) {
        'use strict';

        return Controller.extend('laporankas.laporankas.controller.Main', {
            onInit: function () {
                const oModel = this.getOwnerComponent().getModel(); // Get the OData V4 model

                if (!oModel) {
                    console.error('OData V4 Model is not available.');
                    return;
                }

                // Define filters
                const client = this._getClientFromURL();
                const glAccount = client === '080' ? '0010010000' : '0011010020';

                const aFilters = [
                    new Filter('GlAccount', FilterOperator.EQ, glAccount),
                    new Filter('CreatedBy', FilterOperator.NE, 'SAP_SYSTEM'), // Example filter for CompanyCode
                ];

                // Bind the entity set with filters
                const oListBinding = oModel.bindList('/ZGL_LINE_ITEMS', undefined, undefined, aFilters);

                // Fetch filtered data
                oListBinding
                    .requestContexts()
                    .then((aContexts) => {
                        const aData = aContexts.map((oContext) => oContext.getObject());
                        console.log('Filtered Data:', aData); // Log the filtered data to the console
                    })
                    .catch((oError) => {
                        console.error('Error Fetching Data:', oError); // Log any errors
                    });
            },

            _getClientFromURL: function () {
                const urlParams = new URLSearchParams(window.location.search);
                return urlParams.get('sap-client') || '080'; // Default client
            }
        });
    },
);


### Example CDS result when I run in Eclipse

AccDocPostingDateGlAccountOpposing GlAccountAmount In Journal Item
1000001452024-12-301001000065301000700000
1000001452024-12-301001000063009000400000
1000001452024-12-301001000061012100500000

### The Issue (Result when the data bound in SAPUI5 App)

##### Here is the first result:

AccDocPostingDateGlAccountOpposing GlAccountAmount In Journal Item
1000001452024-12-301001000065301000700000
1000001452024-12-301001000065301000700000
1000001452024-12-301001000065301000700000

##### Here is the second result when I refresh:

AccDocPostingDateGlAccountOpposing GlAccountAmount In Journal Item
1000001452024-12-301001000063009000400000
1000001452024-12-301001000063009000400000
1000001452024-12-301001000063009000400000

### What I've done to solve the issue
- I tried to hit the entity endpoint in the browser/Postman, and I got the correct result as in Eclipse, which makes me a little bit confused.
- I tried to console.log it from the controller, but the result is not correct (duplicated).

Please let me know if there's something wrong with the CDS I created or my configuration in my SAPUI5 App or let me know if there's anything I need to do to solve this issue. Thank you in advance!

Accepted Solutions (1)

Accepted Solutions (1)

hjshin
Explorer
0 Kudos

@WG23 

Even if the key value is duplicated, it is displayed normally when calling the CDS Entity from Postman.
but When table binding is performed, data is expressed repeatedly due to the same key value.

This is
It's not a Binding error, it's a CDS key field configuration issue.
You need to change the key field configuration so that the key value is unique.

WG23
Explorer
0 Kudos

I recently resolved the issue by manually fetching the entity endpoint from the controller in the `onInit` method and binding the data to the table. However, I will consider your suggestion to change the key field configuration in the CDS for a more optimal solution. Thank you! @hjshin

Answers (2)

Answers (2)

hjshin
Explorer
0 Kudos

 

Hi @WG23 

You need to check the CDS key field configuration information.

Can one Line Item be extracted with the two (CompanyCode, AccountingDocument) key fields specified in CDS?
If more than one is extracted, the data may be displayed as duplicate when binding.

WG23
Explorer
0 Kudos
Only the AccountingDocument is unique, I want to get the opposing G/L Account and Ammount in the Journal Entry Item based on the Accounting Document and the G/L Account in the G/L line item. The results when I run the CDS in Eclipse is correct as I expected, but only when the data is bound in my SAPUI5 App it got duplicated
WG23
Explorer
0 Kudos
As you can see in this thread description, the different result when I run in the CDS in Eclipse and when it bound in SAPUI5 App
hjshin
Explorer
0 Kudos

* Try this:
1. Main.controller.js - Comment out onInit Method.

2. Main.view.xml
Set Table Binding property(item) information the same as Postman

3.Testing

* Questions
The binding information for Controller and View is the same. Is there a reason to set both?

* Note
To check OData service response data
Check the response of WebBrowser's Developer Tools -> Network Tab -> Batch request.

WG23
Explorer
0 Kudos

Hi @hjshin thanks for your comment.
What I do in the onInit function is just to console the data, to make sure if it is duplicated as it is in the main.view.xml or not. 
In the postman, I just run a GET protocol with just filter parameters like I did in the table items. But still, I got different results in Postman and in my SAPUI5 Application

WG23
Explorer
0 Kudos
@hjshin I checked the response in the WebBrowser's Dev Tools -> Network -> $Batch. The result is correct as expected, but when it bound to the table items the result got duplicated