@Test
  public void testRunFailWithRetry() {
    final TaskModel taskModelMock = mock(TaskModel.class);
    final OrderCancelRecordEntryModel orderCancelRecordEntryMock =
        mock(OrderCancelRecordEntryModel.class);
    final OrderModificationRecordModel modificationRecordMock =
        mock(OrderModificationRecordModel.class);
    final DefaultSendOrderCancelRequestToDataHubHelper cSVHelperMock =
        mock(DefaultSendOrderCancelRequestToDataHubHelper.class);
    final TaskService paramTaskService = null;
    final OrderModel order = new OrderModel();
    final ModelService modelService = mock(ModelService.class);

    when(taskModelMock.getContext()).thenReturn(orderCancelRecordEntryMock);
    when(orderCancelRecordEntryMock.getModificationRecord()).thenReturn(modificationRecordMock);
    when(cSVHelperMock.createAndSendRawItem(orderCancelRecordEntryMock))
        .thenReturn(new DefaultSendToDataHubResult(HttpStatus.FORBIDDEN, ""));
    when(modificationRecordMock.getOrder()).thenReturn(order);

    cut.setModelService(modelService);
    cut.setOrderCancelRequestCSVHelper(cSVHelperMock);
    try {
      cut.run(paramTaskService, taskModelMock);
    } catch (final RetryLaterException e) {
      verify(cSVHelperMock).createAndSendRawItem(orderCancelRecordEntryMock);
      verify(modelService).save(order);
      assertEquals(OrderStatus.CANCELLING, order.getStatus());
      assertEquals(SendOrderCancelRequestAsCSVTaskRunner.DEFAULT_RETRY_DELAY, e.getDelay());
      return;
    }
    fail("RetryLaterException missing");
  }
  @Test
  public void testRunFailWithoutRetry() throws RetryLaterException {
    final TaskModel taskModelMock = mock(TaskModel.class);
    final OrderCancelRecordEntryModel orderCancelRecordEntryMock =
        mock(OrderCancelRecordEntryModel.class);
    final OrderModificationRecordModel modificationRecordMock =
        mock(OrderModificationRecordModel.class);
    final DefaultSendOrderCancelRequestToDataHubHelper cSVHelperMock =
        mock(DefaultSendOrderCancelRequestToDataHubHelper.class);
    final TaskService paramTaskService = null;
    final OrderModel order = new OrderModel();
    final ModelService modelService = mock(ModelService.class);

    when(taskModelMock.getContext()).thenReturn(orderCancelRecordEntryMock);
    when(orderCancelRecordEntryMock.getModificationRecord()).thenReturn(modificationRecordMock);
    when(cSVHelperMock.createAndSendRawItem(orderCancelRecordEntryMock))
        .thenReturn(new DefaultSendToDataHubResult(HttpStatus.FORBIDDEN, ""));
    when(modificationRecordMock.getOrder()).thenReturn(order);
    when(taskModelMock.getRetry()).thenReturn(Integer.valueOf(11));

    cut.setModelService(modelService);
    cut.setOrderCancelRequestCSVHelper(cSVHelperMock);
    cut.run(paramTaskService, taskModelMock);

    verify(cSVHelperMock).createAndSendRawItem(orderCancelRecordEntryMock);
    verify(modelService).save(order);
    assertEquals(OrderStatus.CANCELLING, order.getStatus());
  }
  @Test
  public void shouldStartApprovalProcessAndIgnoreInactiveCreditLimit() throws Exception {
    final String userId = "GC S HH";
    login(userId);

    // Set up credit limit data for test
    final B2BUnitModel unitLoggedIn = b2bUnitService.getUnitForUid("GC Sales Hamburg");
    final B2BCreditLimitModel creditLimitToUse =
        b2bUnitService.getParent(unitLoggedIn).getCreditLimit();
    creditLimitToUse.setActive(Boolean.TRUE);
    creditLimitToUse.setDateRange(B2BPeriodRange.DAY);
    creditLimitToUse.setDatePeriod(null);
    modelService.save(creditLimitToUse);

    // Credit Limit is active, so unit is returned
    final B2BUnitModel unitWithCreditLimit = b2bUnitService.getUnitWithCreditLimit(unitLoggedIn);
    Assert.assertNotNull(unitWithCreditLimit);

    // Update credit limit with past start/end dates as date range
    final B2BCreditLimitModel creditLimit = unitWithCreditLimit.getCreditLimit();
    creditLimit.setActive(Boolean.FALSE);

    modelService.save(creditLimit);

    // Create order which crosses credit limit
    final OrderModel order =
        createOrder(
            this.login("GC S HH"),
            140,
            OrderStatus.CREATED,
            productService.getProductForCode("testProduct0"));
    Assert.assertNotNull(order);

    final B2BApprovalProcessModel b2bApprovalProcessModel =
        getB2BApprovalProcessModelForOrder(order);

    // Process does not stop at waitProcessCreditLimit, so it should continue after waitProcess
    if (this.waitForProcessAction(b2bApprovalProcessModel.getCode(), "waitProcess", 20000)) {
      modelService.refresh(order);
      final Collection<WorkflowActionModel> actions =
          b2bWorkflowIntegrationService.getStartWorkflowActions(order.getWorkflow());
      Assert.assertEquals(1, actions.size());
      b2bWorkflowIntegrationService.approveWorkflowAction(actions.iterator().next());
    }

    // Credit limit is inactive, so unit is null
    final B2BUnitModel unitWithCreditLimitNull =
        b2bUnitService.getUnitWithCreditLimit(order.getUnit());
    Assert.assertNull(unitWithCreditLimitNull);

    // Process finishes and order placed above is approved - Order total is more than credit limit
    // amount, but
    // credit limit is inactive, so its ignored
    this.waitForProcessToEnd(b2bApprovalProcessModel.getCode(), 20000);
    this.modelService.refresh(order);
    this.modelService.refresh(b2bApprovalProcessModel);
    Assert.assertEquals(OrderStatus.APPROVED, order.getStatus());
    Assert.assertEquals(ProcessState.SUCCEEDED, b2bApprovalProcessModel.getProcessState());
  }
  @Test
  public void shouldStartApprovalProcessAndAssertApprovalFromMerchant() throws Exception {
    login("GC S HH");

    // Set up credit limit data for test
    final B2BUnitModel unitLoggedIn = b2bUnitService.getUnitForUid("GC Sales Hamburg");
    final B2BCreditLimitModel creditLimitToUse =
        b2bUnitService.getParent(unitLoggedIn).getCreditLimit();
    creditLimitToUse.setActive(Boolean.TRUE);
    creditLimitToUse.setDateRange(B2BPeriodRange.DAY);
    creditLimitToUse.setDatePeriod(null);
    modelService.save(creditLimitToUse);

    final OrderModel order =
        createOrder(
            this.login("GC S HH"),
            140,
            OrderStatus.CREATED,
            productService.getProductForCode("testProduct0"));
    Assert.assertNotNull(order);

    final B2BApprovalProcessModel b2bApprovalProcessModel =
        getB2BApprovalProcessModelForOrder(order);

    final B2BUnitModel unitWithCreditLimit = b2bUnitService.getUnitWithCreditLimit(order.getUnit());

    Assert.assertEquals("GC Sales DE", unitWithCreditLimit.getUid());

    if (this.waitForProcessAction(b2bApprovalProcessModel.getCode(), "waitProcess", 20000)) {
      modelService.refresh(order);
      final Collection<WorkflowActionModel> actions =
          b2bWorkflowIntegrationService.getStartWorkflowActions(order.getWorkflow());
      Assert.assertEquals(1, actions.size());
      b2bWorkflowIntegrationService.decideAction(
          actions.iterator().next(), B2BWorkflowIntegrationService.DECISIONCODES.APPROVE.name());
    }

    if (this.waitForProcessAction(
        b2bApprovalProcessModel.getCode(), "waitProcessCreditLimit", 20000)) {
      modelService.refresh(order);
      final Collection<WorkflowActionModel> actions =
          b2bWorkflowIntegrationService.getStartWorkflowActions(order.getWorkflow());
      Assert.assertEquals(1, actions.size());
      this.approveWorkflowAction(actions.iterator().next());
    }

    this.waitForProcessToEnd(b2bApprovalProcessModel.getCode(), 20000);
    this.modelService.refresh(order);
    this.modelService.refresh(b2bApprovalProcessModel);
    Assert.assertEquals(OrderStatus.APPROVED, order.getStatus());
    Assert.assertEquals(ProcessState.SUCCEEDED, b2bApprovalProcessModel.getProcessState());
  }
  @Test
  public void shouldTriggerCreditAlert() throws Exception {
    // Step 1 There should not be any template for Alert
    final EmployeeModel employeeModel = userService.getAdminUser();
    WorkflowTemplateModel workflowTemplateModel = null;
    try {
      workflowTemplateModel =
          workflowTemplateService.getWorkflowTemplateForCode("B2B-Alert-GC Acct Mgr");
    } catch (final UnknownIdentifierException uie) {
      // Do nothing
    }

    Assert.assertNull(workflowTemplateModel);

    /**
     * Create and order between 8000 - 10000 EUR for unit GC Sales DE Alert should be created for GC
     * Sales Rep
     */
    final OrderModel order = createOrder("GC Sales DE Boss", 900, OrderStatus.CREATED);
    Assert.assertNotNull(order);

    // Set up credit limit data for test so that it generates an Alert
    final B2BUnitModel unitLoggedIn = b2bUnitService.getUnitForUid("GC Sales DE");
    final B2BCreditLimitModel creditLimitToUse = unitLoggedIn.getCreditLimit();
    creditLimitToUse.setActive(Boolean.TRUE);
    creditLimitToUse.setDateRange(B2BPeriodRange.DAY);
    creditLimitToUse.setDatePeriod(null);
    creditLimitToUse.setAlertSentDate(null);
    modelService.save(creditLimitToUse);

    final B2BApprovalProcessModel b2bApprovalProcessModel =
        getB2BApprovalProcessModelForOrder(order);

    this.waitForProcessToEnd(b2bApprovalProcessModel.getCode(), 20000);
    this.modelService.refresh(order);
    this.modelService.refresh(b2bApprovalProcessModel);

    // verify that creditCheckAlert was sent - template and workflow should exist for an Alert
    workflowTemplateModel =
        workflowTemplateService.getWorkflowTemplateForCode("B2B-Alert-GC Acct Mgr");
    Assert.assertNotNull(workflowTemplateModel);
    final List<WorkflowModel> workflowModelList =
        newestWorkflowService.getWorkflowsForTemplateAndUser(workflowTemplateModel, employeeModel);
    Assert.assertTrue(CollectionUtils.isNotEmpty(workflowModelList));

    Assert.assertEquals(OrderStatus.APPROVED, order.getStatus());
    Assert.assertEquals(ProcessState.SUCCEEDED, b2bApprovalProcessModel.getProcessState());
  }
  @Test
  public void testHandleError() {
    final OrderCancelRecordEntryModel orderCancelRecordEntryMock =
        mock(OrderCancelRecordEntryModel.class);
    final OrderModificationRecordModel modificationRecordMock =
        mock(OrderModificationRecordModel.class);
    final OrderModel order = new OrderModel();
    final ModelService modelService = mock(ModelService.class);
    final TaskModel taskModelMock = mock(TaskModel.class);

    when(orderCancelRecordEntryMock.getModificationRecord()).thenReturn(modificationRecordMock);
    when(modificationRecordMock.getOrder()).thenReturn(order);
    when(taskModelMock.getContext()).thenReturn(orderCancelRecordEntryMock);

    cut.setModelService(modelService);
    cut.handleError(null, taskModelMock, null);

    verify(modelService).save(order);
    assertEquals(OrderStatus.CANCELLING, order.getStatus());
  }
  @Test
  @Ignore(
      "breaks in https://bamboo.hybris.com/download/HYBRISACCELERATORR-B2BACCELERATOR-BUILD, the test needs to be refactored.")
  public void shouldTriggerCreditAlertOnceForTimePeriod() throws Exception {
    /**
     * Create and order between 8000 - 10000 EUR for unit GC Sales DE Alert should be created for GC
     * Sales Rep
     */
    login("GC Sales DE Boss");

    final OrderModel order = createOrder("GC Sales DE Boss", 900, OrderStatus.CREATED);
    b2bCartService.removeSessionCart();
    Assert.assertNotNull(order);

    // Set up credit limit data for test - should not have alert sent date
    final B2BUnitModel unitLoggedIn = b2bUnitService.getUnitForUid("GC Sales DE");
    final B2BCreditLimitModel creditLimit = unitLoggedIn.getCreditLimit();
    creditLimit.setActive(Boolean.TRUE);
    creditLimit.setDateRange(B2BPeriodRange.DAY);
    creditLimit.setAmount(BigDecimal.valueOf(10000D));
    creditLimit.setAlertThreshold(BigDecimal.valueOf(8000D));
    creditLimit.setDatePeriod(null);
    creditLimit.setAlertSentDate(null);
    modelService.save(creditLimit);

    final B2BApprovalProcessModel b2bApprovalProcessModel =
        getB2BApprovalProcessModelForOrder(order);
    this.waitForProcessToEnd(b2bApprovalProcessModel.getCode(), 20000);
    this.modelService.refresh(order);
    this.modelService.refresh(b2bApprovalProcessModel);
    Assert.assertEquals(OrderStatus.APPROVED, order.getStatus());
    Assert.assertEquals(ProcessState.SUCCEEDED, b2bApprovalProcessModel.getProcessState());
    // Check Alert Sent Date exist now
    modelService.refresh(creditLimit);
    Assert.assertNotNull("AlertSendDate should have been set", creditLimit.getAlertSentDate());

    // create a second order 100 total against the same cost center which makes the orders total of
    // 9010 for the credit limit
    // the order still  exceeds Alert Limit (8000) but the total of all orders is below credit limit
    // (1000)

    final OrderModel order2 = createOrder("GC Sales DE Boss", 10, OrderStatus.CREATED);
    Assert.assertNotNull(order2);

    final B2BApprovalProcessModel b2bApprovalProcessModel2 =
        getB2BApprovalProcessModelForOrder(order2);
    this.waitForProcessToEnd(b2bApprovalProcessModel2.getCode(), 20000);
    this.modelService.refresh(order2);
    this.modelService.refresh(b2bApprovalProcessModel2);
    Assert.assertEquals(OrderStatus.APPROVED, order2.getStatus());
    Assert.assertEquals(ProcessState.SUCCEEDED, b2bApprovalProcessModel2.getProcessState());

    // Alert Sent Date was in past, so it's updated with Current Date
    modelService.refresh(creditLimit);

    Assert.assertNotNull("AlertSentDate should not be null", creditLimit.getAlertSentDate());
    Assert.assertTrue(
        String.format(
            "AlertSentDate %s shold be in the same day as %s",
            creditLimit.getAlertSentDate(), new Date()),
        DateUtils.isSameDay(creditLimit.getAlertSentDate(), new Date()));
  }