Exemple #1
0
 public function testCRUD()
 {
     midcom::get('auth')->request_sudo('org.openpsa.invoices');
     $item = new org_openpsa_invoices_invoice_item_dba();
     $item->invoice = self::$_invoice->id;
     $item->deliverable = self::$_deliverable->id;
     $item->pricePerUnit = 100;
     $item->units = 2.5;
     $stat = $item->create();
     $this->assertTrue($stat);
     $this->register_object($item);
     $parent = $item->get_parent();
     $this->assertEquals($parent->guid, self::$_invoice->guid);
     self::$_invoice->refresh();
     self::$_deliverable->refresh();
     $this->assertEquals(self::$_invoice->sum, 250);
     $this->assertEquals(self::$_deliverable->invoiced, 250);
     $this->assertEquals(self::$_deliverable->state, org_openpsa_sales_salesproject_deliverable_dba::STATUS_INVOICED);
     $item->units = 3.5;
     $stat = $item->update();
     $this->assertTrue($stat);
     self::$_invoice->refresh();
     self::$_deliverable->refresh();
     $this->assertEquals(self::$_invoice->sum, 350);
     $this->assertEquals(self::$_deliverable->invoiced, 350);
     $stat = $item->delete();
     $this->assertTrue($stat);
     self::$_invoice->refresh();
     self::$_deliverable->refresh();
     $this->assertEquals(self::$_invoice->sum, 0);
     $this->assertEquals(self::$_deliverable->invoiced, 0);
     midcom::get('auth')->drop_sudo();
 }
Exemple #2
0
 public function test_generate_invoice()
 {
     midcom::get('auth')->request_sudo('org.openpsa.invoices');
     $customer = $this->create_object('org_openpsa_contacts_group_dba');
     $salesproject = $this->create_object('org_openpsa_sales_salesproject_dba');
     $deliverable_attributes = array('salesproject' => $salesproject->id, 'price' => 100, 'state' => org_openpsa_sales_salesproject_deliverable_dba::STATUS_DELIVERED, 'invoiceByActualUnits' => false);
     $deliverable = $this->create_object('org_openpsa_sales_salesproject_deliverable_dba', $deliverable_attributes);
     $task_attributes = array('project' => $salesproject->id, 'agreement' => $deliverable->id, 'status' => org_openpsa_projects_task_status_dba::COMPLETED, 'invoiceableHours' => true);
     $task = $this->create_object('org_openpsa_projects_task_dba', $task_attributes);
     $_POST = array('org_openpsa_invoices_invoice' => true, 'org_openpsa_invoices_invoice_tasks' => array($task->id => true), 'org_openpsa_invoices_invoice_tasks_price' => array($task->id => 10), 'org_openpsa_invoices_invoice_tasks_units' => array($task->id => 10), 'org_openpsa_invoices_invoice_customer' => $customer->id);
     $url = $this->run_relocate_handler('org.openpsa.invoices', array('projects'));
     $qb = org_openpsa_invoices_invoice_item_dba::new_query_builder();
     $qb->add_constraint('task', '=', $task->id);
     $results = $qb->execute();
     $this->assertEquals(1, sizeof($results));
     $item = $results[0];
     $invoice = new org_openpsa_invoices_invoice_dba($item->invoice);
     $task->refresh();
     $this->assertEquals('invoice/edit/' . $invoice->guid . '/', $url);
     $this->assertEquals(100, $invoice->sum);
     $this->assertEquals($deliverable->id, $item->deliverable);
     $deliverable->refresh();
     $this->assertEquals(org_openpsa_sales_salesproject_deliverable_dba::STATUS_INVOICED, $deliverable->state);
     midcom::get('auth')->drop_sudo();
 }
Exemple #3
0
 private function _generate_invoice()
 {
     $invoice = new org_openpsa_invoices_invoice_dba();
     $invoice->customer = (int) $_POST['org_openpsa_invoices_invoice_customer'];
     $invoice->number = $invoice->generate_invoice_number();
     $invoice->owner = midcom_connection::get_user();
     $invoice->vat = $invoice->get_default('vat');
     $invoice->description = $invoice->get_default('remarks');
     if (!$invoice->create()) {
         midcom::get('uimessages')->add($this->_l10n->get('org.openpsa.invoices'), $this->_l10n->get('failed to create invoice, reason ') . midcom_connection::get_error_string(), 'error');
         return false;
     }
     // create invoice_items
     foreach ($_POST['org_openpsa_invoices_invoice_tasks'] as $task_id => $invoiceable) {
         if (!$invoiceable) {
             continue;
         }
         $task = $this->_tasks[$task_id];
         //instance the invoice_items
         $item = new org_openpsa_invoices_invoice_item_dba();
         $item->task = $task_id;
         try {
             $deliverable = org_openpsa_sales_salesproject_deliverable_dba::get_cached($task->agreement);
             $item->deliverable = $deliverable->id;
         } catch (midcom_error $e) {
             $e->log();
         }
         $item->invoice = $invoice->id;
         $item->description = $task->title;
         $item->pricePerUnit = (double) $_POST['org_openpsa_invoices_invoice_tasks_price'][$task_id];
         $item->units = (double) $_POST['org_openpsa_invoices_invoice_tasks_units'][$task_id];
         $item->create();
         // Connect invoice to the tasks involved
         org_openpsa_projects_workflow::mark_invoiced($task, $invoice);
     }
     // Generate "Send invoice" task
     $invoice_sender_guid = $this->_config->get('invoice_sender');
     if (!empty($invoice_sender_guid)) {
         $invoice->generate_invoicing_task($invoice_sender_guid);
     }
     midcom::get('uimessages')->add($this->_l10n->get('org.openpsa.invoices'), sprintf($this->_l10n->get('invoice %s created'), $invoice->get_label()), 'ok');
     midcom::get()->relocate("invoice/edit/{$invoice->guid}/");
     // This will exit
 }
Exemple #4
0
 private function _get_deliverable_invoices($id)
 {
     $mc = org_openpsa_invoices_invoice_item_dba::new_collector('deliverable', $id);
     $ids = $mc->get_values('invoice');
     if (sizeof($ids) < 1) {
         return array();
     }
     $qb = org_openpsa_invoices_invoice_dba::new_query_builder();
     $qb->add_constraint('id', 'IN', $ids);
     $qb->add_constraint('sent', '>=', $this->_request_data['start']);
     $qb->add_constraint('sent', '<=', $this->_request_data['end']);
     return $qb->execute();
 }
Exemple #5
0
 /**
  * @param mixed $handler_id The ID of the handler.
  * @param Array $args The argument list.
  * @param Array &$data The local request data.
  */
 public function _handler_itemposition($handler_id, array $args, array &$data)
 {
     midcom::get()->skip_page_style = true;
     $item = new org_openpsa_invoices_invoice_item_dba((int) $_POST['id']);
     $item->position = $_POST['position'];
     if (!$item->update()) {
         throw new midcom_error('Failed to update item: ' . midcom_connection::get_error_string());
     }
     return new midcom_response_json(array());
 }
Exemple #6
0
                if ($cycle_number) {
                    $description .= ' ' . $cycle_number;
                }
                foreach ($items as $item) {
                    if ($item->description == $description && $item->deliverable == 0) {
                        echo "Found invoice item for deliverable " . $deliverable->title . " by description\n";
                        flush();
                        $found = true;
                        break;
                    }
                }
            }
            if (!$found) {
                echo "Could not identify invoice item for deliverable " . $deliverable->title . " on invoice " . $invoice->get_label() . ", creating empty item\n";
                flush();
                $item = new org_openpsa_invoices_invoice_item_dba();
                $item->invoice = $invoice->id;
                $item->deliverable = $deliverable->id;
                $item->pricePerUnit = 0;
                $item->units = 1;
                $item->description = $deliverable->title . ' (auto-generated)';
                $item->create();
            }
        }
        $relatedto->delete();
    }
}
$qb_items = org_openpsa_invoices_invoice_item_dba::new_query_builder();
$qb_items->add_constraint('task', '>', 0);
$qb_items->add_constraint('deliverable', '=', 0);
$items = $qb_items->execute();
Exemple #7
0
 /**
  * Helper function that tries to locate unsent invoices for deliverables in the same salesproject
  *
  * Example use case: A support contract with multiple hourly rates (defined
  * as deliverables) for different types of work. Instead of sending the customer
  * one invoice per hourly rate per month, one composite invoice for all fees is generated
  */
 private function _probe_invoice($cycle_number)
 {
     $deliverable_mc = org_openpsa_sales_salesproject_deliverable_dba::new_collector('salesproject', $this->_deliverable->salesproject);
     $deliverable_mc->add_constraint('state', '>', org_openpsa_sales_salesproject_deliverable_dba::STATUS_DECLINED);
     $deliverable_mc->add_constraint('product.delivery', '=', org_openpsa_products_product_dba::DELIVERY_SUBSCRIPTION);
     $deliverables = $deliverable_mc->get_values('id');
     $item_mc = org_openpsa_invoices_invoice_item_dba::new_collector('metadata.deleted', false);
     $item_mc->add_constraint('deliverable.salesproject', '=', $this->_deliverable->salesproject);
     $item_mc->add_constraint('invoice.sent', '=', 0);
     $suspects = $item_mc->get_values('invoice');
     if (sizeof($suspects) > 0) {
         return new org_openpsa_invoices_invoice_dba(array_pop($suspects));
     }
     //Nothing found, create a new invoice
     return $this->_create_invoice($cycle_number);
 }
Exemple #8
0
 private function _find_tasks()
 {
     $qb = org_openpsa_projects_task_dba::new_query_builder();
     $qb->add_constraint('agreement', '=', $this->_deliverable->id);
     if ($this->_deliverable->invoiceByActualUnits) {
         $qb->add_constraint('invoiceableHours', '>', 0);
     } else {
         $item_mc = org_openpsa_invoices_invoice_item_dba::new_collector('deliverable', $this->_deliverable->id);
         $skip_ids = $item_mc->get_values('task');
         if (sizeof($skip_ids) > 0) {
             $qb->add_constraint('id', 'NOT IN', $skip_ids);
         }
     }
     return $qb->execute();
 }
Exemple #9
0
midcom::get('auth')->require_admin_user();
// Ensure this is not buffered
midcom::get('cache')->content->enable_live_mode();
while (@ob_end_flush()) {
    midcom::get()->disable_limits();
}
echo "<h1>Invalidating deliverable caches:</h1>\n";
$qb = org_openpsa_sales_salesproject_deliverable_dba::new_query_builder();
$qb->add_constraint('state', '>=', org_openpsa_sales_salesproject_deliverable_dba::STATUS_ORDERED);
$deliverables = $qb->execute();
echo "<pre>\n";
flush();
foreach ($deliverables as $deliverable) {
    $start = microtime(true);
    echo "Update caches for deliverable #{$deliverable->id} " . $deliverable->title . "\n";
    echo "units: {$deliverable->units} uninvoiceable: {$deliverable->uninvoiceableUnits} price: {$deliverable->price} cost: {$deliverable->cost} invoiced: {$deliverable->invoiced}\n";
    flush();
    $deliverable->calculate_price(false);
    org_openpsa_invoices_invoice_item_dba::update_deliverable($deliverable);
    $deliverable->update_units();
    $deliverable->update();
    $time_consumed = round(microtime(true) - $start, 2);
    echo "OK ({$time_consumed} secs), new units:\n";
    echo "units: {$deliverable->units} uninvoiceable: {$deliverable->uninvoiceableUnits} price: {$deliverable->price} cost: {$deliverable->cost} invoiced: {$deliverable->invoiced}\n";
    flush();
}
?>
</pre>
<p>All done</p>
Exemple #10
0
 /**
  * Helper function to get invoice_item for the passed task id, if there is no item
  * it will return a new created one
  */
 private function _probe_invoice_item_for_task($task_id)
 {
     //check if there is already an invoice_item for this task
     $qb_invoice_item = org_openpsa_invoices_invoice_item_dba::new_query_builder();
     $qb_invoice_item->add_constraint('invoice', '=', $this->id);
     $qb_invoice_item->add_constraint('task', '=', $task_id);
     $invoice_items = $qb_invoice_item->execute();
     if (count($invoice_items) == 1) {
         $invoice_item = $invoice_items[0];
     } else {
         if (count($invoice_items) > 1) {
             debug_add('More than one item found for task #' . $task_id . ', only returning the first', MIDCOM_LOG_INFO);
             $invoice_item = $invoice_items[0];
         } else {
             $invoice_item = new org_openpsa_invoices_invoice_item_dba();
             $invoice_item->task = $task_id;
             $invoice_item->invoice = $this->id;
             $invoice_item->create();
         }
     }
     return $invoice_item;
 }
Exemple #11
0
 private function _count_invoice_items($invoice_id)
 {
     $qb = org_openpsa_invoices_invoice_item_dba::new_query_builder();
     $qb->add_constraint('invoice', '=', $invoice_id);
     $items = $qb->execute();
     $this->register_objects($items);
     return count($items);
 }
Exemple #12
0
 /**
  * @depends testRun_cycle
  */
 public function testRun_cycle_multiple()
 {
     midcom::get('auth')->request_sudo('org.openpsa.invoices');
     $deliverable_attributes = array('salesproject' => $this->_salesproject->id, 'product' => $this->_product->id, 'description' => 'TEST DESCRIPTION 2', 'pricePerUnit' => 10, 'plannedUnits' => 15, 'units' => 10, 'invoiceByActualUnits' => true, 'state' => org_openpsa_sales_salesproject_deliverable_dba::STATUS_STARTED, 'start' => strtotime('2010-02-02 00:00:00'));
     $deliverable2 = $this->create_object('org_openpsa_sales_salesproject_deliverable_dba', $deliverable_attributes);
     $task_attributes = array('project' => $this->_project->id, 'agreement' => $deliverable2->id, 'title' => 'TEST TITLE 2', 'reportedHours' => 10);
     $task2 = $this->create_object('org_openpsa_projects_task_dba', $task_attributes);
     $this->_product->delivery = org_openpsa_products_product_dba::DELIVERY_SUBSCRIPTION;
     $this->_product->update();
     $this->_deliverable->start = strtotime('2010-02-02 00:00:00');
     $this->_deliverable->continuous = true;
     $this->_deliverable->invoiceByActualUnits = false;
     $this->_deliverable->pricePerUnit = 10;
     $this->_deliverable->plannedUnits = 10;
     $this->_deliverable->state = org_openpsa_sales_salesproject_deliverable_dba::STATUS_STARTED;
     $this->_deliverable->update();
     $scheduler = new org_openpsa_invoices_scheduler($this->_deliverable);
     $stat = $scheduler->run_cycle(1, true);
     $this->assertTrue($stat);
     $scheduler = new org_openpsa_invoices_scheduler($deliverable2);
     $stat = $scheduler->run_cycle(1, true);
     $this->assertTrue($stat);
     $qb = org_openpsa_invoices_invoice_item_dba::new_query_builder();
     $qb->add_constraint('deliverable', '=', $this->_deliverable->id);
     $results = $qb->execute();
     $this->assertEquals(1, sizeof($results));
     $item1 = $results[0];
     $this->register_object($item1);
     $qb = org_openpsa_invoices_invoice_item_dba::new_query_builder();
     $qb->add_constraint('deliverable', '=', $deliverable2->id);
     $results = $qb->execute();
     $this->assertEquals(1, sizeof($results));
     $item2 = $results[0];
     $this->register_object($item2);
     $this->assertEquals($item1->invoice, $item2->invoice);
     $this->assertEquals($this->_deliverable->id, $item1->deliverable);
     $this->assertEquals($deliverable2->id, $item2->deliverable);
     $invoice = new org_openpsa_invoices_invoice_dba($item2->invoice);
     $this->register_object($invoice);
     $this->assertEquals(200, $invoice->sum);
     $this->assertEquals(100, $deliverable2->invoiced);
     midcom::get('auth')->drop_sudo();
 }
Exemple #13
0
 /**
  * Helper that adds a customer/deliverable constraints to list QBs
  *
  * @param midcom_core_querybuilder &$qb th QB we're working with
  */
 private function _add_filters(&$qb)
 {
     if ($this->_customer) {
         if (is_a($this->_customer, 'org_openpsa_contacts_group_dba')) {
             $qb->add_constraint('customer', '=', $this->_customer->id);
         } else {
             $qb->add_constraint('customerContact', '=', $this->_customer->id);
         }
     }
     if ($this->_deliverable) {
         $mc = org_openpsa_invoices_invoice_item_dba::new_collector('deliverable', $this->_deliverable->id);
         $invoice_ids = $mc->get_values('invoice');
         if (!empty($invoice_ids)) {
             $qb->add_constraint('id', 'IN', $invoice_ids);
         } else {
             $qb->add_constraint('id', '=', 0);
         }
     }
 }