get('/orders', function () { // Require the user to be logged in global $response; $this->requirePermission('list_orders'); // Get the user object $user = (new authentication())->get_user(); // Check if the request was successful if ($user) { // Log the incident (new logs_o())->add('orders', 'global', 1, $user->id, 'LIST_ORDERS', 'Successfully listed orders'); // Create economic_module_orders object $economic_module_orders = new economic_module_orders(); $orders = new orders_o(); // Return the list of departments $orders->setView('orders_with_invoice_collections'); $response->success( $orders->listObjectsWithPaginationIfSet( function ($order) { // Add the invoice status to the order $order['economic_invoice_module'] = (new economic_module_orders())->getByOrderId($order['id'])->asArray(); // Add the total amount to the order $order['total_net_amount'] = (new orders_o())->select($order['id'])->getNetAmount(); // Add the stripe status to the order $stripe_module_orders = (new stripe_module_orders_o())->select($order['id']); if ($stripe_module_orders->exists()) { $order['stripe_invoice_module'] = $stripe_module_orders->asArray(); } // If the invoice collection is set, add it to the order if (!empty($order['invoice_collection_id'])) { $order['invoice_collection'] = [ 'id' => $order['invoice_collection_id'], 'closed_at' => (new collected_order_invoices_o())->select($order['invoice_collection_id'])->closed_at->value(), 'booked_invoice_id' => (new collected_order_invoices_o())->select($order['invoice_collection_id'])->booked_invoice_id->value() ?? null, 'processor' => (int)(new collected_order_invoices_o())->select($order['invoice_collection_id'])->processor->value() ?? null, ]; } // Add the customer name to the order $order['customer_name'] = (new users_o())->getCustomerName($order['customer_id']); /** @var array $order */ return $order; }, $orders->forceRestrictFilters( [ // This makes sure that the user can only see orders from the departments they explicitly have access to 'department_id' => $user->getGroup()->getDepartments(), ] ) ) ); } else { // Log the incident (new logs_o())->add('orders', 'global', 1, 0, 'LIST_ORDERS', 'No user found, or invalid session'); // Return an error $response->error('Invalid session', 400); } }, [ 'list_orders' => 'List all orders' ] ); $this->post('/orders', function () { // Require the user to be logged in global $response; $this->requirePermission('add_order'); // Get the user object $user = (new authentication())->get_user(); // Check if the request was successful if ($user) { // Get the post data $data = json_decode(file_get_contents('php://input'), true); // Check if the required fields are set $data = $this->getData($data, $response); // Validate the department if (!(new departments_o())->getDepartmentById((int)$data['department_id'])) { $response->error('Department not found', 400); } // Make sure the customer number set is valid $targetUser = (new users_o())->getCustomerByIdOrCustomerNumber((int)$data['customer_id']); if (!$targetUser->exists()) { $response->error('Customer not found', 400); } // Check if the user requires a reference if ($targetUser->requiresReference() && empty($data['reference'])) { $response->error('Reference is required by the customer', 400); } // Get the registration number $reg_1 = $data['reg_1']; // Get the registration numbers (If they are set, they 2-3 are optional) $reg_2 = $data['reg_2'] ?? ''; $reg_3 = $data['reg_3'] ?? ''; // Create the order $order = (new orders_o())->add((int)$data['customer_id'], $user->id, $data['reference'], $data['notes'], (int)$data['department_id'], (string)$reg_1, (string)$reg_2, (string)$reg_3); // Log the incident (new logs_o())->add('orders', $data['department_id'], 1, $user->id, 'ADD_ORDER', 'Successfully added an order (ID: ' . $data['department_id'] . ')'); // Return a success message, containing the orders array $response->success($order->asArray()); } else { // Log the incident (new logs_o())->add('orders', 'global', 1, 0, 'ADD_ORDER', 'No user found, or invalid session'); // Return an error $response->error('Invalid session', 400); } }, [ 'add_order' => 'Add an order' ] ); $this->put('/orders', function () { // Require the user to be logged in global $response; $this->requirePermission('edit_order'); // Get the user object $user = (new authentication())->get_user(); // Check if the request was successful if ($user) { // Get the post data $data = json_decode(file_get_contents('php://input'), true); // Check if the required fields are set if (!isset($data['id'])) { $response->error('ID is required', 400); } // Get the current order $order = (new orders_o())->getOrderById((int)$data['id']); // Check if the order exists if (!$order->exists()) { $response->error('Order not found', 400); } // If the customer ID is set, validate it if (isset($data['customer_id'])) { if (!(new users_o())->getCustomerByIdOrCustomerNumber((int)$data['customer_id'])->exists() || empty($data['customer_id'])) { $response->error('Customer not found or invalid', 400); } $order->customer_id->set((int)$data['customer_id']); } // If the reference is set, validate it if (isset($data['reference'])) { $order->reference->set($data['reference']); } // If the notes are set, validate them if (isset($data['notes'])) { $order->notes->set($data['notes']); } // If the registration number is set, validate it if (isset($data['reg_1'])) { $order->reg_1->set($data['reg_1']); } // If the department ID is set, validate it // Log the incident (new logs_o())->add('orders', $order->department_id->value(), 1, $user->id, 'EDIT_ORDER', 'Successfully updated an order (ID: ' . $data['id'] . ')'); // Return a success message $response->success(['message' => 'Order updated successfully']); } else { // Log the incident (new logs_o())->add('orders', 'global', 1, 0, 'EDIT_ORDER', 'No user found, or invalid session'); // Return an error $response->error('Invalid session', 400); } }, [ 'edit_order' => 'Edit an order' ] ); $this->delete('/orders', function () { // Require the user to be logged in global $response; $this->requirePermission('delete_order'); // Get the user object $user = (new authentication())->get_user(); // Check if the request was successful if ($user) { // Get the payload $id = $this->fromRequest('id'); // Check if the ID is set if (!$id) { $response->error('ID is required', 400); } // Get the current order $order = (new orders_o())->getOrderById((int)$id); // Check if the order exists if (!$order->exists()) { $response->error('Order not found', 400); } // Delete the order $order->delete(); // Log the incident (new logs_o())->add('orders', $order->department_id->value(), 1, $user->id, 'DELETE_ORDER', 'Successfully deleted an order (ID: ' . $id . ')'); // Return a success message $response->success(['message' => 'Order deleted successfully']); } else { // Log the incident (new logs_o())->add('orders', 'global', 1, 0, 'DELETE_ORDER', 'No user found, or invalid session'); // Return an error $response->error('Invalid session', 400); } }, [ 'delete_order' => 'Delete an order' ] ); $this->post('/orders/mark_as_completed', function () { // Require the user to be logged in global $response; $this->requirePermission('mark_order_as_completed'); // Get the user object $user = (new authentication())->get_user(); // Check if the request was successful if ($user) { // Get the post data $data = json_decode(file_get_contents('php://input'), true); // Check if the required fields are set if (!isset($data['id'])) { $response->error('ID is required', 400); } // Get the current order $order = (new orders_o())->getOrderById((int)$data['id']); // Check if the order exists if (!$order->exists()) { $response->error('Order not found', 400); } // Mark the order as completed $order->markAsCompleted(); // Log the incident (new logs_o())->add('orders', $order->department_id->value(), 1, $user->id, 'MARK_ORDER_AS_COMPLETED', 'Successfully marked an order as completed (ID: ' . $data['id'] . ')'); // Return a success message $response->success(['message' => 'Order marked as completed successfully']); } else { // Log the incident (new logs_o())->add('orders', 'global', 1, 0, 'MARK_ORDER_AS_COMPLETED', 'No user found, or invalid session'); // Return an error $response->error('Invalid session', 400); } }, [ 'mark_order_as_completed' => 'Mark an order as completed' ] ); $this->post('/orders/module/stripe/payment_intent', function () { // Require the user to be logged in global $response; $this->requirePermission('charge_order_stripe'); // Get the user object $user = (new authentication())->get_user(); // Check if the request was successful if ($user) { // Get the post data $data = json_decode(file_get_contents('php://input'), true); // Check if the required fields are set if (!isset($data['id'])) { $response->error('ID is required', 400); } // Get the current order $order = (new orders_o())->getOrderById((int)$data['id']); // Check if the order exists if (!$order->exists()) { $response->error('Order not found', 400); } // Get the department $department = (new departments_o())->selectId((int)$order->department_id->value()); // Check if the department is configured for Stripe payments if (!$department->isStripeConfigured()) { $response->error('Department is not configured for Stripe payments', 400); } // Check if the reader is set if (!isset($data['reader'])) { $response->error('Reader ID is required', 400); } // Get the tax percentage (if any) $tax_percentage = (isset($data['tax_percentage'])) ? (int)$data['tax_percentage'] : null; // Check if the tax percentage is valid if ($tax_percentage !== null && ($tax_percentage < 0 || $tax_percentage > 100)) { $response->error('Invalid tax percentage', 400); } function addTaxNetAmount($net_amount, $tax_percentage): float { // Check if the tax percentage is above 0 if (empty($tax_percentage) || $tax_percentage <= 0) { return $net_amount; } return $net_amount + ($net_amount * ($tax_percentage / 100)); } // Get the Stripe payment intent $stripe = new stripe(); $paymentIntent = $stripe->payment_intents->create( addTaxNetAmount( (float)$order->getNetAmount() * 100, $tax_percentage ?? 0 ), [ 'description' => 'Order ID: ' . $order->id, 'metadata' => [ 'order_id' => $order->id, 'customer_id' => $order->customer_id->value(), 'department_id' => $order->department_id->value(), 'tax_percentage' => $tax_percentage ?? 0, ], 'payment_method_types' => ['card_present'], 'capture_method' => 'manual', ] ); // Validate the payment intent try { $stripe->payment_intents->get($paymentIntent->id); } catch (\Stripe\Exception\InvalidRequestException $e) { $response->error('Payment intent not found', 400); } // Set the payment intent ID in the order $stripe_payment_intents = new stripe_payment_intents_o(); $stripe_payment_intents->add( (int)$order->id, $paymentIntent->id, $paymentIntent->client_secret, $paymentIntent->toJSON() ); // Send the payment intent to the reader $stripe->readers->sendPaymentIntent( $data['reader'], $paymentIntent->id, ); // Set the reader on the stripe payment intent $stripe_payment_intents->reader_id->set($data['reader']); // Log the incident (new logs_o())->add('orders', $order->department_id->value(), 1, $user->id, 'CHARGE_ORDER', 'Successfully charged an order (ID: ' . $data['id'] . ')'); $response->success([ 'payment_intent' => $paymentIntent->id, 'client_secret' => $paymentIntent->client_secret, ]); } else { // Log the incident (new logs_o())->add('orders', 'global', 1, 0, 'CHARGE_ORDER', 'No user found, or invalid session'); // Return an error $response->error('Invalid session', 400); } }, [ 'charge_order' => 'Charge an order' ] ); $this->get('/orders/module/stripe/payment_intent', function () { // Require the user to be logged in global $response; $this->requirePermission('get_payment_intent'); // Get the user object $user = (new authentication())->get_user(); // Check if the request was successful if ($user) { // Get the post data self::requireParameters([ 'id' ]); // Check if the required fields are set $id = self::getParameter('id'); if (!isset($id)) { $response->error('ID is required', 400); } // Get the current order $order = (new orders_o())->getOrderById((int)$id); // Check if the order exists if (!$order->exists()) { $response->error('Order not found', 400); } // Check if the order has a payment intent $stripe_payment_intents = new stripe_payment_intents_o(); if (!$stripe_payment_intents->doesOrderHavePaymentIntent((int)$order->id)) { $response->error('Order does not have a payment intent', 400); } $stripe_payment_intents->selectOrderPaymentIntent((int)$order->id); // Get the Stripe payment intent $stripe = new stripe(); try { $payment_intent = $stripe->payment_intents->get( $stripe_payment_intents->payment_intent_id->value() ); } catch (\Stripe\Exception\InvalidRequestException $e) { $response->error('Payment intent not found', 400); } $response->success( $payment_intent->toJSON() ); } else { // Log the incident (new logs_o())->add('orders', 'global', 1, 0, 'GET_PAYMENT_INTENT', 'No user found, or invalid session'); // Return an error $response->error('Invalid session', 400); } }, [ 'get_payment_intent' => 'Get a payment intent' ] ); $this->delete('/orders/module/stripe/payment_intent', function () { // Require the user to be logged in global $response; $this->requirePermission('delete_payment_intent'); // Get the user object $user = (new authentication())->get_user(); // Check if the request was successful if ($user) { // Get the data self::requireParameters([ 'id' ]); $id = self::fromRequest('id'); // Get the current order $order = (new orders_o())->getOrderById((int)$id); // Check if the order exists if (!$order->exists()) { $response->error('Order not found', 400); } // Check if the order has a payment intent $stripe_payment_intents = new stripe_payment_intents_o(); if (!$stripe_payment_intents->doesOrderHavePaymentIntent((int)$order->id)) { $response->error('Order does not have a payment intent', 400); } $stripe_payment_intents->selectOrderPaymentIntent((int)$order->id); try { $stripe_payment_intents->delete(); // Log the incident (new logs_o())->add('orders', $order->department_id->value(), 1, $user->id, 'DELETE_PAYMENT_INTENT', 'Successfully deleted a payment intent (ID: ' . $id . ')'); // Return a success message $response->success(['message' => 'Payment intent deleted successfully']); } catch (\Stripe\Exception\InvalidRequestException $e) { $response->error('Payment intent not found', 400); } } else { // Log the incident (new logs_o())->add('orders', 'global', 1, 0, 'DELETE_PAYMENT_INTENT', 'No user found, or invalid session'); // Return an error $response->error('Invalid session', 400); } }); } /** * @param mixed $data * @param response $response * @return mixed */ private function getData(mixed $data, response $response): mixed { if (!isset($data['customer_id'])) { $response->error('Customer ID is required', 400); } if ((int)$data['customer_id'] < 1 || !is_numeric((int)$data['customer_id'])) { $response->error('Customer ID is required', 400); } if (!isset($data['department_id'])) { $response->error('Department ID is required', 400); } if (!isset($data['reference'])) { $response->error('Reference is required', 400); } if (!isset($data['notes'])) { $response->error('Notes is required', 400); } if (!isset($data['reg_1'])) { $response->error('Registration number 1 is required', 400); } if (strlen($data['reg_1']) < 4) { $response->error('Registration number 1 must be at least 4 characters', 400); } // Optional fields are not checked here, as they are optional and can be empty return $data; } }