vendure-ecommerce / vendure

The commerce platform with customization in its DNA.
https://www.vendure.io
Other
5.53k stars 979 forks source link

Shipping method is not showing under the seller's channel in the admin interface. #2176

Open tlodge opened 1 year ago

tlodge commented 1 year ago

Describe the bug When I buy a product from a seller (using vendure v.2.0 beta) and the multivendor plugin, in the admin interface I am only able to see the shipping details when I am on the default channel. When I switch channels to my seller (bobs-parts) I cannot see the shipping details, but I believe I should to be able to, since the seller is responsible for their shipping and should see the shipping cost from their shipping method reflected in their order. This is also the case if I login to bobs-parts dashboard rather than as a superuser.

To Reproduce I have used the multivendor plugin from this commit. Though I have changed the lines (around line 27) in the multivendor plugin's mv-order-process.ts to:

 if (fromState === 'AddingItems' && toState === 'ArrangingPayment') {
            for (const line of data.order.shippingLines) {
                if (!line.shippingMethodId) {
                    return 'not all lines have shipping';
                }
            }
 }

but this is the only change I have made. I then create a seller as detailed in the multivendor.plugin.ts file and create a product for the seller in the admin interface. I can then create an order, assign shipping and checkout either through the graphql playground or through the remix shopfront.

Expected behavior I expected the seller (bobs-parts) to be able to see the order details in the admin interface, including the shipping details. But the shipping details are only visible when the default channel is selected.

Environment (please complete the following information):

dylviz commented 1 year ago

I don't think I see this issue when I run it. The change that you suggested allowed me to transition into the "Arranging Payment" state. Assuming you also got there, I only needed to set the payment method before I could see the orders split across different channels. Are you using a real payment method? For testing, I just used the following to set the payment method:

payment1: addPaymentToOrder(
        input: { method: "connected-payment-method", metadata: {}}
    ){
        ... on Order{id}
        ... on ErrorResult{
            errorCode
            message
        }
        ... on PaymentFailedError{
            paymentErrorMessage
        }
    }

Also, you mentioned that you modfied "mv-order-handler", I think you meant mv-order-process.ts, is that right? This is the name of the file I modified

tlodge commented 1 year ago

Hi @dylviz - thanks for this - yes, I meant mv-order-process.ts (have edited now).

Can I confirm what you are seeing? So if you set the payment method for a seller, and then check the list of orders in the admin interface are you seeing entries in the shipping column for both the default channel and the seller's channel? I only see entries for shipping in the default channel. So when in the seller's interface the order summary doesn't give any details about the shipping costs, which should also go to the seller, so should be there.

Looking at the responses to GetOrderList, when under the default channel in the admin interface the server responds with data for the shippingLines field, but in the seller's channel for the same query the, shippingLines is an empty array.

dylviz commented 1 year ago

Hi @dylviz - thanks for this - yes, I meant mv-order-process.ts (have edited now).

Can I confirm what you are seeing? So if you set the payment method for a seller, and then check the list of orders in the admin interface are you seeing entries in the shipping column for both the default channel and the seller's channel? I only see entries for shipping in the default channel. So when in the seller's interface the order summary doesn't give any details about the shipping costs, which should also go to the seller, so should be there.

Looking at the responses to GetOrderList, when under the default channel in the admin interface the server responds with data for the shippingLines field, but in the seller's channel for the same query the, shippingLines is an empty array.

From my understanding, I set the payment method for the aggregate order, not specific to a seller (maybe that's what you meant). then the aggregate order (still in the superadmin) automatically transitions to the state of "payment settled" and the aggregate order is then shown as separate order on the individual channels. On the "Default Channel" drop-down menu, I can select "Bobs-parts" and the appropriate order is shown as an "open" order. If I log into Bob's admin account, then I also see the same order ready for fulfillment.

I can see that the response to GetOrderList under any channel has a correct response. Does the "Order" table in your DB look something like this?: image

With an aggregate order and multiple seller orders

tlodge commented 1 year ago

Hi @dylviz - many thanks for taking a look. Yes, sorry, I meant that payment method is set for the aggregate order (rather than seller) and yes that's what my order table looks like. And yes I'm able to see all of the orders in bobs-parts and the order is ready for fulfillment, but when I'm in the bobs-parts channel I see the same order, but without the shipping details. I'll have another dig around - either I'm doing something wrong or I don't quite understand the usecase!

dylviz commented 1 year ago

The difference could potentially be that I logged in as a customer before placing the order and my customer account has a default shipping address associated with it. Did you place the order as a guest? I can try that and see what happens

tlodge commented 1 year ago

Hi @dylviz. Thanks again. I'm logged in as a customer. I tried both through the graphql client and remix and get the same result. Also tried off a vendure backend running the major branch and I get the same result. I'll dig around some more as soon as I get the chance.

dylviz commented 1 year ago

Just to be clear, you're not seeing just this section, correct?: image

And if you open up your customer's account, it looks like this?(shipping address): image

Just a heads up, once you get past this one, there's another problem that I'm seeing with one of the GraphQL queries. But maybe I can show that one once we figure out this one

tlodge commented 1 year ago

So the problem I have is as follows.

In the default channel, I see the shipping details as I would expect for an order:

listing-default-channel

and when I click on that order, I see the breakdown which includes the shipping costs:

order-default-channel

However, when I click on the bob's parts channel, I no longer see an entry in the shipping column:

listing-bobs-parts

And also do not see the shipping reflected in the order totals:

order-bobs-parts

Unless I'm confused/mistaken, I would expect that the seller would be able to see the shipping costs in their order, since they will be responsible for shipping. And obviously in the case where multiple items are bought across sellers, they'll only see the shipping details that are relevant to them.

tlodge commented 1 year ago

OK, so I have found a hacky fix, but my guess is that this is to do with a transition between shippingline details being in the order.lines array to being in the order.shippingLines array. So when I update the code in `mv-shipping-line-assignment-strategy.ts' to this:

async assignShippingLineToOrderLines(ctx: RequestContext, shippingLine: ShippingLine, order: Order) {
        const defaultChannel = await this.channelService.getDefaultChannel();
        await this.entityHydrator.hydrate(ctx, shippingLine, { relations: ['shippingMethod.channels'] });
        const { channels } = shippingLine.shippingMethod;

        if (channels.length === 2) {
            const sellerChannel = channels.find(c => !idsAreEqual(c.id, defaultChannel.id));

            if (sellerChannel) {
                const toreturn = order.lines.filter(line => idsAreEqual(line.sellerChannelId, sellerChannel.id));
                return (order.lines.filter(line => idsAreEqual(line.sellerChannelId, sellerChannel.id))).map(l=>{
                    l.shippingLineId = shippingLine.id;
                    return l;
                });
            }
        }
        return order.lines;
    }

(i.e. I explicitly set the shippingLineId in the order.lines array to the passed in shippingLine.id, then it behaves as I'd expect.

But I suspect that this is not a great fix. If you do get a chance to confirm @michaelbromley that this is what the issue is, then I'll sit back and wait until v2 comes out!