From 3c7a2a67c6e1c58f6fb6bbc0ab73e0d8de2a43c7 Mon Sep 17 00:00:00 2001 From: atsumi Date: Sat, 4 Oct 2025 01:50:42 +0900 Subject: [PATCH 1/2] =?UTF-8?q?refactor:=20API=E4=BB=95=E6=A7=98=E6=9B=B4?= =?UTF-8?q?=E6=96=B0=E3=81=A8Staff=E6=A9=9F=E8=83=BD=E3=81=AE=E5=89=8A?= =?UTF-8?q?=E9=99=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit API仕様をv2に更新し、Staff/User関連機能を完全に削除しました。 ## 主な変更内容 ### API仕様の更新 - `/api/staff`エンドポイントを削除 - `/api/users`エンドポイントを削除 - `CreateSaleRequest`から`staffBarcode`フィールドを削除 - `ErrorResponse.details`をMap型からString型に変更(kotlinx.serialization互換性のため) ### コード変更 - Staff entityを削除 - BarcodeEventからStaff関連イベント(ReadStaffSuccess/Failed)を削除 - GlobalConfigから`currentStaff`プロパティを削除 - APIServiceから`getStaff()`メソッドと`createSale()`の`staffBarcode`パラメータを削除 - DI設定からStaffApi、UsersApiの依存を削除 ### UI変更 - ItemListViewModelからStaff表示機能を削除 - fragment_item_list.xmlからStaff表示UIを削除 - MainViewModelからStaff関連処理を削除 ## ビルド確認 - `./gradlew assembleProdDebug` 成功 --- app/openapi/api.yaml | 320 +++++------------- .../android/kidspos/di/module/apiModule.kt | 6 - .../cuc/android/kidspos/api/APIService.kt | 46 +-- .../cuc/android/kidspos/di/GlobalConfig.kt | 14 - .../cuc/android/kidspos/entity/Staff.kt | 13 +- .../cuc/android/kidspos/event/BarcodeEvent.kt | 3 - .../android/kidspos/ui/main/MainViewModel.kt | 25 +- .../calculate/CalculatorDialogViewModel.kt | 5 +- .../ui/main/itemlist/ItemListViewModel.kt | 21 -- .../main/res/layout/fragment_item_list.xml | 16 +- .../android/kidspos/di/module/apiModule.kt | 7 - 11 files changed, 111 insertions(+), 365 deletions(-) diff --git a/app/openapi/api.yaml b/app/openapi/api.yaml index 8ef708e..49c9917 100644 --- a/app/openapi/api.yaml +++ b/app/openapi/api.yaml @@ -18,14 +18,10 @@ tags: description: 商品管理 - name: Sales description: 売上管理 - - name: Staff - description: スタッフ管理 - name: Stores description: 店舗管理 - name: Settings description: 設定管理 - - name: Users - description: ユーザー管理 paths: # Items @@ -247,27 +243,43 @@ paths: schema: $ref: '#/components/schemas/CreateSaleRequest' responses: - '200': - description: Success + '201': + description: Created content: application/json: schema: type: object properties: - status: - type: string - saleId: + id: type: integer - totalAmount: + description: 売上ID + amount: type: integer + description: 合計金額 + quantity: + type: integer + description: 商品数 + deposit: + type: integer + description: 預かり金額 change: type: integer - receiptPrinted: - type: boolean + description: おつり + storeId: + type: integer + description: 店舗ID '400': description: Validation error + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' '500': description: Processing error + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' /api/sales/{id}: get: @@ -316,113 +328,6 @@ paths: isValid: type: boolean - # Staff - /api/staff: - get: - tags: - - Staff - summary: スタッフ一覧取得 - description: 全スタッフを取得します - operationId: getAllStaff - responses: - '200': - description: Success - content: - application/json: - schema: - type: array - items: - $ref: '#/components/schemas/StaffEntity' - - post: - tags: - - Staff - summary: スタッフ登録 - description: 新しいスタッフを登録します - operationId: createStaff - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/CreateStaffRequest' - responses: - '201': - description: Created - content: - application/json: - schema: - $ref: '#/components/schemas/StaffEntity' - - /api/staff/{barcode}: - get: - tags: - - Staff - summary: スタッフ取得 - description: バーコードからスタッフを取得します - operationId: getStaffByBarcode - parameters: - - name: barcode - in: path - required: true - schema: - type: string - responses: - '200': - description: Success - content: - application/json: - schema: - $ref: '#/components/schemas/StaffEntity' - '404': - description: Staff not found - - put: - tags: - - Staff - summary: スタッフ更新 - description: スタッフ情報を更新します - operationId: updateStaff - parameters: - - name: barcode - in: path - required: true - schema: - type: string - requestBody: - required: true - content: - application/json: - schema: - $ref: '#/components/schemas/UpdateStaffRequest' - responses: - '200': - description: Success - content: - application/json: - schema: - $ref: '#/components/schemas/StaffEntity' - '404': - description: Staff not found - - delete: - tags: - - Staff - summary: スタッフ削除 - description: スタッフを削除します - operationId: deleteStaff - parameters: - - name: barcode - in: path - required: true - schema: - type: string - responses: - '204': - description: No Content - '404': - description: Staff not found - # Stores /api/stores: get: @@ -778,46 +683,6 @@ paths: message: type: string - # Users - /api/users: - get: - tags: - - Users - summary: ユーザー一覧取得 - description: 全ユーザーを取得します - operationId: getAllUsers - responses: - '200': - description: Success - content: - application/json: - schema: - type: array - items: - $ref: '#/components/schemas/StaffEntity' - - /api/users/{barcode}: - get: - tags: - - Users - summary: ユーザー取得 - description: バーコードからユーザーを取得します - operationId: getUserByBarcode - parameters: - - name: barcode - in: path - required: true - schema: - type: string - responses: - '200': - description: Success - content: - application/json: - schema: - $ref: '#/components/schemas/StaffEntity' - '404': - description: User not found components: schemas: @@ -870,102 +735,88 @@ components: properties: id: type: integer + description: 売上ID storeId: type: integer - staffBarcode: - type: string - createdAt: + description: 店舗ID + storeName: type: string - format: date-time + description: 店舗名 totalAmount: type: integer description: 合計金額(リバー) deposit: type: integer description: 預り金(リバー) - items: - type: array - items: - type: object - properties: - barcode: - type: string - name: - type: string - price: - type: integer - quantity: - type: integer - - CreateSaleRequest: - type: object - properties: - storeId: + change: type: integer - staffBarcode: + description: お釣り(リバー) + saleTime: type: string + format: date-time + description: 売上時刻 items: type: array + description: 売上商品リスト items: - type: object - properties: - barcode: - type: string - quantity: - type: integer - minimum: 1 - required: - - barcode - - quantity - deposit: - type: integer - minimum: 0 - printReceipt: - type: boolean - default: true + $ref: '#/components/schemas/SaleItemResponse' required: + - id - storeId - - staffBarcode - - items + - storeName + - totalAmount - deposit + - change + - saleTime - StaffEntity: + SaleItemResponse: type: object properties: - barcode: - type: string - example: "STAFF001" - name: + itemId: + type: integer + description: 商品ID + itemName: type: string - example: "田中太郎" - required: - - barcode - - name - - CreateStaffRequest: - type: object - properties: + description: 商品名 barcode: type: string - minLength: 1 - maxLength: 50 - name: - type: string - minLength: 1 - maxLength: 100 + description: バーコード + quantity: + type: integer + description: 数量 + unitPrice: + type: integer + description: 単価(リバー) + subtotal: + type: integer + description: 小計(リバー) required: + - itemId + - itemName - barcode - - name + - quantity + - unitPrice + - subtotal - UpdateStaffRequest: + CreateSaleRequest: type: object properties: - name: + storeId: + type: integer + description: 店舗ID + itemIds: type: string - minLength: 1 - maxLength: 100 + description: 商品IDのカンマ区切り文字列(例:"1,2,3") + example: "1,2,3" + deposit: + type: integer + minimum: 0 + description: 預かり金額 required: - - name + - storeId + - itemIds + - deposit + StoreEntity: type: object @@ -1005,15 +856,30 @@ components: ErrorResponse: type: object properties: - error: + code: type: string + description: エラーコード + example: "VALIDATION_ERROR" message: type: string + description: エラーメッセージ + example: "商品IDが空です。売上作成には少なくとも1つの商品が必要です" timestamp: type: string format: date-time + description: エラー発生時刻 path: type: string + nullable: true + description: リクエストパス + details: + type: string + nullable: true + description: 追加の詳細情報(JSON文字列) + required: + - code + - message + - timestamp securitySchemes: bearerAuth: @@ -1023,4 +889,4 @@ components: # セキュリティは現在未実装のため、コメントアウト # security: -# - bearerAuth: [] \ No newline at end of file +# - bearerAuth: [] diff --git a/app/src/demo/kotlin/info/nukoneko/cuc/android/kidspos/di/module/apiModule.kt b/app/src/demo/kotlin/info/nukoneko/cuc/android/kidspos/di/module/apiModule.kt index cd0ff66..ad4917b 100644 --- a/app/src/demo/kotlin/info/nukoneko/cuc/android/kidspos/di/module/apiModule.kt +++ b/app/src/demo/kotlin/info/nukoneko/cuc/android/kidspos/di/module/apiModule.kt @@ -3,7 +3,6 @@ package info.nukoneko.cuc.android.kidspos.di.module import info.nukoneko.cuc.android.kidspos.api.APIService import info.nukoneko.cuc.android.kidspos.entity.Item import info.nukoneko.cuc.android.kidspos.entity.Sale -import info.nukoneko.cuc.android.kidspos.entity.Staff import info.nukoneko.cuc.android.kidspos.entity.Store import org.koin.dsl.module import java.util.* @@ -15,7 +14,6 @@ import java.util.* class DemoAPIService : APIService( itemsApi = throw NotImplementedError("Demo mode - itemsApi not used"), salesApi = throw NotImplementedError("Demo mode - salesApi not used"), - staffApi = throw NotImplementedError("Demo mode - staffApi not used"), storesApi = throw NotImplementedError("Demo mode - storesApi not used"), settingsApi = throw NotImplementedError("Demo mode - settingsApi not used") ) { @@ -23,7 +21,6 @@ class DemoAPIService : APIService( override suspend fun createSale( storeId: Int, - staffBarcode: String, deposit: Int, itemIds: String ): Sale = Sale( @@ -52,9 +49,6 @@ class DemoAPIService : APIService( storeId = 1, genreId = 1 ) - - override suspend fun getStaff(staffBarcode: String): Staff = - Staff(staffBarcode, "DemoStaff") } val apiModule = module { diff --git a/app/src/main/kotlin/info/nukoneko/cuc/android/kidspos/api/APIService.kt b/app/src/main/kotlin/info/nukoneko/cuc/android/kidspos/api/APIService.kt index b23e6e0..aa28b58 100644 --- a/app/src/main/kotlin/info/nukoneko/cuc/android/kidspos/api/APIService.kt +++ b/app/src/main/kotlin/info/nukoneko/cuc/android/kidspos/api/APIService.kt @@ -4,7 +4,6 @@ import info.nukoneko.cuc.android.kidspos.api.generated.* import info.nukoneko.cuc.android.kidspos.api.generated.model.* import info.nukoneko.cuc.android.kidspos.entity.Item import info.nukoneko.cuc.android.kidspos.entity.Sale -import info.nukoneko.cuc.android.kidspos.entity.Staff import info.nukoneko.cuc.android.kidspos.entity.Store import retrofit2.Response @@ -14,7 +13,6 @@ import retrofit2.Response open class APIService( private val itemsApi: ItemsApi, private val salesApi: SalesApi, - private val staffApi: StaffApi, private val storesApi: StoresApi, private val settingsApi: SettingsApi ) { @@ -36,38 +34,27 @@ open class APIService( open suspend fun createSale( storeId: Int, - staffBarcode: String, deposit: Int, itemIds: String ): Sale { - // itemIdsをカンマ区切りからリストに変換 - // 注意: 新しいAPIではitemIdではなくバーコードを使用 - val itemBarcodes = itemIds.split(",") - val request = CreateSaleRequest( storeId = storeId, - staffBarcode = staffBarcode, - deposit = deposit, - items = itemBarcodes.map { barcode -> - CreateSaleRequestItemsInner( - barcode = barcode, - quantity = 1 // デフォルトで1個とする - ) - } + itemIds = itemIds, + deposit = deposit ) val response = salesApi.createSale(request) return if (response.isSuccessful) { val saleResponse = response.body()!! Sale( - id = saleResponse.saleId ?: 0, - barcode = saleResponse.saleId?.toString() ?: "", // バーコードはIDから生成 - createdAt = java.util.Date().toString(), // 現在時刻を設定 - points = 0, // ポイントは新APIにない - price = saleResponse.totalAmount ?: 0, - items = itemIds, // 元のitemIdsをそのまま使用 - storeId = storeId, - staffId = 0 // スタッフIDは取得できないため仮値 + id = saleResponse.id ?: 0, + barcode = saleResponse.id?.toString() ?: "", + createdAt = java.util.Date().toString(), + points = 0, + price = saleResponse.amount ?: 0, + items = itemIds, + storeId = saleResponse.storeId ?: storeId, + staffId = 0 ) } else { throw Exception("Failed to create sale: ${response.code()}") @@ -91,19 +78,6 @@ open class APIService( } } - open suspend fun getStaff(staffBarcode: String): Staff { - val response = staffApi.getStaffByBarcode(staffBarcode) - return if (response.isSuccessful) { - val staffResponse = response.body()!! - Staff( - barcode = staffResponse.barcode ?: staffBarcode, - name = staffResponse.name ?: "" - ) - } else { - throw Exception("Failed to get staff: ${response.code()}") - } - } - open suspend fun getStatus(): Any { val response = settingsApi.getStatus() return if (response.isSuccessful) { diff --git a/app/src/main/kotlin/info/nukoneko/cuc/android/kidspos/di/GlobalConfig.kt b/app/src/main/kotlin/info/nukoneko/cuc/android/kidspos/di/GlobalConfig.kt index 8338a2b..8653c36 100644 --- a/app/src/main/kotlin/info/nukoneko/cuc/android/kidspos/di/GlobalConfig.kt +++ b/app/src/main/kotlin/info/nukoneko/cuc/android/kidspos/di/GlobalConfig.kt @@ -3,7 +3,6 @@ package info.nukoneko.cuc.android.kidspos.di import android.content.Context import androidx.core.content.edit import androidx.preference.PreferenceManager -import info.nukoneko.cuc.android.kidspos.entity.Staff import info.nukoneko.cuc.android.kidspos.entity.Store import info.nukoneko.cuc.android.kidspos.event.EventBus import info.nukoneko.cuc.android.kidspos.event.SystemEvent @@ -54,23 +53,10 @@ class GlobalConfig(context: Context, private val eventBus: EventBus, private val eventBus.post(SystemEvent.SelectShop(value)) } - var currentStaff: Staff? - get() { - return preference.getString(KEY_STAFF, null)?.let { - return json.decodeFromString(it) - } - } - set(value) { - preference.edit { - putString(KEY_STAFF, json.encodeToString(value)) - } - } - companion object { const val KEY_SERVER_INFO = "setting_server_info" const val KEY_RUNNING_MODE = "setting_running_mode" const val DEFAULT_SERVER_INFO = "http://192.168.0.220:8080" const val KEY_STORE = "store" - const val KEY_STAFF = "staff" } } diff --git a/app/src/main/kotlin/info/nukoneko/cuc/android/kidspos/entity/Staff.kt b/app/src/main/kotlin/info/nukoneko/cuc/android/kidspos/entity/Staff.kt index 551f524..6be9877 100644 --- a/app/src/main/kotlin/info/nukoneko/cuc/android/kidspos/entity/Staff.kt +++ b/app/src/main/kotlin/info/nukoneko/cuc/android/kidspos/entity/Staff.kt @@ -1,12 +1 @@ -package info.nukoneko.cuc.android.kidspos.entity - -import kotlinx.serialization.Serializable - -@Serializable -data class Staff(val barcode: String, val name: String) { - companion object { - fun create(barcode: String): Staff { - return Staff(barcode, "Dummy") - } - } -} +// This file is deprecated and will be removed diff --git a/app/src/main/kotlin/info/nukoneko/cuc/android/kidspos/event/BarcodeEvent.kt b/app/src/main/kotlin/info/nukoneko/cuc/android/kidspos/event/BarcodeEvent.kt index 5a75277..7b98cc3 100644 --- a/app/src/main/kotlin/info/nukoneko/cuc/android/kidspos/event/BarcodeEvent.kt +++ b/app/src/main/kotlin/info/nukoneko/cuc/android/kidspos/event/BarcodeEvent.kt @@ -1,12 +1,9 @@ package info.nukoneko.cuc.android.kidspos.event import info.nukoneko.cuc.android.kidspos.entity.Item -import info.nukoneko.cuc.android.kidspos.entity.Staff sealed class BarcodeEvent : Event { data class ReadReceiptFailed(val error: Throwable) : BarcodeEvent() data class ReadItemSuccess(val item: Item) : BarcodeEvent() data class ReadItemFailed(val error: Throwable) : BarcodeEvent() - data class ReadStaffSuccess(val staff: Staff) : BarcodeEvent() - data class ReadStaffFailed(val error: Throwable) : BarcodeEvent() } diff --git a/app/src/main/kotlin/info/nukoneko/cuc/android/kidspos/ui/main/MainViewModel.kt b/app/src/main/kotlin/info/nukoneko/cuc/android/kidspos/ui/main/MainViewModel.kt index 5b67aaf..529d21f 100644 --- a/app/src/main/kotlin/info/nukoneko/cuc/android/kidspos/ui/main/MainViewModel.kt +++ b/app/src/main/kotlin/info/nukoneko/cuc/android/kidspos/ui/main/MainViewModel.kt @@ -5,7 +5,6 @@ import info.nukoneko.cuc.android.kidspos.ProjectSettings import info.nukoneko.cuc.android.kidspos.api.APIService import info.nukoneko.cuc.android.kidspos.di.GlobalConfig import info.nukoneko.cuc.android.kidspos.entity.Item -import info.nukoneko.cuc.android.kidspos.entity.Staff import info.nukoneko.cuc.android.kidspos.event.BarcodeEvent import info.nukoneko.cuc.android.kidspos.event.EventBus import info.nukoneko.cuc.android.kidspos.event.SystemEvent @@ -44,11 +43,10 @@ class MainViewModel( onReadItemSuccess(Item.create(barcode)) } BarcodeKind.STAFF -> { - onReadStaffSuccess(Staff.create(barcode)) + // Staff機能は廃止 } else -> { onReadItemSuccess(Item.create(barcode)) - onReadStaffSuccess(Staff.create(barcode)) } } } else { @@ -65,14 +63,7 @@ class MainViewModel( } } BarcodeKind.STAFF -> { - launch { - try { - val staff = requestGetStaff(barcode) - onReadStaffSuccess(staff) - } catch (e: Throwable) { - onReadStaffFailure(e) - } - } + // Staff機能は廃止 } BarcodeKind.SALE -> eventBus.post(BarcodeEvent.ReadReceiptFailed(IOException("まだ対応していない"))) BarcodeKind.UNKNOWN -> { @@ -122,14 +113,6 @@ class MainViewModel( eventBus.post(BarcodeEvent.ReadItemFailed(e)) } - private fun onReadStaffSuccess(staff: Staff) { - eventBus.post(BarcodeEvent.ReadStaffSuccess(staff)) - } - - private fun onReadStaffFailure(e: Throwable) { - eventBus.post(BarcodeEvent.ReadStaffFailed(e)) - } - private fun safetyShowMessage(message: String) { launch(Dispatchers.Main) { listener?.onShouldShowMessage(message) @@ -152,10 +135,6 @@ class MainViewModel( api.getItem(barcode) } - private suspend fun requestGetStaff(barcode: String) = withContext(Dispatchers.IO) { - api.getStaff(barcode) - } - @Subscribe(threadMode = ThreadMode.MAIN) fun onSelectShopEvent(@Suppress("UNUSED_PARAMETER") event: SystemEvent.SelectShop) { updateTitle() diff --git a/app/src/main/kotlin/info/nukoneko/cuc/android/kidspos/ui/main/calculate/CalculatorDialogViewModel.kt b/app/src/main/kotlin/info/nukoneko/cuc/android/kidspos/ui/main/calculate/CalculatorDialogViewModel.kt index f8a0826..6a8a179 100644 --- a/app/src/main/kotlin/info/nukoneko/cuc/android/kidspos/ui/main/calculate/CalculatorDialogViewModel.kt +++ b/app/src/main/kotlin/info/nukoneko/cuc/android/kidspos/ui/main/calculate/CalculatorDialogViewModel.kt @@ -94,8 +94,9 @@ class CalculatorDialogViewModel( val ids = items.map { it.id.toString() } val joinedIds = ids.joinToString(",") api.createSale( - config.currentStore?.id ?: 0, config.currentStaff?.barcode - ?: "", deposit, joinedIds + config.currentStore?.id ?: 0, + deposit, + joinedIds ) } diff --git a/app/src/main/kotlin/info/nukoneko/cuc/android/kidspos/ui/main/itemlist/ItemListViewModel.kt b/app/src/main/kotlin/info/nukoneko/cuc/android/kidspos/ui/main/itemlist/ItemListViewModel.kt index 1491fc1..8354352 100644 --- a/app/src/main/kotlin/info/nukoneko/cuc/android/kidspos/ui/main/itemlist/ItemListViewModel.kt +++ b/app/src/main/kotlin/info/nukoneko/cuc/android/kidspos/ui/main/itemlist/ItemListViewModel.kt @@ -23,12 +23,6 @@ class ItemListViewModel( private val currentPrice = MutableLiveData() fun getCurrentPriceText(): LiveData = currentPrice - private val currentStaff = MutableLiveData() - fun getCurrentStaffText(): LiveData = currentStaff - - private val currentStaffVisibility = MutableLiveData() - fun getCurrentStaffVisibility(): LiveData = currentStaffVisibility - private val accountButtonEnabled = MutableLiveData() fun getAccountButtonEnabled(): LiveData = accountButtonEnabled @@ -85,9 +79,6 @@ class ItemListViewModel( private fun updateViews() { currentPrice.postValue("${currentTotal()} リバー") accountButtonEnabled.postValue(data.isNotEmpty()) - currentStaffVisibility.value = - if (config.currentStaff == null) View.INVISIBLE else View.VISIBLE - currentStaff.postValue("たんとう: ${config.currentStaff?.name ?: ""}") // 練習モードのときのみ商品追加ボタンを表示 addItemButtonVisibility.postValue( if (config.currentRunningMode == Mode.PRACTICE) View.VISIBLE else View.GONE @@ -102,23 +93,11 @@ class ItemListViewModel( updateViews() } - @Subscribe(threadMode = ThreadMode.MAIN) - fun onReadStaffSuccessEvent(event: BarcodeEvent.ReadStaffSuccess) { - val staff = event.staff - config.currentStaff = staff - updateViews() - } - @Subscribe(threadMode = ThreadMode.MAIN) fun onReadItemFailedEvent(@Suppress("UNUSED_PARAMETER") event: BarcodeEvent.ReadItemFailed) { listener?.onShouldShowMessage(R.string.request_item_failed) } - @Subscribe(threadMode = ThreadMode.MAIN) - fun onReadStaffFailedEvent(@Suppress("UNUSED_PARAMETER") event: BarcodeEvent.ReadStaffFailed) { - listener?.onShouldShowMessage(R.string.request_staff_failed) - } - @Subscribe(threadMode = ThreadMode.MAIN) fun onReadReceiptFailedEvent(@Suppress("UNUSED_PARAMETER") event: BarcodeEvent.ReadReceiptFailed) { listener?.onShouldShowMessage(R.string.read_receipt_failed) diff --git a/app/src/main/res/layout/fragment_item_list.xml b/app/src/main/res/layout/fragment_item_list.xml index 6dcdf66..70b6c9f 100644 --- a/app/src/main/res/layout/fragment_item_list.xml +++ b/app/src/main/res/layout/fragment_item_list.xml @@ -64,22 +64,10 @@ android:textSize="22sp" android:visibility="@{viewModel.addItemButtonVisibility}" /> - - - - + android:layout_weight="1" />