Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Possible bug with generating post request #1147

Open
stefan-willems-beech opened this issue Jan 31, 2023 · 3 comments
Open

Possible bug with generating post request #1147

stefan-willems-beech opened this issue Jan 31, 2023 · 3 comments
Assignees
Labels

Comments

@stefan-willems-beech
Copy link

Used libraries

core, jsonapi, jsonapi-angular, utils

Library version(s)

 "@datx/core": "^2.4.12",     "@datx/jsonapi": "^2.4.12",     "@datx/jsonapi-angular": "^2.4.12",     "@datx/utils": "^2.4.8",

Sample API response (if relevant)

Request objects

{
    "data": {
        "attributes": {
            "created_at": "2023-01-30T13:48:37.000Z"
        },
        "id": "130",
        "type": "order-lines",
        "relationships": {
            "product": {
                "data": {
                    "id": "166",
                    "type": "products"
                }
            }
        }
    }
}
{
    "data": {
        "attributes": {
            "created_at": "2023-01-30T13:48:37.000Z"
        },
        "id": "129",
        "type": "order-lines",
        "relationships": {
            "product": {
                "data": {
                    "id": "74",
                    "type": "products"
                }
            }
        }
    }
}

Environments with the issue

Chrome 109.0.5414.74, Ubuntu 22.04.1 LTS

Environments without the issue

No response

Current behavior

public persistOrder(): void {
        if (!this.isAbleToPersist()) {
            return;
        }

        const requestOptions = {
            queryParams: {
                include: 'order-lines.product'
            }
        } as IRequestOptions;

        const order = this.conceptOrder.value;
        order.status = OrderStatus.CONCEPT;
        order.retrieveAt = this.orderFormGroup.get('retrieveAt').value;
        order.reference = this.orderFormGroup.get('reference').value;

        this.orderPersistSubscription = order.save(requestOptions).pipe(
            mergeMap((persistedOrder: Order) => {
                console.log(persistedOrder.orderLines.map((orderLine: OrderLine) => orderLine.position)); // This is line 163
                const obs = this.updateOrderLines(persistedOrder);
                console.log(persistedOrder.orderLines.map((orderLine: OrderLine) => orderLine.position)); // This is line 165
                return combineLatest(obs);

            }),
        ).subscribe(() => {
            // this.router.navigate(['/orders/concept/list']);
        });
    }

    private updateOrderLines(order: Order): Observable<OrderLine>[] {
        const observables = [];
        const orderLineControls = (this.orderLineFormGroup.get('orderLines') as FormArray).controls;

        orderLineControls.forEach((orderLineFormGroup: FormGroup) => {
            if (orderLineFormGroup.pristine) {
                return;
            }

            const orderLine = order.orderLines.find(
                (findOrderLine: OrderLine) => findOrderLine.product?.reference === orderLineFormGroup.get('reference').value);

            if (!(orderLine instanceof OrderLine)) {
                return;
            }

            console.log(orderLine.position, orderLine.product.reference); // This is line 190
            this.updateOrderLine(orderLine, orderLineFormGroup);
            console.log(orderLine.position, orderLine.product.reference); /// This is line 192
            observables.push(orderLine.save());
        });

        return observables;
    }

    private updateOrderLine(orderLine: OrderLine, formGroup: FormGroup): void {
        orderLine.update({amount: formGroup.get('amount').value});
        orderLine.update({bigbagType: formGroup.get('bigbagType').value});
        orderLine.update({hasPallet: formGroup.get('hasPallet').value});
        orderLine.update({position: formGroup.get('position').value});
    }

logging

concept-order-create.component.ts:163(2) [false, false]
concept-order-create.component.ts:190 false '100123'
concept-order-create.component.ts:192 true '100123'
concept-order-create.component.ts:190 false '100267'
concept-order-create.component.ts:192 false '100267'
concept-order-create.component.ts:165 (2) [true, false]

I'm searching a little bit with the generation of the patch request towards the API

whereas currently it looks like the changes on the object aren't generated into the body of the request.
weirdly when editing the amount property of the orderLine model it does handle properly.

I don't know for sure if it is a bug or support question.

import {BaseModel} from './base-model';
import {Attribute} from '@datx/core';
import {BigbagType} from '../modules/shared/enums/bigbag-type.enum';
import {Product} from './product';
import * as moment from 'moment/moment';

export class OrderLine extends BaseModel {
    static type = 'order-lines';

    @Attribute() public amount: number;

    @Attribute({map: 'bigbag_type'}) public bigbagType: BigbagType;

    @Attribute({
        map: 'created_at',
        parse: (value: string) => value ? moment(value) : null,
        serialize: (value: moment.Moment) => value?.toISOString(),

    }) public createdAt?: moment.Moment;

    @Attribute({map: 'has_pallet'}) public hasPallet: boolean;

    @Attribute() public position: number;

    @Attribute({toOne: Product}) public product: Product;
}

Expected behavior

Request objects

{
    "data": {
        "attributes": {
            "created_at": "2023-01-30T13:48:37.000Z",
            "has_pallet": true
        },
        "id": "130",
        "type": "order-lines",
        "relationships": {
            "product": {
                "data": {
                    "id": "166",
                    "type": "products"
                }
            }
        }
    }
}

Reproduction steps

I have send most of my code regarding this issue
@stefan-willems-beech
Copy link
Author

stefan-willems-beech commented Jan 31, 2023

even when doing this

orderLine.hasPallet = true;
orderLine.save().subscribe();

it doesn't generate the hasPallet value inside the request data.

@stefan-willems-beech
Copy link
Author

It looks like, when the order is patched, the collection is internally updated overriding the changes on the linked order-line resources.

But with the JSON API SPEC it is not possible to create/update relations on the same request as the parent, which leaves us with the option to do it sequentially, running into this issue.

The thing I tried is to deepcopy the list of order-lines before persisting the order and when checking this list all the attributes still have the correct value but if I check the list of referenced order-lines they are reverted to the original state.

Is there an option to send with the save() method to not update the reference internally inside the collection? Which should result in the order-lines not being overridden?

This is a preferred situation because we navigate back to a list afterwards and then refetch all the records, which in turn should update the persisted order record.

@stefan-willems-beech
Copy link
Author

stefan-willems-beech commented Feb 13, 2023

There is something fundamentally not working:

I have tried the following:

this.orderPersistSubscription = combineLatest(this.orderLineService.currentPersistedOrderLines.map(
            (orderLine: OrderLine) => {
                delete orderLine['has_pallet'];
                delete orderLine['bigbag_type'];
                return orderLine.save();
            })
        ).pipe(
            // mergeMap(() => order.save(requestOptions)),
            // mergeMap(() => combineLatest(this.orderLineService.currentNewOrderLines.map(
            //     (orderLine: OrderLine) => orderLine.save()))
            // )
        ).subscribe(() => {
            // this.orderLineService.hasChanges = false;
            // this.router.navigate(['/orders/concept/list']);
        });

when removing the leftover properties which the map generates, the request works 2 times.
Once when has_pallet goes from true to false and the next request where it goes from false to true.
After these 2 requests the request isn't generated properly.

My thought process to handle the order overriding the references was to first patch the persisted order lines, to secondly post/patch the order and lastly to post the newly created order lines (because they need the order reference).

P.S. @DarkoKukovec could you give me any feedback on whether this issue is looked into or being tested, because we currently have a dependency on this very issue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants