Refactor invoice comparison logic and deprecate temporary route
- Enhance `/collected-invoices/economic/compare` with improved HTTP status determination and response structure. - Add handling for `draft_total` and `booked_total` comparisons against internal totals. - Deprecate `/tmp-customer-list-overcharged` route with error response. - Update OpenAPI documentation for `compareCollectedInvoiceEconomic` endpoint. - Introduce `CollectedInvoiceEconomicCompareResponse` schema for consistent API responses. - Comment out unused return data and debug code for clarity.
This commit is contained in:
@@ -3140,6 +3140,41 @@ paths:
|
||||
'200':
|
||||
description: Ready invoices retrieved successfully
|
||||
|
||||
/collected-invoices/economic/compare:
|
||||
get:
|
||||
tags:
|
||||
- Invoices
|
||||
summary: Compare collected invoice totals with E-conomic
|
||||
description: |
|
||||
Compares a collected invoice in the system with its corresponding invoice in E-conomic.
|
||||
Returns totals from both sources, their difference, and any warnings detected during comparison.
|
||||
operationId: compareCollectedInvoiceEconomic
|
||||
parameters:
|
||||
- name: collected_invoice_id
|
||||
in: query
|
||||
required: true
|
||||
description: The internal collected invoice ID to compare
|
||||
schema:
|
||||
type: integer
|
||||
minimum: 1
|
||||
responses:
|
||||
'200':
|
||||
description: Comparison completed successfully
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/CollectedInvoiceEconomicCompareResponse'
|
||||
'400':
|
||||
$ref: '#/components/responses/BadRequest'
|
||||
'401':
|
||||
$ref: '#/components/responses/Unauthorized'
|
||||
'403':
|
||||
$ref: '#/components/responses/Forbidden'
|
||||
'404':
|
||||
$ref: '#/components/responses/NotFound'
|
||||
'500':
|
||||
$ref: '#/components/responses/InternalServerError'
|
||||
|
||||
/superuser/invoicing/period:
|
||||
get:
|
||||
tags:
|
||||
@@ -5516,6 +5551,7 @@ components:
|
||||
cashier_id:
|
||||
type: integer
|
||||
description: Cashier user ID
|
||||
|
||||
cashier_name:
|
||||
type: string
|
||||
description: Cashier name
|
||||
@@ -5544,6 +5580,65 @@ components:
|
||||
type: string
|
||||
format: date-time
|
||||
|
||||
CollectedInvoiceEconomicCompareResponse:
|
||||
type: object
|
||||
description: Result of comparing a collected invoice with its E-conomic counterpart
|
||||
properties:
|
||||
collected_invoice_id:
|
||||
type: integer
|
||||
description: The internal collected invoice ID
|
||||
example: 123
|
||||
draft_id:
|
||||
type: integer
|
||||
nullable: true
|
||||
description: E-conomic draft invoice ID, if present
|
||||
example: 456
|
||||
booked_id:
|
||||
type: integer
|
||||
nullable: true
|
||||
description: E-conomic booked invoice ID, if present
|
||||
example: 28368
|
||||
warnings:
|
||||
type: array
|
||||
description: List of warnings detected during comparison
|
||||
items:
|
||||
type: string
|
||||
example:
|
||||
- "Total amount mismatch for draft invoice ID 456: E-Conomic total is 867.5, internal total is 694"
|
||||
draft_total:
|
||||
type: number
|
||||
format: float
|
||||
nullable: true
|
||||
description: Total amount from the E-conomic draft (gross)
|
||||
example: 867.5
|
||||
booked_total:
|
||||
type: number
|
||||
format: float
|
||||
nullable: true
|
||||
description: Total amount from the E-conomic booked invoice (gross minus VAT if applicable)
|
||||
example: 694
|
||||
difference:
|
||||
type: number
|
||||
format: float
|
||||
nullable: true
|
||||
description: draft_total minus booked_total when both are available
|
||||
example: 0
|
||||
internal_total:
|
||||
type: number
|
||||
format: float
|
||||
description: Internal total amount for the collected invoice
|
||||
example: 694
|
||||
order_ids:
|
||||
type: array
|
||||
description: List of order IDs included in the collected invoice
|
||||
items:
|
||||
type: integer
|
||||
example: [38679, 39210]
|
||||
required:
|
||||
- collected_invoice_id
|
||||
- internal_total
|
||||
- order_ids
|
||||
|
||||
SelfServeLaneStatus:
|
||||
type: object
|
||||
properties:
|
||||
|
||||
@@ -7,7 +7,10 @@ use classes\redis;
|
||||
use dynamicimages\images\machine_1;
|
||||
use goals\classes\goals;
|
||||
use goals\classes\goals_criteria;
|
||||
use objects\collected_order_invoices_o;
|
||||
use objects\departments_o;
|
||||
use objects\order_items_o;
|
||||
use objects\orders_o;
|
||||
use objects\products_o;
|
||||
use objects\users_o;
|
||||
use traits\route_t;
|
||||
@@ -52,15 +55,92 @@ class exampleRoute
|
||||
$response->success(['message' => 'Hello World!']);
|
||||
});
|
||||
|
||||
$this->get('/tmp-customer-list-overcharged', function () {
|
||||
global $response;
|
||||
$response->error(['message' => 'This route is deprecated.']);
|
||||
/**
|
||||
* Steps:
|
||||
* 1. Get a list of all collected order invoices in january
|
||||
* 2. Extract the customers, and make sure they haven't been charged more than once for product ID: 78.
|
||||
* 3. Get a list of the amount of times, at what price and for what order IDs they have been charged.
|
||||
* 4. If they have been charged more than once, add them to a list of overcharged customers.
|
||||
* 5. Return the list of overcharged customers.
|
||||
*/
|
||||
// Step 1: Get a list of all collected order invoices in january
|
||||
$invoices = [];
|
||||
$product = (new products_o())->select(78);
|
||||
$all_invoices = (new collected_order_invoices_o())->getObjectsWhereClause("closed_at BETWEEN '2026-01-31 00:00:00' AND '2026-02-01 23:59:59'");
|
||||
// Filter out empty invoices
|
||||
foreach ($all_invoices as $invoice) {
|
||||
if ($invoice->isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
$invoices[] = $invoice;
|
||||
}
|
||||
// Get all orders related to the invoices
|
||||
$overcharged_customers = [];
|
||||
$order_ids = (new orders_o())->getFieldsWhereIn([
|
||||
'deleted_at' => null,
|
||||
'invoice_collection_id' => array_map(function ($invoice) {
|
||||
return $invoice->id;
|
||||
}, $invoices)],
|
||||
['id', 'customer_id']);
|
||||
$order_id_to_customer_id = array_column($order_ids, 'customer_id', 'id');
|
||||
$order_ids = array_map(function ($order) {
|
||||
return (int)$order['id'];
|
||||
}, $order_ids);
|
||||
// Get all the products in the orders
|
||||
$order_items = (new order_items_o())->getFieldsWhereIn(['order_id' => $order_ids, 'product_id' => [$product->id], 'deleted_at' => null], ['price', 'quantity', 'order_id', 'id']);
|
||||
// Define the customers => items map
|
||||
$customer_items_map = [];
|
||||
foreach ($order_items as $order_item) {
|
||||
$customer_items_map[(string)$order_id_to_customer_id[(string)$order_item['order_id']]][] = $order_item;
|
||||
}
|
||||
// Ignore the first item for each customer (as that is correct)
|
||||
foreach ($customer_items_map as $customer_id => $items) {
|
||||
array_shift($customer_items_map[$customer_id]);
|
||||
}
|
||||
// Create a total per customer number of items and price map
|
||||
foreach ($customer_items_map as $customer_id => $items) {
|
||||
$total_quantity = 0;
|
||||
$total_price = 0.0;
|
||||
foreach ($items as $item) {
|
||||
$total_quantity += (int)$item['quantity'];
|
||||
$total_price += (float)$item['price'] * (int)$item['quantity'];
|
||||
}
|
||||
// If the total quantity is more than 1, add to overcharged customers
|
||||
if ($total_quantity > 1) {
|
||||
$overcharged_customers[$customer_id] = [
|
||||
'total_quantity' => $total_quantity,
|
||||
'total_price' => $total_price,
|
||||
'items' => $items,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
// Format message
|
||||
foreach ($overcharged_customers as $customer_id => $data) {
|
||||
$customer = (new users_o())->getUserByCustomerNumber((int)$customer_id);
|
||||
$message = "Customer number: {$customer->customer_number->value()} - x{$data['total_quantity']} items for a total of {$data['total_price']} DKK\n";
|
||||
//$message .= "Items:\n";
|
||||
foreach ($data['items'] as $item) {
|
||||
//$message .= "- Order Item ID: {$item['id']}, Order ID: {$item['order_id']}, Price: {$item['price']}, Quantity: {$item['quantity']}\n";
|
||||
}
|
||||
echo $message . "\n";
|
||||
}
|
||||
|
||||
$response->success(['message' => 'Customer list overcharged', 'inv_count' => count($invoices), 'ord_count' => count($order_ids), 'order_ids' => $order_ids, 'order_items' => count($order_items), 'customer_items_map' => $customer_items_map, 'overcharged_customers' => $overcharged_customers]);
|
||||
});
|
||||
|
||||
$this->get('/debug', function () {
|
||||
global $response;
|
||||
//$response->success(['message' => 'Debugging route!']);
|
||||
$response->success(['message' => 'Debugging route!']);
|
||||
$machine_1 = new machine_1();
|
||||
//$machine_1->debugAssets();
|
||||
$machine_1->current_step = 0;
|
||||
$machine_1->only_generate_current_step = false;
|
||||
$machine_1->highlighted_buttons = [
|
||||
0, 2, 4, 7
|
||||
//0, 2, 4, 7
|
||||
];
|
||||
$machine_1->setup();
|
||||
$machine_1->servePicture();
|
||||
|
||||
@@ -199,6 +199,15 @@ class orderInvoicesRoute
|
||||
$warnings[] = 'Error comparing booked total: ' . $e->getMessage();
|
||||
}
|
||||
}
|
||||
// Determine HTTP status
|
||||
// 404 = Not found (in either draft or booked)
|
||||
// 200 = OK (Found one, and matches internal total)
|
||||
// 409 = Conflict (Both found but do not match)
|
||||
$httpStatus = match (true) {
|
||||
$draft_id === null && $booked_id === null => 404,
|
||||
($draft_total !== null && $internal_total === (float)$draft_total) || ($booked_total !== null && $internal_total === (float)$booked_total) => 200,
|
||||
default => 409,
|
||||
};
|
||||
// Return the comparison result
|
||||
$response->success([
|
||||
'collected_invoice_id' => $collected_invoice_id,
|
||||
@@ -207,10 +216,10 @@ class orderInvoicesRoute
|
||||
'warnings' => $warnings,
|
||||
'draft_total' => $draft_total,
|
||||
'booked_total' => $booked_total,
|
||||
'difference' => ($draft_total !== null && $booked_total !== null) ? (float)$draft_total - (float)$booked_total : null,
|
||||
'internal_total' => $invoice->getTotalAmount(),
|
||||
'order_ids' => $invoice->getOrderIds(),
|
||||
]);
|
||||
'difference' => ((float)($draft_total ?? $booked_total) - (float)$invoice->getTotalAmount()),
|
||||
'internal_total' => $internal_total,
|
||||
//'order_ids' => $invoice->getOrderIds(),
|
||||
], $httpStatus);
|
||||
|
||||
},
|
||||
[
|
||||
|
||||
Reference in New Issue
Block a user