/** * Initiates a new subscription cycle and registers a midcom.services.at call for the next cycle. * * The subscription cycles rely on midcom.services.at. I'm not sure if it is wise to rely on it for such * a totally mission critical part of OpenPSA. Some safeguards might be wise to add. */ function run_cycle($cycle_number, $send_invoice = true) { if (time() < $this->_deliverable->start) { debug_add('Subscription hasn\'t started yet, register the start-up event to $start'); return $this->_create_at_entry($cycle_number, $this->_deliverable->start); } debug_add('Running cycle ' . $cycle_number . ' for deliverable "' . $this->_deliverable->title . '"'); $this_cycle_start = $this->get_cycle_start($cycle_number, time()); $next_cycle_start = $this->calculate_cycle_next($this_cycle_start); $product = org_openpsa_products_product_dba::get_cached($this->_deliverable->product); if ($this->_deliverable->state < org_openpsa_sales_salesproject_deliverable_dba::STATUS_STARTED) { $this->_deliverable->state = org_openpsa_sales_salesproject_deliverable_dba::STATUS_STARTED; $this->_deliverable->update(); } if ($send_invoice) { $calculator = new org_openpsa_invoices_calculator(); $this_cycle_amount = $calculator->process_deliverable($this->_deliverable, $cycle_number); } $tasks_completed = array(); $tasks_not_completed = array(); if ($product->orgOpenpsaObtype == org_openpsa_products_product_dba::TYPE_SERVICE) { // Close previous task(s) $last_task = null; $new_task = null; $task_qb = org_openpsa_projects_task_dba::new_query_builder(); $task_qb->add_constraint('agreement', '=', $this->_deliverable->id); $task_qb->add_constraint('status', '<', org_openpsa_projects_task_status_dba::CLOSED); $tasks = $task_qb->execute(); foreach ($tasks as $task) { $stat = org_openpsa_projects_workflow::complete($task, sprintf(midcom::get('i18n')->get_string('completed by subscription %s', 'org.openpsa.sales'), $cycle_number)); if ($stat) { $tasks_completed[] = $task; } else { $tasks_not_completed[] = $task; } $last_task = $task; } // Create task for the duration of this cycle $task_title = sprintf('%s %s', $this->_deliverable->title, $this->get_cycle_identifier($this_cycle_start)); $new_task = $this->create_task($this_cycle_start, $next_cycle_start - 1, $task_title, $last_task); } // TODO: Warehouse management: create new order if ($this->_deliverable->end < $next_cycle_start && $this->_deliverable->end != 0) { debug_add('Do not register next cycle, the contract ends before'); return true; } if ($this->_create_at_entry($cycle_number + 1, $next_cycle_start)) { if ($send_invoice) { $this->_notify_owner($calculator, $cycle_number, $next_cycle_start, $this_cycle_amount, $tasks_completed, $tasks_not_completed); } return true; } else { return false; } }
public static function update_deliverable(org_openpsa_sales_salesproject_deliverable_dba $deliverable) { $invoiced = self::get_sum(array('deliverable' => $deliverable->id)); if ($invoiced != $deliverable->invoiced) { $deliverable->invoiced = $invoiced; if ($deliverable->orgOpenpsaObtype == org_openpsa_products_product_dba::DELIVERY_SINGLE && $deliverable->state < org_openpsa_sales_salesproject_deliverable_dba::STATUS_INVOICED) { $deliverable->state = org_openpsa_sales_salesproject_deliverable_dba::STATUS_INVOICED; } $deliverable->update(); } }