public function testHandler_process_subscription() { midcom::get('auth')->request_sudo('org.openpsa.sales'); $product = org_openpsa_products_product_dba::get_cached(self::$_product->id); $product->delivery = org_openpsa_products_product_dba::DELIVERY_SUBSCRIPTION; $product->update(); $deliverable_attributes = array('salesproject' => self::$_salesproject->id, 'product' => self::$_product->id, 'start' => time(), 'continuous' => true, 'unit' => 'q', 'orgOpenpsaObtype' => org_openpsa_products_product_dba::DELIVERY_SUBSCRIPTION); $deliverable = $this->create_object('org_openpsa_sales_salesproject_deliverable_dba', $deliverable_attributes); $deliverable->update(); $_SERVER['REQUEST_METHOD'] = 'POST'; $_POST = array('order' => true); $url = $this->run_relocate_handler('org.openpsa.sales', array('deliverable', 'process', $deliverable->guid)); $this->assertEquals($url, 'salesproject/' . self::$_salesproject->guid . '/'); $deliverable->refresh(); $this->assertEquals(org_openpsa_sales_salesproject_deliverable_dba::STATUS_ORDERED, $deliverable->state); $mc = new org_openpsa_relatedto_collector($deliverable->guid, 'midcom_services_at_entry_dba'); $mc->add_object_order('start', 'DESC'); $at_entries = $mc->get_related_objects(); $this->assertEquals(1, sizeof($at_entries)); $this->register_object($at_entries[0]); $_POST = array('run_cycle' => true, 'at_entry' => $at_entries[0]->guid); $url = $this->run_relocate_handler('org.openpsa.sales', array('deliverable', 'process', $deliverable->guid)); $this->assertEquals($url, 'salesproject/' . self::$_salesproject->guid . '/'); $deliverable->refresh(); $mc = new org_openpsa_relatedto_collector($deliverable->guid, 'midcom_services_at_entry_dba'); $mc->add_object_order('start', 'DESC'); $at_entries = $mc->get_related_objects(); $this->assertEquals(1, sizeof($at_entries)); $this->register_object($at_entries[0]); midcom::get('auth')->drop_sudo(); }
/** * * @param mixed $handler_id The ID of the handler. * @param array &$data The local request data. */ public function _show_generator($handler_id, array &$data) { midcom_show_style('sales_report-deliverable-start'); // Quick workaround to Bergies lazy determination of whether this is user's or everyone's report... if ($this->_request_data['query_data']['resource'] == 'user:'******'auth')->user->guid) { // My report $data['handler_id'] = 'deliverable_report'; } else { // Generic report $data['handler_id'] = 'sales_report'; } /*** Copied from sales/handler/deliverable/report.php ***/ midcom_show_style('sales_report-deliverable-header'); $invoices_node = midcom_helper_misc::find_node_by_component('org.openpsa.invoices'); $sums_per_person = array(); $sums_all = array('price' => 0, 'cost' => 0, 'profit' => 0); $odd = true; foreach ($data['invoices'] as $deliverable_guid => $invoices) { if (count($invoices) == 0) { // No invoices sent in this project, skip continue; } try { $deliverable = org_openpsa_sales_salesproject_deliverable_dba::get_cached($deliverable_guid); $product = org_openpsa_products_product_dba::get_cached($deliverable->product); $salesproject = org_openpsa_sales_salesproject_dba::get_cached($deliverable->salesproject); $customer = midcom_db_group::get_cached($salesproject->customer); } catch (midcom_error $e) { continue; } if (!array_key_exists($salesproject->owner, $sums_per_person)) { $sums_per_person[$salesproject->owner] = array('price' => 0, 'cost' => 0, 'profit' => 0); } // Calculate the price and cost from invoices $invoice_price = 0; $data['invoice_string'] = ''; $invoice_cycle_numbers = array(); foreach ($invoices as $invoice) { $invoice_price += $invoice->sum; $invoice_class = $invoice->get_status(); if ($invoices_node) { $invoice_label = "<a class=\"{$invoice_class}\" href=\"{$invoices_node[MIDCOM_NAV_FULLURL]}invoice/{$invoice->guid}/\">" . $invoice->get_label() . "</a>"; } else { $invoice_label = $invoice->get_label(); } if ($product->delivery == org_openpsa_products_product_dba::DELIVERY_SUBSCRIPTION) { $invoice_cycle_numbers[] = (int) $invoice->parameter('org.openpsa.sales', 'cycle_number'); } $data['invoice_string'] .= "<li class=\"{$invoice_class}\">{$invoice_label}</li>\n"; } if ($product->delivery == org_openpsa_products_product_dba::DELIVERY_SUBSCRIPTION) { // This is a subscription, it should be shown only if it is the first invoice if (!in_array(1, $invoice_cycle_numbers)) { continue; // This will skip to next deliverable } $scheduler = new org_openpsa_invoices_scheduler($deliverable); if ($deliverable->end == 0) { // Subscription doesn't have an end date, use specified amount of months for calculation $cycles = $scheduler->calculate_cycles($this->_config->get('subscription_profit_months')); $data['calculation_basis'] = sprintf($data['l10n']->get('%s cycles in %s months'), $cycles, $this->_config->get('subscription_profit_months')); } else { $cycles = $scheduler->calculate_cycles(); $data['calculation_basis'] = sprintf($data['l10n']->get('%s cycles, %s - %s'), $cycles, strftime('%x', $deliverable->start), strftime('%x', $deliverable->end)); } $price = $deliverable->price * $cycles; $cost = $deliverable->cost * $cycles; } else { // This is a single delivery, calculate cost as percentage as it may be invoiced in pieces if ($deliverable->price) { $cost_percentage = 100 / $deliverable->price * $invoice_price; $cost = $deliverable->cost / 100 * $cost_percentage; } else { $cost_percentage = 100; $cost = $deliverable->cost; } $price = $invoice_price; $data['calculation_basis'] = sprintf($data['l10n']->get('%s%% of %s'), round($cost_percentage), $deliverable->price); } // And now just count the profit $profit = $price - $cost; $data['customer'] = $customer; $data['salesproject'] = $salesproject; $data['deliverable'] = $deliverable; $data['price'] = $price; $sums_per_person[$salesproject->owner]['price'] += $price; $sums_all['price'] += $price; $data['cost'] = $cost; $sums_per_person[$salesproject->owner]['cost'] += $cost; $sums_all['cost'] += $cost; $data['profit'] = $profit; $sums_per_person[$salesproject->owner]['profit'] += $profit; $sums_all['profit'] += $profit; if ($odd) { $data['row_class'] = ''; $odd = false; } else { $data['row_class'] = ' class="even"'; $odd = true; } midcom_show_style('sales_report-deliverable-item'); } $data['sums_per_person'] = $sums_per_person; $data['sums_all'] = $sums_all; midcom_show_style('sales_report-deliverable-footer'); /*** /Copied from sales/handler/deliverable/report.php ***/ midcom_show_style('sales_report-deliverable-end'); }
<?php $view =& $data['view_deliverable']; $status = $data['deliverable']->get_status(); $costType = $view['costType']; $per_unit = $data['l10n']->get('per unit'); try { $product = org_openpsa_products_product_dba::get_cached($data['deliverable']->product); $unit_options = midcom_baseclasses_components_configuration::get('org.openpsa.products', 'config')->get('unit_options'); if (array_key_exists($product->unit, $unit_options)) { $unit = midcom::get('i18n')->get_string($unit_options[$product->unit], 'org.openpsa.products'); $per_unit = sprintf($data['l10n']->get('per %s'), $unit); } } catch (midcom_error $e) { $product = false; $unit = $data['l10n']->get('unit'); } ?> <div class="org_openpsa_sales_salesproject_deliverable &(status);"> <div class="sidebar"> <div class="contacts area"> <?php echo "<h2>" . $data['l10n']->get('customer') . "</h2>\n"; $customer = $data['salesproject']->get_customer(); echo "<dl>\n<dt>\n" . $customer->render_link() . "</dl>\n</dt>\n"; $contacts = $data['salesproject']->contacts; foreach ($contacts as $contact_id => $active) { $person_card = org_openpsa_widgets_contact::get($contact_id); $person_card->show(); } ?>
/** * Shows the loaded salesproject. * * @param mixed $handler_id The ID of the handler. * @param array &$data The local request data. */ public function _show_view($handler_id, array &$data) { // For AJAX handling it is the controller that renders everything $data['view_salesproject'] = $data['controller']->get_content_html(); midcom_show_style('show-salesproject'); if (count($data['products']) > 0) { asort($data['products']); // We have products defined in the system, add deliverable support midcom_show_style('show-salesproject-deliverables-header'); if (array_key_exists('deliverables_objects', $data)) { foreach ($data['deliverables_objects'] as $deliverable) { $data['deliverable'] = $this->_controllers[$deliverable->id]->get_content_html(); $data['deliverable_object'] =& $deliverable; $data['deliverable_toolbar'] = $this->_build_deliverable_toolbar($deliverable); try { $data['product'] = org_openpsa_products_product_dba::get_cached($deliverable->product); } catch (midcom_error $e) { $data['product'] = false; } if ($deliverable->orgOpenpsaObtype == org_openpsa_products_product_dba::DELIVERY_SUBSCRIPTION) { midcom_show_style('show-salesproject-deliverables-subscription'); } else { midcom_show_style('show-salesproject-deliverables-item'); } } } midcom_show_style('show-salesproject-deliverables-footer'); } midcom_show_style('show-salesproject-related'); }
function deliver($update_deliveries = true) { if ($this->state > org_openpsa_sales_salesproject_deliverable_dba::STATUS_DELIVERED) { return false; } $product = org_openpsa_products_product_dba::get_cached($this->product); if ($product->delivery == org_openpsa_products_product_dba::DELIVERY_SUBSCRIPTION) { // Subscriptions are ongoing, not one delivery return false; } // Check if we need to create task or ship goods if ($update_deliveries) { switch ($product->orgOpenpsaObtype) { case org_openpsa_products_product_dba::TYPE_SERVICE: // Change status of tasks connected to the deliverable $task_qb = org_openpsa_projects_task_dba::new_query_builder(); $task_qb->add_constraint('agreement', '=', $this->id); $task_qb->add_constraint('status', '<', org_openpsa_projects_task_status_dba::CLOSED); $tasks = $task_qb->execute(); foreach ($tasks as $task) { org_openpsa_projects_workflow::close($task, sprintf(midcom::get('i18n')->get_string('completed from deliverable %s', 'org.openpsa.sales'), $this->title)); } break; case org_openpsa_products_product_dba::TYPE_GOODS: // TODO: Warehouse management: mark product as shipped // TODO: Warehouse management: mark product as shipped default: break; } } $this->state = org_openpsa_sales_salesproject_deliverable_dba::STATUS_DELIVERED; $this->end = time(); if ($this->update()) { // Update sales project and mark as delivered (if no other deliverables are active) $salesproject = new org_openpsa_sales_salesproject_dba($this->salesproject); $salesproject->mark_delivered(); midcom::get('uimessages')->add(midcom::get('i18n')->get_string('org.openpsa.sales', 'org.openpsa.sales'), sprintf(midcom::get('i18n')->get_string('marked deliverable "%s" delivered', 'org.openpsa.sales'), $this->title), 'ok'); return true; } return false; }
/** * @todo Check if we already have an open task for this delivery? */ function create_task($start, $end, $title, $source_task = null) { $salesproject = org_openpsa_sales_salesproject_dba::get_cached($this->_deliverable->salesproject); $product = org_openpsa_products_product_dba::get_cached($this->_deliverable->product); // Check if we already have a project for the sales project $project = $salesproject->get_project(); // Create the task $task = new org_openpsa_projects_task_dba(); $task->agreement = $this->_deliverable->id; $task->customer = $salesproject->customer; $task->title = $title; $task->description = $this->_deliverable->description; $task->start = $start; $task->end = $end; $task->plannedHours = $this->_deliverable->plannedUnits; $task->manager = $salesproject->owner; if ($project) { $task->project = $project->id; $task->orgOpenpsaAccesstype = $project->orgOpenpsaAccesstype; $task->orgOpenpsaOwnerWg = $project->orgOpenpsaOwnerWg; } if (!empty($source_task)) { $task->priority = $source_task->priority; $task->manager = $source_task->manager; } // TODO: Figure out if we really want to keep this $task->hoursInvoiceableDefault = true; if ($task->create()) { $task->add_members('contacts', array_keys($salesproject->contacts)); if (!empty($source_task)) { $source_task->get_members(); $task->add_members('resources', array_keys($source_task->resources)); } org_openpsa_relatedto_plugin::create($task, 'org.openpsa.projects', $product, 'org.openpsa.products'); // Copy tags from deliverable so we can seek resources $tagger = new net_nemein_tag_handler(); $tagger->copy_tags($this->_deliverable, $task); midcom::get('uimessages')->add(midcom::get('i18n')->get_string('org.openpsa.sales', 'org.openpsa.sales'), sprintf(midcom::get('i18n')->get_string('created task "%s"', 'org.openpsa.sales'), $task->title), 'ok'); return $task; } else { throw new midcom_error("The task for this cycle could not be created. Last Midgard error was: " . midcom_connection::get_error_string()); } }