star-cloud/app/Services/Transaction/TransactionService.php
sky121113 40aec884b0 [REFACTOR] 溫度回報邏輯優化與 MQTT 規格標準化
1. 優化 ProcessHeartbeat 溫度處理邏輯,改為「變動即記錄」並標準化為整數型態。
2. 在 Machine Model 中新增 temperature 欄位的 integer cast。
3. 更新 MQTT 與 API 技術規格技能文件 (SKILL.md),同步最新的溫度記錄規則。
4. 更新 config/api-docs.php,明確標註心跳上報之溫度規格與日誌規則。
5. 移除 routes/api.php 中已廢棄之 B600 與機台日誌 REST API 路由。
6. 清理 docs 目錄,將初期計畫文件遷移至 docs/plan/。
2026-04-22 17:02:24 +08:00

122 lines
4.4 KiB
PHP

<?php
namespace App\Services\Transaction;
use App\Models\Transaction\Order;
use App\Models\Transaction\OrderItem;
use App\Models\Transaction\Invoice;
use App\Models\Transaction\DispenseRecord;
use Illuminate\Support\Facades\DB;
use App\Models\Machine\Machine;
class TransactionService
{
/**
* Process a new transaction (B600).
*/
public function processTransaction(array $data): Order
{
return DB::transaction(function () use ($data) {
$machine = Machine::where('serial_no', $data['serial_no'])->firstOrFail();
// Create Order
$order = Order::create([
'company_id' => $machine->company_id,
'flow_id' => $data['flow_id'] ?? null,
'order_no' => $data['order_no'] ?? $this->generateOrderNo(),
'machine_id' => $machine->id,
'member_id' => $data['member_id'] ?? null,
'total_amount' => $data['total_amount'],
'discount_amount' => $data['discount_amount'] ?? 0,
'pay_amount' => $data['pay_amount'],
'payment_type' => $data['payment_type'] ?? 0,
'payment_status' => $data['payment_status'] ?? 1,
'payment_at' => now(),
'status' => 'completed',
'metadata' => $data['metadata'] ?? null,
]);
// Create Order Items
if (!empty($data['items'])) {
foreach ($data['items'] as $item) {
$order->items()->create([
'product_id' => $item['product_id'],
'product_name' => $item['product_name'] ?? 'Unknown',
'barcode' => $item['barcode'] ?? null,
'price' => $item['price'],
'quantity' => $item['quantity'],
'subtotal' => $item['price'] * $item['quantity'],
]);
}
}
return $order;
});
}
/**
* Generate a unique order number.
*/
protected function generateOrderNo(): string
{
return 'ORD-' . now()->format('YmdHis') . '-' . strtoupper(bin2hex(random_bytes(3)));
}
/**
* Record Invoice (B601).
*/
public function recordInvoice(array $data): Invoice
{
return DB::transaction(function () use ($data) {
$machine = Machine::where('serial_no', $data['serial_no'])->firstOrFail();
$order = null;
if (!empty($data['flow_id'])) {
$order = Order::where('flow_id', $data['flow_id'])->first();
}
return Invoice::create([
'company_id' => $machine->company_id,
'order_id' => $order?->id ?? ($data['order_id'] ?? null),
'machine_id' => $machine->id,
'flow_id' => $data['flow_id'] ?? null,
'invoice_no' => $data['invoice_no'] ?? null,
'amount' => $data['amount'] ?? 0,
'carrier_id' => $data['carrier_id'] ?? null,
'invoice_date' => $data['invoice_date'] ?? null,
'random_number' => $data['random_no'] ?? null,
'love_code' => $data['love_code'] ?? null,
'metadata' => $data['metadata'] ?? null,
]);
});
}
/**
* Record dispense result (B602).
*/
public function recordDispense(array $data): DispenseRecord
{
return DB::transaction(function () use ($data) {
$machine = Machine::where('serial_no', $data['serial_no'])->firstOrFail();
$order = null;
if (!empty($data['flow_id'])) {
$order = Order::where('flow_id', $data['flow_id'])->first();
}
return DispenseRecord::create([
'company_id' => $machine->company_id,
'order_id' => $order?->id ?? ($data['order_id'] ?? null),
'flow_id' => $data['flow_id'] ?? null,
'machine_id' => $machine->id,
'slot_no' => $data['slot_no'] ?? 'unknown',
'product_id' => $data['product_id'] ?? null,
'amount' => $data['amount'] ?? 0,
'remaining_stock' => $data['remaining_stock'] ?? null,
'dispense_status' => $data['dispense_status'] ?? 0,
'machine_time' => $data['machine_time'] ?? now(),
]);
});
}
}