Example #1
0
  static void updateStatusFinished(
      OrderDTO order, Date startOfBillingPeriod, Date endOfBillingPeriod)
      throws SessionInternalError {

    // all one timers are done
    if (order.getOrderPeriod().getId() == Constants.ORDER_PERIOD_ONCE) {
      OrderBL orderBL = new OrderBL(order);
      orderBL.setStatus(null, Constants.ORDER_STATUS_FINISHED);
    } else { // recursive orders get more complicated
      // except those that are immortal :)
      if (order.getActiveUntil() == null) {
        return;
      }
      // see until when the incoming process will cover
      // compare if this is after the order exipres
      Logger log = Logger.getLogger(BillingProcessBL.class);
      log.debug(
          "order "
              + order.getId()
              + "end of bp "
              + endOfBillingPeriod
              + " active until "
              + order.getActiveUntil());
      if (endOfBillingPeriod.compareTo(Util.truncateDate(order.getActiveUntil())) >= 0) {
        OrderBL orderBL = new OrderBL(order);
        orderBL.setStatus(null, Constants.ORDER_STATUS_FINISHED);
      }
    }
  }
Example #2
0
  public CachedRowSet getList(Integer orderId) throws SQLException, Exception {
    prepareStatement(InvoiceSQL.customerList);

    // find out the user from the order
    Integer userId;
    OrderBL order = new OrderBL(orderId);
    if (order.getEntity().getUser().getCustomer().getParent() == null) {
      userId = order.getEntity().getUser().getUserId();
    } else {
      userId = order.getEntity().getUser().getCustomer().getParent().getBaseUser().getUserId();
    }
    cachedResults.setInt(1, userId.intValue());
    execute();
    conn.close();
    return cachedResults;
  }
  public void updateProvisioningStatus(Integer in_order_id, Integer in_order_line_id, String result)
      throws EmptyResultDataAccessException {

    OrderDAS orderDb = new OrderDAS();
    OrderDTO order = orderDb.find(in_order_id);
    OrderBL order_bl = new OrderBL(order);

    OrderLineDAS lineDAS = new OrderLineDAS();
    OrderLineDTO order_line =
        lineDAS.findForUpdate(in_order_line_id); // lineDb.findNow(in_order_line_id);

    if (order_line == null) {
      throw new EmptyResultDataAccessException("Didn't find order line: " + in_order_line_id, 1);
    }
    LOG.debug("update order line : " + order_line.getId());

    if (result.equals("fail")) {
      order_bl.setProvisioningStatus(in_order_line_id, Constants.PROVISIONING_STATUS_FAILED);
      LOG.debug("Provisioning status set to 'FAILED' for order line : " + order_line.getId());
    } else if (result.equals("unavailable")) {
      order_bl.setProvisioningStatus(in_order_line_id, Constants.PROVISIONING_STATUS_UNAVAILABLE);
      LOG.debug("Provisioning status set to 'UNAVAILABLE' for order line : " + order_line.getId());
    } else if (result.equals("success")) {
      LOG.debug("order line Status before : " + order_line.getProvisioningStatusId());
      if (order_line
          .getProvisioningStatusId()
          .equals(Constants.PROVISIONING_STATUS_PENDING_ACTIVE)) {
        order_bl.setProvisioningStatus(in_order_line_id, Constants.PROVISIONING_STATUS_ACTIVE);
        LOG.debug("Provisioning status set to 'ACTIVE' for order line : " + order_line.getId());
      } else if (order_line
          .getProvisioningStatusId()
          .equals(Constants.PROVISIONING_STATUS_PENDING_INACTIVE)) {
        order_bl.setProvisioningStatus(in_order_line_id, Constants.PROVISIONING_STATUS_INACTIVE);
        LOG.debug("Provisioning status set to 'INACTIVE' for order line : " + order_line.getId());
      } else {
        throw new SessionInternalError(
            "Invalid or unexpected "
                + "provisioning status: "
                + order_line.getProvisioningStatusId());
      }
    } else {
      throw new SessionInternalError(
          "Can not process message with " + "result property value " + result);
    }

    lineDAS.flush();
  }
Example #4
0
  /**
   * This will remove all the records (sql delete, not just flag them). It will also update the
   * related orders if applicable
   */
  public void delete(Integer executorId) throws SessionInternalError {
    if (invoice == null) {
      throw new SessionInternalError("An invoice has to be set before delete");
    }

    // prevent a delegated Invoice from being deleted
    if (invoice.getDelegatedInvoiceId() != null && invoice.getDelegatedInvoiceId().intValue() > 0) {
      SessionInternalError sie =
          new SessionInternalError("A carried forward Invoice cannot be deleted");
      sie.setErrorMessages(
          new String[] {"InvoiceDTO,invoice,invoice.error.fkconstraint," + invoice.getId()});
      throw sie;
    }
    // start by updating purchase_order.next_billable_day if applicatble
    // for each of the orders included in this invoice
    for (OrderProcessDTO orderProcess : (Collection<OrderProcessDTO>) invoice.getOrderProcesses()) {
      OrderDTO order = orderProcess.getPurchaseOrder();
      if (order.getNextBillableDay() == null) {
        // the next billable day doesn't need updating
        if (order.getStatusId().equals(Constants.ORDER_STATUS_FINISHED)) {
          OrderBL orderBL = new OrderBL(order);
          orderBL.setStatus(null, Constants.ORDER_STATUS_ACTIVE);
        }
        continue;
      }
      // only if this invoice is the responsible for the order's
      // next billable day
      if (order.getNextBillableDay().equals(orderProcess.getPeriodEnd())) {
        order.setNextBillableDay(orderProcess.getPeriodStart());
        if (order.getStatusId().equals(Constants.ORDER_STATUS_FINISHED)) {
          OrderBL orderBL = new OrderBL(order);
          orderBL.setStatus(null, Constants.ORDER_STATUS_ACTIVE);
        }
      }
    }

    // go over the order process records again just to delete them
    // we are done with this order, delete the process row
    for (OrderProcessDTO orderProcess : (Collection<OrderProcessDTO>) invoice.getOrderProcesses()) {
      OrderDTO order = orderProcess.getPurchaseOrder();
      OrderProcessDAS das = new OrderProcessDAS();
      order.getOrderProcesses().remove(orderProcess);
      das.delete(orderProcess);
    }
    invoice.getOrderProcesses().clear();

    // get rid of the contact associated with this invoice
    try {
      ContactBL contact = new ContactBL();
      if (contact.setInvoice(invoice.getId())) {
        contact.delete();
      }
    } catch (Exception e1) {
      LOG.error("Exception deleting the contact of an invoice", e1);
    }

    // remove the payment link/s
    PaymentBL payment = new PaymentBL();
    Iterator<PaymentInvoiceMapDTO> it = invoice.getPaymentMap().iterator();
    while (it.hasNext()) {
      PaymentInvoiceMapDTO map = it.next();
      payment.removeInvoiceLink(map.getId());
      invoice.getPaymentMap().remove(map);
      // needed because the collection has changed
      it = invoice.getPaymentMap().iterator();
    }

    // log that this was deleted, otherwise there will be no trace
    if (executorId != null) {
      eLogger.audit(
          executorId,
          invoice.getBaseUser().getId(),
          Constants.TABLE_INVOICE,
          invoice.getId(),
          EventLogger.MODULE_INVOICE_MAINTENANCE,
          EventLogger.ROW_DELETED,
          null,
          null,
          null);
    }

    // before delete the invoice most delete the reference in table
    // PAYMENT_INVOICE
    new PaymentInvoiceMapDAS().deleteAllWithInvoice(invoice);

    Set<InvoiceDTO> invoices = invoice.getInvoices();
    if (invoices.size() > 0) {
      for (InvoiceDTO delegate : invoices) {
        // set status to unpaid as against carried
        delegate.setInvoiceStatus(new InvoiceStatusDAS().find(Constants.INVOICE_STATUS_UNPAID));
        // remove delegated invoice link
        delegate.setInvoice(null);
        getHome().save(delegate);
      }
    }

    // now delete the invoice itself
    getHome().delete(invoice);
    getHome().flush();
  }
Example #5
0
  private boolean processOrdersForUser(
      UserDTO user,
      Integer entityId,
      BillingProcessDTO process,
      boolean isReview,
      boolean onlyRecurring,
      boolean useProcessDateForInvoice,
      int maximumPeriods,
      Hashtable<TimePeriod, NewInvoiceDTO> newInvoices) {

    boolean includedOrders = false;
    Integer userId = user.getUserId();

    LOG.debug("Processing orders for user " + userId);

    // initialize the subaccounts iterator if this user is a parent
    Iterator subAccountsIt = null;
    if (user.getCustomer().getIsParent() != null
        && user.getCustomer().getIsParent().intValue() == 1) {
      UserBL parent = new UserBL(userId);
      subAccountsIt = parent.getEntity().getCustomer().getChildren().iterator();
    }

    // get the orders that might be processable for this user
    OrderDAS orderDas = new OrderDAS();
    Collection<OrderDTO> orders = orderDas.findByUser_Status(userId, Constants.ORDER_STATUS_ACTIVE);

    // go through each of them, and update the DTO if it applies
    for (OrderDTO order : orders) {
      LOG.debug("Processing order :" + order.getId());
      // apply any order processing filter pluggable task
      try {
        PluggableTaskManager taskManager =
            new PluggableTaskManager(entityId, Constants.PLUGGABLE_TASK_ORDER_FILTER);
        OrderFilterTask task = (OrderFilterTask) taskManager.getNextClass();
        boolean isProcessable = true;
        while (task != null) {
          isProcessable = task.isApplicable(order, process);
          if (!isProcessable) {
            break; // no need to keep doing more tests
          }
          task = (OrderFilterTask) taskManager.getNextClass();
        }

        // include this order only if it complies with all the
        // rules
        if (isProcessable) {

          LOG.debug("Order processable");

          if (onlyRecurring) {
            if (order.getOrderPeriod().getId() != Constants.ORDER_PERIOD_ONCE) {
              includedOrders = true;
              LOG.debug("It is not one-timer. " + "Generating invoice");
            }
          } else {
            includedOrders = true;
          }
          /*
           * now find if there is already an invoice being
           * generated for the given due date period
           */
          // find the due date that applies to this order
          OrderBL orderBl = new OrderBL();
          orderBl.set(order);
          TimePeriod dueDatePeriod = orderBl.getDueDate();
          // look it up in the hashtable
          NewInvoiceDTO thisInvoice = (NewInvoiceDTO) newInvoices.get(dueDatePeriod);
          if (thisInvoice == null) {
            LOG.debug(
                "Adding new invoice for period "
                    + dueDatePeriod
                    + " process date:"
                    + process.getBillingDate());
            // we need a new one with this period
            // define the invoice date
            thisInvoice = new NewInvoiceDTO();
            if (useProcessDateForInvoice) {
              thisInvoice.setDate(process.getBillingDate());
            } else {
              thisInvoice.setDate(
                  orderBl.getInvoicingDate(),
                  order.getOrderPeriod().getId() != Constants.ORDER_PERIOD_ONCE);
            }
            thisInvoice.setIsReview(isReview ? new Integer(1) : new Integer(0));
            thisInvoice.setCarriedBalance(BigDecimal.ZERO);
            thisInvoice.setDueDatePeriod(dueDatePeriod);
          } else {
            LOG.debug("invoice found for period " + dueDatePeriod);
            if (!useProcessDateForInvoice) {
              thisInvoice.setDate(
                  orderBl.getInvoicingDate(),
                  order.getOrderPeriod().getId() != Constants.ORDER_PERIOD_ONCE);
            }
          }
          /*
           * The order periods plug-in might not add any period. This should not happen
           * but if it does, the invoice should not be included
           */
          if (addOrderToInvoice(
              entityId, order, thisInvoice, process.getBillingDate(), maximumPeriods)) {
            // add or replace
            newInvoices.put(dueDatePeriod, thisInvoice);
          }
          LOG.debug("After putting period there are " + newInvoices.size() + " periods.");

          // here it would be easy to update this order
          // to_process and
          // next_billable_time. I can't do that because these
          // fields
          // will be read by the following tasks, and they
          // will asume
          // they are not modified.
        }

      } catch (PluggableTaskException e) {
        LOG.fatal("Problems handling order filter task.", e);
        throw new SessionInternalError("Problems handling order filter task.");
      } catch (TaskException e) {
        LOG.fatal("Problems excecuting order filter task.", e);
        throw new SessionInternalError("Problems executing order filter task.");
      }
    } // for - all the orders for this user

    // see if there is any subaccounts to include in this invoice
    while (subAccountsIt != null) { // until there are no more subaccounts (subAccountsIt != null) {
      CustomerDTO customer = null;
      while (subAccountsIt.hasNext()) {
        customer = (CustomerDTO) subAccountsIt.next();
        if (customer.getInvoiceChild() == null || customer.getInvoiceChild().intValue() == 0) {
          break;
        } else {
          LOG.debug("Subaccount not included in parent's invoice " + customer.getId());
          customer = null;
        }
      }
      if (customer != null) {
        userId = customer.getBaseUser().getUserId();
        // if the child does not have any orders to invoice, this should
        // not affect the current value of includedOrders
        if (processOrdersForUser(
            customer.getBaseUser(),
            entityId,
            process,
            isReview,
            onlyRecurring,
            useProcessDateForInvoice,
            maximumPeriods,
            newInvoices)) {
          // if ANY child has orders to invoice, it is enough for includedOrders to be true
          includedOrders = true;
        }
        LOG.debug("Now processing subaccount " + userId);

      } else {
        subAccountsIt = null;
        LOG.debug("No more subaccounts to process");
      }
    }

    return includedOrders;
  }
Example #6
0
  public InvoiceDTO[] generateInvoice(
      BillingProcessDTO process, UserDTO user, boolean isReview, boolean onlyRecurring)
      throws SessionInternalError {

    Integer userId = user.getUserId();
    Integer entityId = user.getEntity().getId();

    // get the configuration
    boolean useProcessDateForInvoice = true;
    int maximumPeriods = 1;
    boolean paymentApplication = false;
    try {
      ConfigurationBL config = new ConfigurationBL(process.getEntity().getId());
      useProcessDateForInvoice = config.getEntity().getInvoiceDateProcess() == 1;
      maximumPeriods = config.getEntity().getMaximumPeriods();
      paymentApplication = config.getEntity().getAutoPaymentApplication() == 1;
    } catch (Exception e) {
      // swallow exception
    }

    // this contains the generated invoices, one per due date
    // found in the applicable purchase orders.
    // The key is the object TimePeriod
    Hashtable<TimePeriod, NewInvoiceDTO> newInvoices = new Hashtable<TimePeriod, NewInvoiceDTO>();
    InvoiceDTO[] retValue = null;

    LOG.debug(
        "In generateInvoice for user " + userId + " process date:" + process.getBillingDate());

    /*
     * Go through the orders first
     * This method will recursively call itself to find sub-accounts in any
     * level
     */
    boolean includedOrders =
        processOrdersForUser(
            user,
            entityId,
            process,
            isReview,
            onlyRecurring,
            useProcessDateForInvoice,
            maximumPeriods,
            newInvoices);

    if (!includedOrders || newInvoices.size() == 0) {
      // check if invoices without orders are allowed
      PreferenceBL preferenceBL = new PreferenceBL();
      try {
        preferenceBL.set(entityId, Constants.PREFERENCE_ALLOW_INVOICES_WITHOUT_ORDERS);
      } catch (EmptyResultDataAccessException fe) {
        // use default
      }

      if (preferenceBL.getInt() == 0) {
        LOG.debug("No applicable orders. No invoice generated (skipping invoices).");
        return null;
      }
    }

    if (!isReview) {
      for (Map.Entry<TimePeriod, NewInvoiceDTO> newInvoiceEntry : newInvoices.entrySet()) {
        // process events before orders added to invoice
        processOrderToInvoiceEvents(newInvoiceEntry.getValue(), entityId);
      }
    }

    /*
     * Include those invoices that should've been paid
     * (or have negative balance, as credits)
     */
    LOG.debug("Considering overdue invoices");
    // find the invoice home interface
    InvoiceDAS invoiceDas = new InvoiceDAS();
    // any of the new invoices being created could hold the overdue invoices
    NewInvoiceDTO holder =
        newInvoices.isEmpty() ? null : (NewInvoiceDTO) newInvoices.elements().nextElement();

    Collection dueInvoices = invoiceDas.findWithBalanceByUser(user);
    LOG.debug("Processing invoices for user " + user.getUserId());
    // go through each of them, and update the DTO if it applies

    for (Iterator it = dueInvoices.iterator(); it.hasNext(); ) {
      InvoiceDTO invoice = (InvoiceDTO) it.next();
      if (invoice.getToProcess() == InvoiceDTO.DO_NOT_PROCESS) {
        LOG.debug("skipping invoice " + invoice.getId() + " because DO_NOT_PROCESS is set");
        continue;
      }
      LOG.debug("Processing invoice " + invoice.getId());
      // apply any invoice processing filter pluggable task
      try {
        PluggableTaskManager taskManager =
            new PluggableTaskManager(entityId, Constants.PLUGGABLE_TASK_INVOICE_FILTER);
        InvoiceFilterTask task = (InvoiceFilterTask) taskManager.getNextClass();
        boolean isProcessable = true;
        while (task != null) {
          isProcessable = task.isApplicable(invoice, process);
          if (!isProcessable) {
            break; // no need to keep doing more tests
          }
          task = (InvoiceFilterTask) taskManager.getNextClass();
        }

        // include this invoice only if it complies with all the rules
        if (isProcessable) {
          // check for an invoice
          if (holder == null) {
            // Since there are no new invoices (therefore no orders),
            // don't let invoices with positive balances generate
            // an invoice.
            if (BigDecimal.ZERO.compareTo(invoice.getBalance()) < 0) {
              continue;
            }

            // no invoice/s yet (no applicable orders), so create one
            holder = new NewInvoiceDTO();
            holder.setDate(process.getBillingDate());
            holder.setIsReview(isReview ? new Integer(1) : new Integer(0));
            holder.setCarriedBalance(BigDecimal.ZERO);
            holder.setInvoiceStatus(new InvoiceStatusDAS().find(Constants.INVOICE_STATUS_UNPAID));

            // need to set a due date, so use the order default
            OrderBL orderBl = new OrderBL();
            OrderDTO order = new OrderDTO();
            order.setBaseUserByUserId(user);
            orderBl.set(order);
            TimePeriod dueDatePeriod = orderBl.getDueDate();

            holder.setDueDatePeriod(dueDatePeriod);
            newInvoices.put(dueDatePeriod, holder);
          }

          InvoiceBL ibl = new InvoiceBL(invoice);
          holder.addInvoice(ibl.getDTO());
          // for those invoices wiht only overdue invoices, the
          // currency has to be initialized

          if (holder.getCurrency() == null) {
            holder.setCurrency(invoice.getCurrency());
          } else if (holder.getCurrency().getId() != invoice.getCurrency().getId()) {
            throw new SessionInternalError(
                "An invoice with different "
                    + "currency is not supported. "
                    + "Currency = "
                    + holder.getCurrency().getId()
                    + "invoice = "
                    + invoice.getId());
          }
          // update the amount of the new invoice that is due to
          // previously unpaid overdue invoices

          // carry the remaining balance, plus the previously carried balance to the new invoice
          BigDecimal balance =
              (invoice.getBalance() == null) ? BigDecimal.ZERO : invoice.getBalance();
          BigDecimal carried = balance.add(holder.getCarriedBalance());
          holder.setCarriedBalance(carried);
        }

        LOG.debug("invoice " + invoice.getId() + " result " + isProcessable);

      } catch (PluggableTaskException e) {
        LOG.fatal("Problems handling task invoice filter.", e);
        throw new SessionInternalError("Problems handling task invoice filter.");
      } catch (TaskException e) {
        LOG.fatal("Problems excecuting task invoice filter.", e);
        throw new SessionInternalError("Problems executing task invoice filter.");
      }
    }

    if (newInvoices.size() == 0) {
      // no orders or invoices for this invoice
      LOG.debug("No applicable orders or invoices. No invoice generated (skipping invoices).");
      return null;
    }

    try {
      retValue = new InvoiceDTO[newInvoices.size()];
      int index = 0;
      for (NewInvoiceDTO invoice : newInvoices.values()) {
        LOG.debug(
            "Processing invoice "
                + invoice.getId()
                + " "
                + invoice.getBalance()
                + " "
                + invoice.getTotal());
        /*
         * Apply invoice composition tasks to the new invoices object
         */
        composeInvoice(entityId, user.getUserId(), invoice);

        LOG.debug(
            "  after composeInvoice "
                + invoice.getId()
                + " "
                + invoice.getBalance()
                + " "
                + invoice.getTotal());
        if (!isReview) {
          // process events after orders added to invoice
          processOrderAddedOnInvoiceEvents(invoice, entityId);
          LOG.debug("processing old invoices");
          for (InvoiceDTO oldInvoice : invoice.getInvoices()) {
            // since this invoice is being delegated, mark it as being carried forward
            // so that it is not re-processed later. do not clear the old balance!
            LOG.debug(
                "  setting status unpaid and carried on "
                    + oldInvoice.getId()
                    + " "
                    + oldInvoice.getBalance()
                    + " "
                    + oldInvoice.getTotal());
            oldInvoice.setInvoiceStatus(
                new InvoiceStatusDAS().find(Constants.INVOICE_STATUS_UNPAID_AND_CARRIED));
          }
        }

        /*
         * apply this object to the DB, generating the actual rows
         */
        // only if the invoice generated actually has some lines in it
        if (invoice.areLinesGeneratedEmpty()) {
          LOG.warn(
              "User "
                  + user.getUserId()
                  + " had orders or invoices but"
                  + " the invoice composition task didn't generate any lines.");
          continue;
        }

        // If this is a web services API call, the billing
        // process id is 0. Don't link to the billing process
        // object for API calls.
        retValue[index] =
            generateDBInvoice(
                user.getUserId(),
                invoice,
                (process.getId() != 0 ? process : null),
                Constants.ORDER_PROCESS_ORIGIN_PROCESS);

        // try to get this new invioce paid by previously unlinked
        // payments
        if (paymentApplication && !isReview) {
          PaymentBL pBL = new PaymentBL();
          pBL.automaticPaymentApplication(retValue[index]);
        }

        index++;
      }
    } catch (PluggableTaskException e1) {
      LOG.error("Error handling pluggable tasks when composing an invoice");
      throw new SessionInternalError(e1);
    } catch (TaskException e1) {
      LOG.error("Task exception when composing an invoice");
      throw new SessionInternalError(e1);
    } catch (Exception e1) {
      LOG.error("Error, probably linking payments", e1);
      throw new SessionInternalError(e1);
    }

    InvoicesGeneratedEvent generatedEvent = new InvoicesGeneratedEvent(entityId, process.getId());
    generatedEvent.addInvoices(retValue);
    EventManager.process(generatedEvent);

    return retValue;
  }
Example #7
0
  /**
   * Generates one single invoice for one single purchase order. This is meant to be called outside
   * the billing process.
   *
   * @param orderId
   * @return
   * @throws PluggableTaskException
   * @throws SessionInternalError
   */
  public InvoiceDTO generateInvoice(Integer orderId, Integer invoiceId)
      throws PluggableTaskException, SessionInternalError, SQLException {
    InvoiceDTO retValue = null;
    // find the order
    OrderBL order = new OrderBL(orderId);
    // define some data
    Integer entityId = order.getEntity().getUser().getEntity().getId();
    ConfigurationBL config = new ConfigurationBL(entityId);
    int maxPeriods = config.getEntity().getMaximumPeriods();
    boolean paymentApplication = config.getEntity().getAutoPaymentApplication() == 1;
    // The user could be the parent of a sub-account
    Integer userId = findUserId(order.getEntity());
    Date processDate = Calendar.getInstance().getTime();
    processDate = Util.truncateDate(processDate);
    // create the my invoice
    NewInvoiceDTO newInvoice = new NewInvoiceDTO();
    newInvoice.setDate(processDate);
    newInvoice.setIsReview(new Integer(0));
    // find the due date that applies
    TimePeriod period = order.getDueDate();
    newInvoice.setDueDatePeriod(period);
    // this is an isolated invoice that doesn't care about previous
    // overdue invoices
    newInvoice.setCarriedBalance(BigDecimal.ZERO);
    newInvoice.setInvoiceStatus(new InvoiceStatusDAS().find(Constants.INVOICE_STATUS_UNPAID));

    try {
      // put the order in the invoice using all the pluggable taks stuff
      addOrderToInvoice(entityId, order.getEntity(), newInvoice, processDate, maxPeriods);

      // this means that the user is trying to generate an invoice from
      // an order that the configurated tasks have rejected. Therefore
      // either this is the case an generating this invoice doesn't make
      // sense, or some business rules in the tasks have to be changed
      // (probably with a personalized task for this entity)
      if (newInvoice.getOrders().size() == 0) {
        return null;
      }

      // process events before orders added to invoice
      processOrderToInvoiceEvents(newInvoice, entityId);

      // generate the invoice lines
      composeInvoice(entityId, userId, newInvoice);

      // process events after orders added to invoice
      processOrderAddedOnInvoiceEvents(newInvoice, entityId);

      // put the resulting invoice in the database
      if (invoiceId == null) {
        // it is a new invoice from a singe order
        retValue =
            generateDBInvoice(userId, newInvoice, null, Constants.ORDER_PROCESS_ORIGIN_MANUAL);
        // try to get this new invioce paid by previously unlinked
        // payments
        if (paymentApplication) {
          PaymentBL pBL = new PaymentBL();
          pBL.automaticPaymentApplication(retValue);
        }
      } else {
        // it is an order going into an existing invoice
        InvoiceBL invoice = new InvoiceBL(invoiceId);
        boolean isUnpaid = invoice.getEntity().getToProcess() == 1;
        invoice.update(newInvoice);
        retValue = invoice.getEntity();
        createOrderProcess(newInvoice, retValue, null, Constants.ORDER_PROCESS_ORIGIN_MANUAL);
        eLogger.info(
            entityId,
            userId,
            invoiceId,
            EventLogger.MODULE_INVOICE_MAINTENANCE,
            EventLogger.INVOICE_ORDER_APPLIED,
            Constants.TABLE_INVOICE);
        // if the invoice is now not payable, take the user
        // out of ageing
        if (isUnpaid && retValue.getToProcess() == 0) {
          AgeingBL ageing = new AgeingBL();
          ageing.out(retValue.getBaseUser(), null);
        }
      }
    } catch (TaskException e) {
      // this means that the user is trying to generate an invoice from
      // an order that the configurated tasks have rejected. Therefore
      // either this is the case an generating this invoice doesn't make
      // sense, or some business rules in the tasks have to be changed
      // (probably with a personalized task for this entity)
      LOG.warn("Exception in generate invoice ", e);
    }

    if (retValue != null) {
      InvoicesGeneratedEvent generatedEvent = new InvoicesGeneratedEvent(entityId, null);
      generatedEvent.getInvoiceIds().add(retValue.getId());
      EventManager.process(generatedEvent);
    }

    return retValue;
  }
 public void updateProvisioningStatus(Integer orderLineId, Integer provisioningStatus) {
   OrderLineDTO orderLine = new OrderLineDAS().find(orderLineId);
   OrderBL orderBL = new OrderBL(orderLine.getPurchaseOrder());
   orderBL.setProvisioningStatus(orderLineId, provisioningStatus);
 }
Example #9
0
  protected void processRules(OrderDTO newOrder) throws TaskException {
    // now we have the line with good defaults, the order and the item
    // These have to be visible to the rules
    KnowledgeBase knowledgeBase;
    try {
      knowledgeBase = readKnowledgeBase();
    } catch (Exception e) {
      throw new TaskException(e);
    }
    session = knowledgeBase.newStatefulKnowledgeSession();
    List<Object> rulesMemoryContext = new ArrayList<Object>();
    rulesMemoryContext.add(helperOrder);

    // add OrderDTO to rules memory context
    newOrder.setCurrency(new CurrencyDAS().find(newOrder.getCurrency().getId()));
    if (newOrder.getCreateDate() == null) {
      newOrder.setCreateDate(new Date());
    }
    rulesMemoryContext.add(newOrder);

    for (OrderLineDTO line : newOrder.getLines()) {
      if (line.getItem() != null) {
        ItemBL item = new ItemBL(line.getItemId());
        rulesMemoryContext.add(
            item.getDTO(
                helperOrder.getLanguage(),
                helperOrder.getUserId(),
                helperOrder.getEntityId(),
                helperOrder.getCurrencyId()));
      }
      rulesMemoryContext.add(line);
    }

    if (newOrder.getPricingFields() != null && newOrder.getPricingFields().size() > 0) {
      for (PricingField pf : newOrder.getPricingFields()) {
        rulesMemoryContext.add(pf);
      }
    }
    try {
      Integer userId = newOrder.getBaseUserByUserId().getId();
      UserDTOEx user = DTOFactory.getUserDTOEx(userId);
      rulesMemoryContext.add(user);
      ContactBL contact = new ContactBL();
      contact.set(userId);
      ContactDTOEx contactDTO = contact.getDTO();
      rulesMemoryContext.add(contactDTO);

      // Add the subscriptions
      OrderBL order = new OrderBL();
      for (OrderDTO myOrder : order.getActiveRecurringByUser(userId)) {
        for (OrderLineDTO myLine : myOrder.getLines()) {
          rulesMemoryContext.add(new Subscription(myLine));
        }
      }
    } catch (Exception e) {
      throw new TaskException(e);
    }
    session.setGlobal("order", helperOrder);
    // then execute the rules

    executeStatefulRules(session, rulesMemoryContext);
  }
  /**
   * Sets the user status to the given "aged" status. If the user status is already set to the aged
   * status no changes will be made. This method also performs an HTTP callback and sends a
   * notification message when a status change is made.
   *
   * <p>If the user becomes suspended and can no longer log-in to the system, all of their active
   * orders will be automatically suspended.
   *
   * <p>If the user WAS suspended and becomes active (and can now log-in to the system), any
   * automatically suspended orders will be re-activated.
   *
   * @param user user
   * @param status status to set
   * @param today today's date
   * @param executorId executor id
   */
  public void setUserStatus(UserDTO user, UserStatusDTO status, Date today, Integer executorId) {
    // only set status if the new "aged" status is different from the users current status
    if (status.getId() == user.getStatus().getId()) {
      return;
    }

    LOG.debug("Setting user " + user.getId() + " status to '" + getStatusDescription(status) + "'");

    if (executorId != null) {
      // this came from the gui
      eLogger.audit(
          executorId,
          user.getId(),
          Constants.TABLE_BASE_USER,
          user.getId(),
          EventLogger.MODULE_USER_MAINTENANCE,
          EventLogger.STATUS_CHANGE,
          user.getStatus().getId(),
          null,
          null);
    } else {
      // this is from a process, no executor involved
      eLogger.auditBySystem(
          user.getCompany().getId(),
          user.getId(),
          Constants.TABLE_BASE_USER,
          user.getId(),
          EventLogger.MODULE_USER_MAINTENANCE,
          EventLogger.STATUS_CHANGE,
          user.getStatus().getId(),
          null,
          null);
    }

    // make the change
    boolean couldLogin = user.getStatus().getCanLogin() == 1;
    UserStatusDTO oldStatus = user.getStatus();

    user.setUserStatus(status);
    user.setLastStatusChange(today);

    // status changed to deleted, remove user
    if (status.getId() == UserDTOEx.STATUS_DELETED) {
      LOG.debug("Deleting user " + user.getId());
      new UserBL(user.getId()).delete(executorId);
      return;
    }

    // status changed from active to suspended
    // suspend customer orders
    if (couldLogin && status.getCanLogin() == 0) {
      LOG.debug("User " + user.getId() + " cannot log-in to the system. Suspending active orders.");

      OrderBL orderBL = new OrderBL();
      ScrollableResults orders =
          new OrderDAS().findByUser_Status(user.getId(), Constants.ORDER_STATUS_ACTIVE);

      while (orders.next()) {
        OrderDTO order = (OrderDTO) orders.get()[0];
        orderBL.set(order);
        orderBL.setStatus(executorId, Constants.ORDER_STATUS_SUSPENDED_AGEING);
      }

      orders.close();
    }

    // status changed from suspended to active
    // re-active suspended customer orders
    if (!couldLogin && status.getCanLogin() == 1) {
      LOG.debug(
          "User "
              + user.getId()
              + " can now log-in to the system. Activating previously suspended orders.");

      OrderBL orderBL = new OrderBL();
      ScrollableResults orders =
          new OrderDAS().findByUser_Status(user.getId(), Constants.ORDER_STATUS_SUSPENDED_AGEING);

      while (orders.next()) {
        OrderDTO order = (OrderDTO) orders.get()[0];
        orderBL.set(order);
        orderBL.setStatus(executorId, Constants.ORDER_STATUS_ACTIVE);
      }

      orders.close();
    }

    // perform callbacks and notifications
    performAgeingCallback(user, oldStatus, status);
    sendAgeingNotification(user, oldStatus, status);

    // emit NewUserStatusEvent
    NewUserStatusEvent event =
        new NewUserStatusEvent(
            user.getCompany().getId(), user.getId(), oldStatus.getId(), status.getId());
    EventManager.process(event);
  }