Copied to clipboard

Flag this post as spam?

This post will be reported to the moderators as potential spam to be looked at


  • Kevin 35 posts 159 karma points
    Nov 10, 2016 @ 18:33
    Kevin
    0

    Order Status Issues

    Hi,

    first let me describe what I am trying to achieve. I want to programmatically create an invoice and then automatically invoke custom logic. This logic should also be invoked if an existing invoice is paid in the Merchello back office.

    Below is the current outline of my solution:

    Using various API calls I:

    1) Create an unpaid invoice.

    2) Pay the invoice so that the invoice becomes "Paid" and "Not Fulfilled" and an order is implicitly created.

    3) Use a new task in the "OrderPreparationOrderCreate" to invoke custom logic.

    4) Based on the outcome of the logic above set the order status to either Fulfilled or Not Fullfilled.

    Would this be a sensible approach or is there a better strategy?

    What is confusing me is if I create an unpaid invoice so no order is created, the invoice still shows in the "Unfulfilled Orders" section of the back office even though there is no merchOrder record. Is this correct or a bug?

    And more interestingly, if in step 4 above my logic does not succeed and I change the order status to "Not Fulfilled", it confuses the backed. The order is still visible in the "Unfulfilled Orders" section but has a "Fulfilment Status" of "Fulfilled".

    I welcome any thoughts on this issue.

    Thanks

  • Rusty Swayne 1655 posts 4993 karma points c-trib
    Nov 10, 2016 @ 20:35
    Rusty Swayne
    0

    Hey Kevin,

    Orders (by default) are not created until a payment has been received and is generally done via the IPaymentResult.ApproveOrderCreation property.

    In the Merchello.config there is a property that can be used to override this setting.

    <!-- 
    Overrides the Payment Method's IPaymentResponse ApproveOrderCreation indicating an order should always be created no matter
    if the payment has been collected or not. 
    -->
    <setting alias="AlwaysApproveOrderCreation" value="false" /> 
    

    Setting this to true will create the order whether or not it is paid or not.

    The order status will be set to unfulfilled even if there is no order IF there are shippable items (until version 2.2 ... if I remember ... it would actually remain unfulfilled even if there were no shippable items, but that was updated and resolved).

  • Kevin 35 posts 159 karma points
    Nov 11, 2016 @ 08:38
    Kevin
    0

    Hi Rusty,

    thanks for your reply.

    I do have AlwaysApproveOrderCreation set to false which works as desired.

    To make myself clearer:

    1) I create an invoice - this works fine and no order is created owing to the flag above.

    2) As a second step in my own code, I then pay the invoice like this

    invoice.AuthorizeCapturePayment(cash.Key)
    

    These two steps alone result in a paid fulfilled invoice.

    However, when an invoice is paid, I want to do some custom logic. I do this by adding a step to the OrderPreparationOrderCreate task chain:

    <taskChain alias="OrderPreparationOrderCreate">
            <tasks>
                <task type="Merchello.Core.Chains.OrderCreation.ConvertInvoiceItemsToOrderItemsTask, Merchello.Core" />
                <task type="MyNamespace.MyClass.OrderCreatedTask, MyAssembly" />
            </tasks>
        </taskChain>
    

    And my code looks like:

    namespace MyNamespace
    {
        public class MyClass : OrderCreationAttemptChainTaskBase
        {
            public OrderCreatedTask(IInvoice invoice)
                : base(invoice)
            {
            }
    
            public override Attempt<IOrder> PerformTask(IOrder value)
            {
                if (!DoSomething())
                {
                    order.OrderStatus.Key = Constants.DefaultKeys.OrderStatus.NotFulfilled;
                }
                return Attempt<IOrder>.Succeed(value);
            }
        }
    }
    

    If the call to DoSomething() fails (returns false) I want the invoice (and order) to be unfulfilled. But what happens is the order correctly shows under "Unfulfilled Orders" but has a "Fulfillment Status" of Fulfilled as in the image below.

    enter image description here

    What I want to achieve is to have an unpaid invoice (effectively cancelling the payment just entered) and for the order to be unfulfilled. I hope that makes more sense.

    Thanks for your help.

  • Kevin 35 posts 159 karma points
    Nov 11, 2016 @ 09:10
    Kevin
    0

    To expand on this, the code above does not refund the invoice payments. I have added this to the code:

    public override Attempt<IOrder> PerformTask(IOrder value)
    {
        if (!DoSomething())
        {
            order.OrderStatus.Key = Constants.DefaultKeys.OrderStatus.NotFulfilled;
            var cashProvider = MerchelloContext.Current.Gateways.Payment.GetProviderByKey(
                            Constants.ProviderKeys.Payment.CashPaymentProviderKey);
            var cash = cashProvider?.PaymentMethods.FirstOrDefault();
            if (cash != null)
            {
                foreach (var p in invoice.Payments())
                {
                    invoice.RefundPayment(p, cash.Key, p.Amount);
                }
            }
        }
        return Attempt<IOrder>.Succeed(value);
    }
    

    And now in the "Unfulfilled Orders" section I see an unpaid invoice as desired, but the fulfillment status is still displaying as fulfilled.

    enter image description here

  • Rusty Swayne 1655 posts 4993 karma points c-trib
    Nov 11, 2016 @ 21:02
    Rusty Swayne
    0

    Hey Kevin,

    You might be fighting against some of the operations Merchello is trying to do behind the scenes - if there is already a shipment created with all shippable items added to the shipment AND the shipment is marked shipped or delivered the Fulfilled label in the angular may be catching ... I'd have to check that.

    Do you have shipments already?

  • Kevin 35 posts 159 karma points
    Nov 11, 2016 @ 21:18
    Kevin
    0

    Thanks Rusty. The item in question is not shippable.

  • Rusty Swayne 1655 posts 4993 karma points c-trib
    Nov 11, 2016 @ 21:54
    Rusty Swayne
    0

    Ah, we had quite a few people wanting sales without shippable items to be automatically fulfilled which was implemented in 2.2.0 - http://issues.merchello.com/youtrack/issue/M-1078

    Can you confirm it is just the label in the angular that you are fighting?

  • Kevin 35 posts 159 karma points
    Nov 11, 2016 @ 21:58
    Kevin
    0

    That would make sense. I am pretty sure it is just the label. All my other testing to date seems OK and the status guids in the database look OK.

  • Kevin 35 posts 159 karma points
    Nov 14, 2016 @ 17:48
    Kevin
    0

    I think I have got to the bottom of this now. I have changed this code

    var orderService = MerchelloContext.Current.Services.OrderService;
    order.OrderStatus.Key = Constants.DefaultKeys.OrderStatus.NotFulfilled;
    orderService.Save(order);
    

    to this code

    var orderService = MerchelloContext.Current.Services.OrderService;
    order.OrderStatus = orderService.GetOrderStatusByKey(Constants.DefaultKeys.OrderStatus.NotFulfilled);
    orderService.Save(order);
    

    and that seems to have solved it.

    I think the original code changed the cached copy of the data, and changed it incorrectly (bad data integrity, order status key and order status name mismatch).

    Once in cache, although the data in the database was correct, the bad integrity cached copy was being used. By flushing the cache the correctly saved data was read from the database causing the objects to be constructed correctly and so displayed in the back office correctly regardless which version of the code above is used.

  • Rusty Swayne 1655 posts 4993 karma points c-trib
    Nov 14, 2016 @ 19:45
    Rusty Swayne
    0

    Thanks Kevin,

    That does makes sense and I've made a note of the potential caching issue.

  • Kevin 35 posts 159 karma points
    Nov 15, 2016 @ 07:40
    Kevin
    1

    No worries,

    Whilst the caching issue should be investigated, the real issue is that I introduced bad data integrity by having an OrderStatus with a mismatching key and string name.

    Perhaps this could be avoided by either:

    1) When updating order.OrderStatus.Key have the object do a full refresh and cache update internally?

    or

    2) encapsulating my solution in my previous in a helper method like:

    orderService.ChangeStatus(Constants.DefaultKeys.OrderStatus.NotFulfilled);
    

    or

    orderService.SetStatus(Constants.DefaultKeys.OrderStatus.NotFulfilled);
    

    Just an idea...

Please Sign in or register to post replies

Write your reply to:

Draft