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

Improve order fulfillment process #1777

Merged
merged 65 commits into from
Mar 13, 2018

Conversation

mad-anne
Copy link
Contributor

@mad-anne mad-anne commented Feb 12, 2018

I want to merge this change because it simplifies order related logic. DeliveryGroup model is removed with all logic related to it and all order lines are placed directly into Order. Fulfillment model is introduced and it represents single shipment of many order lines in given quantity. There may be many fulfillments in an order and each order line may be in many fulfillments.

Closes #1767, closes #1850

Pull Request Checklist

  1. Privileged views and APIs are guarded by proper permission checks.
  2. All visible strings are translated with proper context.
  3. All data-formatting is locale-aware (dates, numbers, and so on).
  4. Database queries are optimized and the number of queries is constant.
  5. The changes are tested.
  6. The code is documented (docstrings, project documentation).
  7. Python code quality checks pass: pycodestyle, pydocstyle, pylint.
  8. JavaScript code quality checks pass: eslint.

[Edit]

Order details dashboard page.

screen shot 2018-03-07 at 10 08 27

Fulfillment view.

screen shot 2018-03-07 at 10 08 13

Cancel fulfillment modal.

cancel-fulfillment

Order details storefront.

screen shot 2018-03-12 at 10 34 08

@mad-anne mad-anne added this to the 2018.02 milestone Feb 12, 2018
@mad-anne mad-anne self-assigned this Feb 12, 2018
@mad-anne mad-anne force-pushed the order-fulfillment branch 2 times, most recently from 2ee01cd to 31f7f46 Compare February 20, 2018 11:28
@codecov
Copy link

codecov bot commented Feb 20, 2018

Codecov Report

Merging #1777 into master will decrease coverage by 0.17%.
The diff coverage is 60.49%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master    #1777      +/-   ##
==========================================
- Coverage   83.52%   83.34%   -0.18%     
==========================================
  Files         145      145              
  Lines        6250     6179      -71     
  Branches      664      652      -12     
==========================================
- Hits         5220     5150      -70     
- Misses        856      858       +2     
+ Partials      174      171       -3
Impacted Files Coverage Δ
saleor/dashboard/order/filters.py 88.88% <ø> (+2.68%) ⬆️
saleor/dashboard/order/urls.py 100% <ø> (ø) ⬆️
saleor/core/analytics.py 74.19% <0%> (+2.31%) ⬆️
saleor/dashboard/order/utils.py 100% <100%> (ø) ⬆️
saleor/account/views.py 73.97% <100%> (ø) ⬆️
saleor/product/utils.py 87.39% <100%> (ø) ⬆️
saleor/checkout/core.py 92.59% <100%> (-0.07%) ⬇️
saleor/dashboard/views.py 46.87% <33.33%> (+0.2%) ⬆️
saleor/dashboard/order/views.py 53.58% <33.92%> (-2.53%) ⬇️
saleor/dashboard/order/forms.py 73.95% <58.69%> (-4.23%) ⬇️
... and 4 more

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update ec5502c...3dbfb79. Read the comment docs.

@mad-anne mad-anne force-pushed the order-fulfillment branch 2 times, most recently from 5b05ada to 0850e76 Compare February 21, 2018 13:39
@codecov-io
Copy link

codecov-io commented Feb 22, 2018

Codecov Report

❗ No coverage uploaded for pull request base (master@9627bf5). Click here to learn what that means.
The diff coverage is 57.75%.

Impacted file tree graph

@@            Coverage Diff            @@
##             master    #1777   +/-   ##
=========================================
  Coverage          ?   83.94%           
=========================================
  Files             ?      151           
  Lines             ?     6427           
  Branches          ?      665           
=========================================
  Hits              ?     5395           
  Misses            ?      857           
  Partials          ?      175
Impacted Files Coverage Δ
saleor/dashboard/order/urls.py 100% <ø> (ø)
saleor/dashboard/order/filters.py 88.88% <ø> (ø)
saleor/core/analytics.py 74.19% <0%> (ø)
saleor/product/utils.py 87.23% <100%> (ø)
saleor/checkout/core.py 92.8% <100%> (ø)
saleor/dashboard/order/utils.py 100% <100%> (ø)
saleor/account/views.py 73.97% <100%> (ø)
saleor/dashboard/views.py 46.87% <33.33%> (ø)
saleor/dashboard/order/views.py 58.77% <34.28%> (ø)
saleor/order/emails.py 81.81% <38.46%> (ø)
... and 4 more

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 9627bf5...c9da395. Read the comment docs.


There are three possible delivery group statuses:
There are two possible fulfillment statuses:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't there exist a third status to indicate which groups are already dispatched?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I came from the assumption, that we consider fulfilled group as dispatched. This is why user also is asked for tracking number, when fulfilling the items.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How does that work with packing slips? The usual flow for a warehouse (where packing slips are used) is:

  1. dispatcher creates a shipment group (fulfillment)
  2. warehouse prints a packing slip
  3. warehouse collects and packages items
  4. warehouse dispatches the order (this is usually the moment you know the tracking number)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For now we could leave this as it is, cause it's quite simple. We can discuss further changes in the flow and open new PR if necessary.

model_name='order',
name='last_status_change',
),
migrations.RunPython(assign_order_to_lines, migrations.RunPython.noop)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we please move the RunPython action to a separate migration file?

@rafalp
Copy link
Contributor

rafalp commented Mar 2, 2018

@mad-anne could you please update your PR's description to mention that it also fixes the #1850 ? Thanks!

@mad-anne mad-anne force-pushed the order-fulfillment branch 2 times, most recently from 6cafb3a to 669a38d Compare March 7, 2018 09:14
@maarcingebala maarcingebala modified the milestones: 2018.02, 2018.03 Mar 7, 2018

@property
def quantity_fulfilled(self):
lines = FulfillmentLine.objects.filter(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Isn't the logic here too much for a property? I would expect from a property to perform rather simple logic based on model fields. Here we're performing a database query. I'm afraid that sooner or later this will lead to duplicated queries or someone will call it in a template (performing queries from templates isn't a good practice). Wouldn't it be better to denormalize this value and store it in the database? @patrys What's your view on that?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍 from my end. Executing queries in a property adds a hidden cost to something that looks innocent plus there is no way to optimize it.

As for the logic if FulfillmentLine objects for the order are already prefetched then iterating over lines.all() and filtering in Python is cheaper (as it won't touch the database) than executing a filter().

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

True, if we did the filtering in Python then such logic would be acceptable for a property in my opinion. I assume that anyone using this will have to ensure proper prefetching.

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

Successfully merging this pull request may close these issues.

Random order generator should also randomly set shipping price Improve order fulfillment process.
5 participants