diff --git a/src/main/kotlin/info/nukoneko/kidspos/receipt/ReceiptPrinter.kt b/src/main/kotlin/info/nukoneko/kidspos/receipt/ReceiptPrinter.kt index 1ba91b9..6a75f88 100644 --- a/src/main/kotlin/info/nukoneko/kidspos/receipt/ReceiptPrinter.kt +++ b/src/main/kotlin/info/nukoneko/kidspos/receipt/ReceiptPrinter.kt @@ -87,7 +87,10 @@ class ReceiptPrinter( @Throws(IOException::class) fun print() { - Socket(ipOrHost, port).use { socket -> + Socket().apply { + soTimeout = 5000 // 5秒でタイムアウト + connect(java.net.InetSocketAddress(ipOrHost, port), 5000) // 接続タイムアウト5秒 + }.use { socket -> socket.getOutputStream().use { it.write(command.build()) } diff --git a/src/main/kotlin/info/nukoneko/kidspos/server/controller/api/ItemApiController.kt b/src/main/kotlin/info/nukoneko/kidspos/server/controller/api/ItemApiController.kt index d42b6e0..198bec8 100644 --- a/src/main/kotlin/info/nukoneko/kidspos/server/controller/api/ItemApiController.kt +++ b/src/main/kotlin/info/nukoneko/kidspos/server/controller/api/ItemApiController.kt @@ -101,13 +101,13 @@ class ItemApiController { ], ) fun findByBarcode( - @Parameter(description = "Item barcode (4+ digits)", required = true, example = "1234567890") + @Parameter(description = "Item barcode (format: A01XXXXXXA)", required = true, example = "A01000001A") @PathVariable barcode: String, ): ResponseEntity { logger.info("Fetching item with barcode: {}", barcode) - // Validate barcode format - if (!barcode.matches(Regex("^[0-9]{4,}$"))) { + // Validate barcode format (A + 種別(2桁) + ID(6桁) + A) + if (!barcode.matches(Regex("^A(00|01|02)\\d{6}A$"))) { throw InvalidBarcodeException(barcode) } diff --git a/src/main/kotlin/info/nukoneko/kidspos/server/controller/api/SaleApiController.kt b/src/main/kotlin/info/nukoneko/kidspos/server/controller/api/SaleApiController.kt index a02dc14..6060ae8 100644 --- a/src/main/kotlin/info/nukoneko/kidspos/server/controller/api/SaleApiController.kt +++ b/src/main/kotlin/info/nukoneko/kidspos/server/controller/api/SaleApiController.kt @@ -11,8 +11,10 @@ import info.nukoneko.kidspos.server.service.mapper.SaleMapper import jakarta.validation.Valid import org.slf4j.LoggerFactory import org.springframework.http.ResponseEntity +import org.springframework.scheduling.annotation.Async import org.springframework.validation.annotation.Validated import org.springframework.web.bind.annotation.* +import java.util.concurrent.CompletableFuture /** * 販売APIコントローラー @@ -50,12 +52,18 @@ class SaleApiController( ) when (val result = saleProcessingService.processSaleWithValidation(saleBean, items)) { is SaleResult.Success -> { - // Print receipt - receiptService.printReceipt( - request.storeId, - items, - request.deposit, - ) + // Print receipt asynchronously (non-blocking) + CompletableFuture.runAsync { + try { + receiptService.printReceipt( + request.storeId, + items, + request.deposit, + ) + } catch (e: Exception) { + logger.error("Failed to print receipt asynchronously", e) + } + } val sale = result.sale val response = diff --git a/src/main/kotlin/info/nukoneko/kidspos/server/entity/SaleEntity.kt b/src/main/kotlin/info/nukoneko/kidspos/server/entity/SaleEntity.kt index 19cb4e7..f8e8bfb 100644 --- a/src/main/kotlin/info/nukoneko/kidspos/server/entity/SaleEntity.kt +++ b/src/main/kotlin/info/nukoneko/kidspos/server/entity/SaleEntity.kt @@ -14,6 +14,7 @@ import java.util.* * @property quantity 数量 * @property amount 売上げ金額 * @property deposit 預かり金 + * @property changeAmount お釣り * @property createdAt 作成日時 */ @Entity @@ -23,6 +24,7 @@ data class SaleEntity( val storeId: Int, // 店舗ID val quantity: Int, // 数量 val amount: Int, // 売り上げ - val deposit: Int, + val deposit: Int, // 預かり金 + val changeAmount: Int, // お釣り val createdAt: Date, ) diff --git a/src/main/kotlin/info/nukoneko/kidspos/server/service/SalePersistenceService.kt b/src/main/kotlin/info/nukoneko/kidspos/server/service/SalePersistenceService.kt index 96adf97..6075643 100644 --- a/src/main/kotlin/info/nukoneko/kidspos/server/service/SalePersistenceService.kt +++ b/src/main/kotlin/info/nukoneko/kidspos/server/service/SalePersistenceService.kt @@ -36,6 +36,7 @@ class SalePersistenceService( val saleId = idGenerationService.generateNextId(saleRepository) val totalAmount = saleCalculationService.calculateSaleAmount(items) val quantity = saleCalculationService.calculateQuantity(items) + val changeAmount = saleCalculationService.calculateChange(saleBean.deposit, totalAmount) val sale = SaleEntity( @@ -44,6 +45,7 @@ class SalePersistenceService( quantity = quantity, amount = totalAmount, deposit = saleBean.deposit, + changeAmount = changeAmount, createdAt = Date(), ) diff --git a/src/main/kotlin/info/nukoneko/kidspos/server/service/SaleService.kt b/src/main/kotlin/info/nukoneko/kidspos/server/service/SaleService.kt index 00b837c..0461278 100644 --- a/src/main/kotlin/info/nukoneko/kidspos/server/service/SaleService.kt +++ b/src/main/kotlin/info/nukoneko/kidspos/server/service/SaleService.kt @@ -64,13 +64,16 @@ class SaleService( items.forEach { logger.debug("Item - ID: {}, Name: {}, Price: {}", it.id, it.name, it.price) } + val totalAmount = items.sumOf { it.price } + val changeAmount = saleBean.deposit - totalAmount val sale = SaleEntity( id, saleBean.storeId, items.size, - items.sumOf { it.price }, + totalAmount, saleBean.deposit, + changeAmount, Date(), )