package validators;
import api.v1.Order;
import api.v1.PoseidonAPIObject;
import com.avaje.ebean.BeanState;
import com.avaje.ebean.Ebean;
import com.avaje.ebean.Model;
import com.avaje.ebean.ValuePair;
import models.OrderModel;
import org.joda.time.DateTime;
import org.joda.time.DateTimeZone;
import org.slf4j.LoggerFactory;
import service.PoseidonService;
import java.util.*;
public class OrderValidator implements ModelValidator, ApiValidator {
private static org.slf4j.Logger log = LoggerFactory.getLogger(OrderValidator.class);
public OrderValidator() {
super();
}
@Override
public ValidationResult validateModel(Model modelObject) {
ValidationResult result = new ValidationResult();
OrderModel orderModel = (OrderModel) modelObject;
if (orderModel.met_ref == null || orderModel.met_ref.isEmpty()) {
result.addValidationError(new ValidationError(ValidationErrorType.ORDER_MISSING_METREF));
}
if (
((orderModel.custref_po_calloff == null) || orderModel.custref_po_calloff.isEmpty()) &&
((orderModel.custref_contractnum == null) || orderModel.custref_contractnum.isEmpty()) &&
((orderModel.custref_email == null) || orderModel.custref_email.isEmpty())
) {
result.addValidationError(new ValidationError(ValidationErrorType.ORDER_MISSING_PO_CALLOFF));
}
if (orderModel.customer_email != null && !orderModel.customer_email.isEmpty()) {
String[] emails = orderModel.customer_email.split("[ ,\\n]+");
for (String email : emails) {
if (!EmailMatcher.isValidEmail(email)) {
result.addValidationError(new ValidationError(ValidationErrorType.ORDER_INVALID_EMAIL,"customer_email",email));
}
}
}
if ( orderModel.product != null) {
ProductValidator pv = new ProductValidator();
ValidationResult r = pv.validateModel(orderModel.product);
for (ValidationError validationError : r.validationErrors) {
result.addValidationError(validationError);
}
}
result = validateDates(result, orderModel);
return result;
}
private ValidationResult validateDates(ValidationResult result, OrderModel orderModel) {
DateTime today = getToday();
Date start_date1 = orderModel.start_date1;
Date start_date2 = orderModel.start_date2;
Date start_date3 = orderModel.start_date3;
Date end_date1 = orderModel.end_date1;
Date end_date2 = orderModel.end_date2;
Date end_date3 = orderModel.end_date3;
DateTimeZone tz = PoseidonService.getTimeZone();
DateTime start1 = start_date1 != null ? new DateTime(start_date1,tz) : null;
DateTime start2 = start_date2 != null ? new DateTime(start_date2,tz) : null;
DateTime start3 = start_date3 != null ? new DateTime(start_date3,tz) : null;
DateTime end1 = end_date1 != null ? new DateTime(end_date1,tz) : null;
DateTime end2 = end_date2 != null ? new DateTime(end_date2,tz) : null;
DateTime end3 = end_date3 != null ? new DateTime(end_date3,tz) : null;
if (orderModel.id == null || orderModel.id == 0) { // new order
if (start1 != null && start1.isBefore(today)) {
log.debug("today = " + today + ", start_date1 = " + orderModel.start_date1);
result.addValidationError(new ValidationError(ValidationErrorType.ORDER_START_BEFORE_TODAY, "start_date1"));
}
if (start2 != null && start2.isBefore(today)) {
log.debug("today = " + today + ", start_date2 = " + orderModel.start_date2);
result.addValidationError(new ValidationError(ValidationErrorType.ORDER_START_BEFORE_TODAY, "start_date2"));
}
if (start3 != null && start3.isBefore(today)) {
log.debug("today = " + today + ", start_date3 = " + orderModel.start_date3);
result.addValidationError(new ValidationError(ValidationErrorType.ORDER_START_BEFORE_TODAY, "start_date3"));
}
}
BeanState bs = Ebean.getBeanState(orderModel);
Map<String, ValuePair> dirtyFields = bs.getDirtyValues();
if (isNewOrDirtyOrder(bs, dirtyFields, "start_date1", "end_date1") &&
start1 != null &&
end1 != null &&
end1.isBefore(start1)) {
result.addValidationError(new ValidationError(ValidationErrorType.ORDER_END_BEFORE_START, "start_date1"));
}
if ((isNewOrDirtyOrder(bs, dirtyFields, "start_date2", "end_date2")) &&
start2 != null &&
end2 != null &&
end2.isBefore(start2)) {
result.addValidationError(new ValidationError(ValidationErrorType.ORDER_END_BEFORE_START, "start_date2"));
}
if ((isNewOrDirtyOrder(bs, dirtyFields, "start_date3", "end_date3")) &&
start3 != null &&
end3 != null &&
end3.isBefore(start3)) {
result.addValidationError(new ValidationError(ValidationErrorType.ORDER_END_BEFORE_START, "start_date3"));
}
if (isNewOrDirtyOrder(bs, dirtyFields, "end_date3") &&
end3 != null &&
end3.isBefore(today)) {
result.addValidationError(new ValidationError(ValidationErrorType.ORDER_END_BEFORE_TODAY, "start_date3"));
}
if ((isNewOrDirtyOrder(bs, dirtyFields, "end_date2")) &&
start3 == null &&
end2 != null &&
end2.isBefore(today)) {
result.addValidationError(new ValidationError(ValidationErrorType.ORDER_END_BEFORE_TODAY, "start_date2"));
}
if ((isNewOrDirtyOrder(bs, dirtyFields, "end_date1")) &&
start2 == null &&
end1 != null &&
end1.isBefore(today)) {
result.addValidationError(new ValidationError(ValidationErrorType.ORDER_END_BEFORE_TODAY, "start_date1"));
}
if (start2 != null && end1.isAfter(start2)) {
result.addValidationError(new ValidationError(ValidationErrorType.ORDER_START_BEFORE_PREV_END, "start_date2"));
}
if (start3!= null && end2.isAfter(start3)) {
result.addValidationError(new ValidationError(ValidationErrorType.ORDER_START_BEFORE_PREV_END, "start_date3"));
}
if (end2 == null && start3 != null) {
result.addValidationError(new ValidationError(ValidationErrorType.ORDER_UNSPEC_END_BEFORE_START, "start_date3"));
}
if (end1 == null && start2 != null) {
result.addValidationError(new ValidationError(ValidationErrorType.ORDER_UNSPEC_END_BEFORE_START, "start_date2"));
}
return result;
}
private boolean isNewOrDirtyOrder(BeanState bs, Map<String, ValuePair> dirtyFields, String field) {
return bs.isNew() || dirtyFields.keySet().contains(field);
}
private boolean isNewOrDirtyOrder(BeanState bs, Map<String, ValuePair> dirtyFields, String field1, String field2) {
return bs.isNew() || (dirtyFields.keySet().contains(field1) || dirtyFields.keySet().contains(field2));
}
@Override
public ValidationResult validateApi(PoseidonAPIObject apiObject) {
Order apiOrder = (Order) apiObject;
ValidationResult result = new ValidationResult();
DateTime today = getToday();
Date start_date1 = apiOrder.start_date1;
Date start_date2 = apiOrder.start_date2;
Date start_date3 = apiOrder.start_date3;
Date end_date1 = apiOrder.end_date1;
Date end_date2 = apiOrder.end_date2;
Date end_date3 = apiOrder.end_date3;
DateTimeZone tz = PoseidonService.getTimeZone();
DateTime start1 = start_date1 != null ? new DateTime(start_date1,tz) : null;
DateTime start2 = start_date2 != null ? new DateTime(start_date2,tz) : null;
DateTime start3 = start_date3 != null ? new DateTime(start_date3,tz) : null;
DateTime end1 = end_date1 != null ? new DateTime(end_date1,tz) : null;
DateTime end2 = end_date2 != null ? new DateTime(end_date2,tz) : null;
DateTime end3 = end_date3 != null ? new DateTime(end_date3,tz) : null;
log.debug("p1 = " + start1 + " - " + end1 );
log.debug("p2 = " + start2 + " - " + end2 );
log.debug("p3 = " + start3 + " - " + end3 );
log.debug("today = " + today);
if (isNewOrder(apiOrder)) {
if (start1 != null && start1.isBefore(today)) {
log.debug("today = " + today + ", start_date1 = " + start1);
result.addValidationError(new ValidationError(ValidationErrorType.ORDER_START_BEFORE_TODAY, "start_date1"));
}
if (start2 != null && start2.isBefore(today)) {
log.debug("today = " + today + ", start_date2 = " + start2);
result.addValidationError(new ValidationError(ValidationErrorType.ORDER_START_BEFORE_TODAY, "start_date2"));
}
if (start3 != null && start3.isBefore(today)) {
log.debug("today = " + today + ", start_date3 = " + start3);
result.addValidationError(new ValidationError(ValidationErrorType.ORDER_START_BEFORE_TODAY, "start_date3"));
}
}
if (start1 != null && end1 != null && end1.isBefore(start1)) {
log.debug("start1= " + start1 + ", end_date1 = " + end1);
result.addValidationError(new ValidationError(ValidationErrorType.ORDER_END_BEFORE_START, "end_date1"));
}
if (start2 != null && end2 != null && end2.isBefore(start2)) {
log.debug("start2= " + start_date2 + ", end_date2 = " + end_date2);
result.addValidationError(new ValidationError(ValidationErrorType.ORDER_END_BEFORE_START, "end_date2"));
}
if (start3 != null && end3 != null && end3.isBefore(start3)) {
log.debug("start3= " + start_date3 + ", end_date3 = " + end_date3);
result.addValidationError(new ValidationError(ValidationErrorType.ORDER_END_BEFORE_START, "end_date3"));
}
if (end3 != null && end3.isBefore(today)) {
log.debug("today = " + today + ", end_date3 = " + end3);
result.addValidationError(new ValidationError(ValidationErrorType.ORDER_END_BEFORE_TODAY, "end_date3"));
}
if (start3 == null && end2 != null && end2.isBefore(today)) {
log.debug("today = " + today + ", end_date2 = " + end2);
result.addValidationError(new ValidationError(ValidationErrorType.ORDER_END_BEFORE_TODAY, "end_date2"));
}
if (start2 == null && end1 != null && end1.isBefore(today)) {
log.debug("today = " + today + ", end_date1 = " + end_date1);
result.addValidationError(new ValidationError(ValidationErrorType.ORDER_END_BEFORE_TODAY, "end_date1"));
}
if (start2 != null && end1.isAfter(start2)) {
log.debug("start2= " + start2 + ", end_date1 = " + end1);
result.addValidationError(new ValidationError(ValidationErrorType.ORDER_START_BEFORE_PREV_END, "start_date2"));
}
if (start3 != null && end2.isAfter(start3)) {
log.debug("start3= " + start_date3 + ", end_date2 = " + end_date2);
result.addValidationError(new ValidationError(ValidationErrorType.ORDER_START_BEFORE_PREV_END, "start_date3"));
}
if (end2 == null && start3 != null) {
result.addValidationError(new ValidationError(ValidationErrorType.ORDER_UNSPEC_END_BEFORE_START, "start_date3"));
}
if (end1 == null && start2 != null) {
result.addValidationError(new ValidationError(ValidationErrorType.ORDER_UNSPEC_END_BEFORE_START, "start_date2"));
}
if ( apiOrder.product != null){
ProductValidator pv = new ProductValidator();
ValidationResult r = pv.validateApi(apiOrder.product);
for (ValidationError validationError : r.validationErrors) {
result.addValidationError(validationError);
}
}
return result;
}
private boolean isNewOrder(Order apiOrder) {
return apiOrder.id == null || apiOrder.id == 0;
}
private DateTime getToday() {
DateTime now = PoseidonService.getNow();
return now.withTimeAtStartOfDay() ;
}
}