Skip to content

Commit

Permalink
Extract DeliveryService - split code
Browse files Browse the repository at this point in the history
  • Loading branch information
cer committed Sep 30, 2019
1 parent 4672a5a commit e25652c
Show file tree
Hide file tree
Showing 32 changed files with 530 additions and 123 deletions.
1 change: 1 addition & 0 deletions ftgo-application/build.gradle
Expand Up @@ -5,6 +5,7 @@ dependencies {
compile project(":ftgo-order-service")
compile project(":ftgo-restaurant-service")
compile project(":ftgo-courier-service")
compile project(":ftgo-delivery-service")

compile "org.springframework.boot:spring-boot-starter-actuator:$springBootVersion"
compile "org.springframework.boot:spring-boot-starter-web:$springBootVersion"
Expand Down
@@ -1,6 +1,7 @@
package net.chrisrichardson.ftgo;

import net.chrisrichardson.ftgo.consumerservice.main.ConsumerServiceConfiguration;
import net.chrisrichardson.ftgo.deliveryservice.web.DeliveryServiceWebConfiguration;
import net.chrisrichardson.ftgo.orderservice.main.OrderServiceConfiguration;
import net.chrisrichardson.ftgo.restaurantservice.RestaurantServiceConfiguration;
import org.springframework.boot.SpringApplication;
Expand All @@ -14,7 +15,7 @@
@ComponentScan
@Import({ConsumerServiceConfiguration.class,
OrderServiceConfiguration.class,
RestaurantServiceConfiguration.class})
RestaurantServiceConfiguration.class, DeliveryServiceWebConfiguration.class})
public class FtgoApplicationMain {

public static void main(String[] args) {
Expand Down
Expand Up @@ -15,29 +15,13 @@ public CourierService(CourierRepository courierRepository) {
this.courierRepository = courierRepository;
}

@Transactional
public void updateAvailability(long courierId, boolean available) {
if (available)
noteAvailable(courierId);
else
noteUnavailable(courierId);
}

@Transactional
public Courier createCourier(PersonName name, Address address) {
Courier courier = new Courier(name, address);
courierRepository.save(courier);
return courier;
}

void noteAvailable(long courierId) {
courierRepository.findById(courierId).get().noteAvailable();
}

void noteUnavailable(long courierId) {
courierRepository.findById(courierId).get().noteUnavailable();
}

public Courier findCourierById(long courierId) {
return courierRepository.findById(courierId).get();
}
Expand Down
Expand Up @@ -24,12 +24,6 @@ public ResponseEntity<CreateCourierResponse> create(@RequestBody CreateCourierRe
return new ResponseEntity<>(new CreateCourierResponse(courier.getId()), HttpStatus.OK);
}

@RequestMapping(path="/couriers/{courierId}/availability", method= RequestMethod.POST)
public ResponseEntity<String> updateCourierLocation(@PathVariable long courierId, @RequestBody CourierAvailability availability) {
courierService.updateAvailability(courierId, availability.isAvailable());
return new ResponseEntity<>(HttpStatus.OK);
}

@RequestMapping(path="/couriers/{courierId}", method= RequestMethod.GET)
public ResponseEntity<Courier> get(@PathVariable long courierId) {
Courier courier = courierService.findCourierById(courierId);
Expand Down
@@ -0,0 +1,10 @@
package net.chrisrichardson.ftgo.deliveryservice.api.service;

import java.time.LocalDateTime;

public interface DeliveryService {
void scheduleDelivery(LocalDateTime readyBy, Long orderId);

void cancelDelivery(long orderId);

}
8 changes: 8 additions & 0 deletions ftgo-delivery-service/build.gradle
@@ -0,0 +1,8 @@
dependencies {
compile project(":ftgo-delivery-service-api")
compile project(":ftgo-common")

compile "org.springframework.boot:spring-boot-starter-data-jpa:$springBootVersion"
compile "org.springframework.boot:spring-boot-starter-web:$springBootVersion"

}
@@ -0,0 +1,43 @@
package net.chrisrichardson.ftgo.deliveryservice.domain;

import javax.persistence.*;
import java.time.LocalDateTime;

@Embeddable
public class Action {

@Enumerated(EnumType.STRING)
private ActionType type;
private LocalDateTime time;

@ManyToOne
@JoinColumn(name="order_id", nullable=false)
private Delivery order;

private Action() {
}

public Action(ActionType type, Delivery order, LocalDateTime time) {
this.type = type;
this.order = order;
this.time = time;
}

public boolean actionFor(Delivery order) {
return this.order.getId().equals(order.getId());
}

public static Action makePickup(Delivery order) {
return new Action(ActionType.PICKUP, order, null);
}

public static Action makeDropoff(Delivery order, LocalDateTime deliveryTime) {
return new Action(ActionType.DROPOFF, order, deliveryTime);
}


public ActionType getType() {
return type;
}

}
@@ -0,0 +1,4 @@
package net.chrisrichardson.ftgo.deliveryservice.domain;

public enum ActionType { PICKUP, DROPOFF
}
@@ -0,0 +1,7 @@
package net.chrisrichardson.ftgo.deliveryservice.domain;

public interface CustomDeliveryCourierRepository {

DeliveryCourier findOrCreateCourier(long courierId);

}
@@ -0,0 +1,21 @@
package net.chrisrichardson.ftgo.deliveryservice.domain;

import org.springframework.beans.factory.annotation.Autowired;

import javax.persistence.EntityManager;

public class CustomDeliveryCourierRepositoryImpl implements CustomDeliveryCourierRepository {

@Autowired
private EntityManager entityManager;

@Override
public DeliveryCourier findOrCreateCourier(long courierId) {
DeliveryCourier courier = entityManager.find(DeliveryCourier.class, courierId);
if (courier == null) {
courier = DeliveryCourier.create(courierId);
entityManager.persist(courier);
}
return courier;
}
}
@@ -0,0 +1,84 @@
package net.chrisrichardson.ftgo.deliveryservice.domain;

import net.chrisrichardson.ftgo.common.Address;
import net.chrisrichardson.ftgo.common.UnsupportedStateTransitionException;
import org.hibernate.annotations.DynamicUpdate;

import javax.persistence.*;
import java.time.LocalDateTime;

@Entity
@Table(name = "orders")
@Access(AccessType.FIELD)
@DynamicUpdate
public class Delivery {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

@Enumerated(EnumType.STRING)
@Column(name="orderState")
private DeliveryState deliveryState;

@ManyToOne(fetch = FetchType.LAZY)
private DeliveryRestaurant restaurant;

@ManyToOne
private DeliveryCourier assignedCourier;

@Embedded
@AttributeOverrides({
@AttributeOverride(name="street1", column = @Column(name="delivery_address_street1")),
@AttributeOverride(name="street2", column = @Column(name="delivery_address_street2")),
@AttributeOverride(name="city", column = @Column(name="delivery_address_city")),
@AttributeOverride(name="state", column = @Column(name="delivery_address_state")),
@AttributeOverride(name="zip", column = @Column(name="delivery_address_zip")),
}
)
private Address deliveryAddress;
private LocalDateTime deliveredTime;
private LocalDateTime pickedUpTime;

public Long getId() {
return id;
}


public void schedule(DeliveryCourier assignedCourier) {
this.assignedCourier = assignedCourier;
}


public void notePickedUp() {
switch (deliveryState) {
case READY_FOR_PICKUP:
this.deliveryState = DeliveryState.PICKED_UP;
this.pickedUpTime = LocalDateTime.now();
return;
default:
throw new UnsupportedStateTransitionException(deliveryState);
}
}

public void noteDelivered() {
switch (deliveryState) {
case PICKED_UP:
this.deliveryState = DeliveryState.DELIVERED;
this.deliveredTime = LocalDateTime.now();
return;
default:
throw new UnsupportedStateTransitionException(deliveryState);
}
}


public void cancel() {
// TODO should be a state change: this.state = DeliveryState.CANCELLED;
this.assignedCourier = null;
}

public DeliveryCourier getAssignedCourier() {
return assignedCourier;
}
}
@@ -0,0 +1,67 @@
package net.chrisrichardson.ftgo.deliveryservice.domain;

import org.hibernate.annotations.DynamicUpdate;

import javax.persistence.*;
import java.util.List;

@Entity
@Access(AccessType.FIELD)
@DynamicUpdate
@Table(name = "courier")
public class DeliveryCourier {

@Id
private long id;

@Embedded
private Plan plan;

private Boolean available;

private DeliveryCourier() {
}

public DeliveryCourier(long courierId) {
this.id = courierId;
this.plan = new Plan();
}

public static DeliveryCourier create(long courierId) {
return new DeliveryCourier(courierId);
}

public void noteAvailable() {
this.available = true;

}

public void addAction(Action action) {
plan.add(action);
}

public void cancelDelivery(Delivery order) {
plan.removeDelivery(order);
}

public boolean isAvailable() {
return available;
}

public Plan getPlan() {
return plan;
}

public long getId() {
return id;
}

public void noteUnavailable() {
this.available = false;
}

public List<Action> actionsForDelivery(Delivery order) {
return plan.actionsForDelivery(order);
}

}
@@ -0,0 +1,13 @@
package net.chrisrichardson.ftgo.deliveryservice.domain;

import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.CrudRepository;

import java.util.List;

public interface DeliveryCourierRepository extends CrudRepository<DeliveryCourier, Long>, CustomDeliveryCourierRepository {

@Query("SELECT c FROM DeliveryCourier c WHERE c.available = true")
List<DeliveryCourier> findAllAvailable();

}
@@ -0,0 +1,9 @@
package net.chrisrichardson.ftgo.deliveryservice.domain;

public interface DeliveryCourierService {
void notePickedUp(long orderId);

void noteDelivered(long orderId);

void updateAvailability(long courierId, boolean available);
}
@@ -0,0 +1,6 @@
package net.chrisrichardson.ftgo.deliveryservice.domain;

import org.springframework.data.repository.CrudRepository;

public interface DeliveryRepository extends CrudRepository<Delivery, Long> {
}
@@ -0,0 +1,24 @@
package net.chrisrichardson.ftgo.deliveryservice.domain;

import net.chrisrichardson.ftgo.common.Address;
import org.hibernate.annotations.DynamicUpdate;

import javax.persistence.*;

@Entity
@Table(name = "restaurant")
@Access(AccessType.FIELD)
@DynamicUpdate
public class DeliveryRestaurant {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

private String name;

@Embedded
private Address address;


}
@@ -0,0 +1,20 @@
package net.chrisrichardson.ftgo.deliveryservice.domain;

import net.chrisrichardson.ftgo.deliveryservice.api.service.DeliveryService;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.domain.EntityScan;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;

@Configuration
@EnableJpaRepositories
@EnableAutoConfiguration
@EntityScan
public class DeliveryServiceDomainConfiguration {

@Bean
public DeliveryService deliveryService(DeliveryRepository deliveryRepository, DeliveryCourierRepository courierRepository) {
return new DeliveryServiceImpl(courierRepository, deliveryRepository);
}
}

0 comments on commit e25652c

Please sign in to comment.