Code Monkey home page Code Monkey logo

ecommerce's People

Contributors

ag4ta avatar andrzejkrzywda avatar antonpaisov avatar bbuchalter avatar bingerxd avatar bryszard avatar caws avatar dependabot-support avatar dependabot[bot] avatar fidel avatar fpacanowski avatar hugohernani avatar israelb avatar jandudulski avatar kennethkalmer avatar krzykamil avatar lukaszreszke avatar mostlyobvious avatar mpraglowski avatar ortegacmanuel avatar pansarin avatar pjurewicz avatar porbas avatar pstrzalk avatar saksham-jain avatar sardaukar avatar stolarczykt avatar swistak35 avatar tomaszpatrzek avatar wlk avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

ecommerce's Issues

Client panel - see my orders

At the moment we have some hardcoded clients for whom we can create orders.

This issue is meant to be a small step towards a more typical ecommerce where clients can create their orders.
However, for now let's just start with displaying the existing orders for the specific client.

Authentication could be part of this ticket, but we can also have a temporary shortcut of "selecting" the client which we want to log-in as.

It could be a new route like /client and then a new read model - ClientOrders.

Ordering::Order has lost its invariant

Moving ItemAddedToBasket and ItemRemovedFromBasket events to the Pricing BC caused that Ordering::Order can no longer protect its business rule of not adding items after order submission.

There had been raise AlreadySubmitted unless @state.equal?(:draft) before

Unit tests for processes

At the moment the processes are testes mostly via the integration tests.
Also, they are ignored by mutant (almost always a technical debt).

The goal of this ticket is to cover our processes with unit tests.

I'd aim for unit tests where events are the input and commands are the expected output.
However, they do have the drawback of risking being out of sync (when the published events are changed), but I hope this will be caught at integration level.

To whowever is interested in helping here, feel free to approach the process one by one. Just create a ticket per each process.

3+1 gratis

This feature allows customers to get 1 item free when they buy 3 items.

Archiving old orders

The orders screen becomes messy after some time.

Let's allow to archive specific orders - they would then disappear from the main screen.

Waitlist

Waitlist

Short description

This feature allows customers to "subscribe" to a product.

For the shop owner it allows to sell more and increase customer loyalty.

Impact Mapping

Which target groups are impacted?

Customers interested in a specific product which is not available at the moment.

It might be a product which they bought already (and a product which makes sense to buy regularly). This means it targets existing clients.

Also, new clients who are simply interested in that one product.

How do we want to change their behaviour?

Instead of silently leaving the shop, we want them to subscribe for the product.

How this feature makes more money?

We can look which products are mostly waited on and introduce them to the offer without a risk, potentially with a bigger margin.

We sell more stuff at a bigger margin.

We collect more emails.

Start from the middle

Add a link on a ProductPage - notify me when available.

When logged in client, show green confirmation. If not logged in - show link to login or field for email (without logging in).

Schedule an email when a product is available.

Middle is ready - next steps

Add link also to ProductList pages.

When notifying by email present a link to a cart with this item in the cart.

Add notifications system to the store and show unread notification there.

Open questions

  • Wait/subscribe to a combo of products - only then be notified when all are available

Testing

What are the acceptance scenarios?

  • Add product to offer
  • Make it unavailable
  • Log in as existing client (or present email field)
  • "notify me"
  • Enable product
  • assert email was sent with the right link

Cancel Order as UI button

It used to be the part of admin panel. Later it was removed, but the code under the hood is still there and tested.
Let's add this feature to the UI.

Ensure a customer exists before an order can be submitted or confirmed

As of recently, we've only had a check if customer id is not nil. What was missing and still is missing is to check whether a customer exists.

In a way, the check is there but only in the form of a read model coupling:
order.customer = Customer.find(event.data[:customer_id]).name

One option is to create a check in the SubmitOrder cmd handler. Another (better?) would be to turn the OrderSubmission process into actual process manager. This resembles a typical "checklist" characteristical to process managers.

Changing order discounts

Sometimes a client may negotiate well and try to improve the discount. Let's allow it to happen.

Client Authentication

Currently, a client can "log in" by navigating to /client URL, selecting desired client name, and clicking the login button.
The outcome of this issue should be a possibility to log in using the client login and password.

Typical ecommerce cart

Right now the system is more an order management system. Let's build a simple cart system. The simplest possible. Just adding/removing from cart. Confirming. Later we will extend it.

Separate context from application

Rails application is a web delivery mechanism for this ecommerce app. The contexts can live above the application to signify their independence. This can also draw greater line between write and read models — there they belong.

What's more — we can reuse contexts in applications based on different frameworks. Or even in different applications.

Get rid of the technical debt in OrdersController#update_discount

Recently I’ve introduced technical debt by adding not so nice the if statement to the update_discount action:

def update_discount
@order_id = params[:id]
if Orders::Order.find_by_uid(params[:id]).percentage_discount
command_bus.(
Pricing::ChangePercentageDiscount.new(
order_id: @order_id,
amount: params[:amount]
)
)
else
command_bus.(
Pricing::SetPercentageDiscount.new(
order_id: @order_id,
amount: params[:amount]
)
)
end
redirect_to edit_order_path(@order_id)
end

We would like to improve this code and make tech debt disappear.

Issues to resolve:

  • dependency on a read model
  • if statement

All suggestions on how to resolve this issue are greatly appreciated!

Simplify reusability of existing bounded contexts

We want to reuse some of the existing BCs.

Gathering them in one directory sounds like a good step forward. Also, this may be a good experiment in the popular topic of "in what directories should we put the domain code".

Create dedicated orders view for client

Currently, when a user logs in as a specific client /client they see a list of submitted orders. Paid, Expired and Cancelled orders are also visible. The user has the possibility to navigate to a specific order and see its details by clicking the order's number.

Then they're redirected to that order at /orders/id URL. The /orders URL is dedicated to being used by the shops' staff, not the client itself.

Therefore new view should be created for the client to see its orders. The view should contain ordered items and their final price.

Better uniqueness validation for coupons and happy hours

Currently the validation for uniqueness on registering coupons and creating happy hours is very simple - based on id only. If there is a coupon with a same id, the aggregate will mark it as @registered = true and raise an AlreadyRegistered error when somebody tries to register is again.

You can see it here - https://github.com/RailsEventStore/ecommerce/blob/0c4d8d0305c4ee6554e64789c32451c7ad826e81/ecommerce/pricing/lib/pricing/coupon.rb

It would be good to have some other uniqueness validation - eg. on the code attribute (in both coupons and happy hours). I'm not telling where such validation should be added. I'd say this is part of the exercise to decide about it.

Happy hour

This feature allows setting a certain period of time when a price of a certain product (or a list of products) is different.

CI: run only tests of the changed components

With the current high level of decoupling between our components (BC, read models, processes) it feels like we could speedup CI/CD process by only running those component tests which could potentially be impacted by the change.

Anyone knows how to start with this?

Show the order history - with RES browser

The idea here is to use RES browser. It's already used but the stream which we show doesn't contain all the data.

We can show the Orders read model as a stream (it's not yet a stream, but we can make it a stream). This would work, but it feels a bit like coupling this stream for two purposes:

  • building the Orders data structure for the client facing UI
  • use it in RES browser

Maybe as the first step, this coupling is fine.

Creating an explicit stream per read model sounds like a very good thing to do, anyway. This will simplify the process of rebuilding orders and show it as an example education-wise.

Display Shipments

Let's create a new menu item called "Shipments".

A list of those orders which have Shipment assigned will appear.

Probably we only need to react to "Shipment*" events.
The output would be an ActiveRecord model ShipmentsList::Shipment with shipment_id/order_id, address, status.

Removing order discounts

Currently we allow setting orders discount via the UI. It would be nice to be able to remove them

Change HappyHour into TimePromotion

The first implementation of HappyHour is not very useful in the context of ecommerce - it is a daily recurring promotion on products, while in ecommerce it's a rare use case. More often we need a one-time promotion constrained in time.

At the same time, this implementation had other flaws. It was:

  1. Using too big command
  2. Accessing internal data of an aggregate
  3. Reusing Products::Product read model for the context of the Happy Hour UI

As the next iteration we want to change it, simplify and get rid of some flaws at the same time.

The change - we will have TimePromotion instead of HappyHour.
It won't be a recurring promotion (for now), but just bounded by the start_time and end_time.
It won't be checking if there is an overlapping promotion, promotions can be stacked.
It won't be applied to a specific product, but rather to all products.

Duplicate products and customers

Steps to reproduce:
Setup database and then for example run rake db: seed a couple of times (seeds are using commands)
2022-05-19-152850_1197x864_scrot
There is some code that is supposed to raise an error, and it even has a test, but it seems the test are false positives
2022-05-19-153136_1463x814_scrot
Both the products and customers have multiple duplicates (same attributes, different ids). Seems resonable that this state should not be allowed

Type streams empty?

Running the demo, I see that even after creating several order, all type streams are empty. What am I doing wrong? Example for one of the types:

image

image

image

Integration tests shouldn't use commands for setup

In ideal world integration tests shouldn't use commands. Commands are hidden as the black box in the application.
Integration tests are the top of the testing pyramid and should assume as minimal internals as possible.

We should test via the HTTP layer instead.

Sometimes, when for some reason, certain data changes are not possible via the http, then using commands is allowed.

Also, when a feature is in progress, it might be a good idea to start with commands in the integration test but over time replace with "UI simulation".

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.