Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 23 additions & 4 deletions ios/CodeMatch/Features/Scanner/ScannerScreen.swift
Original file line number Diff line number Diff line change
Expand Up @@ -260,8 +260,12 @@ struct ScannerScreen: View {
result: result,
sessionBoxNumber: viewModel.sessionBoxNumber,
deliverySummary: viewModel.deliverySummary,
qrPartNumber: viewModel.qrPartNumber.map { CodeMatcher.format(partNumber: $0) },
barcodePartNumber: viewModel.barcodePartNumber.map { CodeMatcher.format(partNumber: $0) }
qrPartNumber: viewModel.qrPartNumber.map {
CodeMatcher.format(partNumber: $0, destination: viewModel.destination)
},
barcodePartNumber: viewModel.barcodePartNumber.map {
CodeMatcher.format(partNumber: $0, destination: viewModel.destination)
}
)
.accessibilityIdentifier("resultView")
case .qr, .barcode:
Expand Down Expand Up @@ -452,12 +456,16 @@ struct ScannerScreen: View {
VStack(spacing: 8) {
CodeReadout(
label: AppLocalization.string("QR・納品書の品目番号"),
partNumber: viewModel.qrPartNumber.map { CodeMatcher.format(partNumber: $0) },
partNumber: viewModel.qrPartNumber.map {
CodeMatcher.format(partNumber: $0, destination: viewModel.destination)
},
payload: viewModel.qrValue
)
CodeReadout(
label: AppLocalization.string("バーコード・現品票の品番"),
partNumber: viewModel.barcodePartNumber.map { CodeMatcher.format(partNumber: $0) },
partNumber: viewModel.barcodePartNumber.map {
CodeMatcher.format(partNumber: $0, destination: viewModel.destination)
},
payload: viewModel.barcodeValue
)
}
Expand Down Expand Up @@ -641,6 +649,17 @@ struct ScannerScreen: View {
}
.accessibilityIdentifier("demoBluetoothMoltenBarcodeButton")
}

HStack {
Button(AppLocalization.string("モックQR(デンソー)")) {
bluetoothScanner.simulateScan(ScannerViewModel.sampleDensoQRPayload)
}
.accessibilityIdentifier("demoBluetoothDensoQRButton")
Button(AppLocalization.string("モックCode 128(デンソー)")) {
bluetoothScanner.simulateScan(ScannerViewModel.sampleDensoBarcodePayload)
}
.accessibilityIdentifier("demoBluetoothDensoBarcodeButton")
}
}
}
.buttonStyle(.borderedProminent)
Expand Down
22 changes: 20 additions & 2 deletions ios/CodeMatch/Features/Scanner/ScannerViewModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,16 @@ final class ScannerViewModel: ObservableObject {
/// 同じ納品書QRの2箱目。モルテンのQRは箱を区別しないため、現品票の管理コードだけが異なる。
static let sampleMoltenSecondBoxBarcodePayload = "PAF1-15-422@0NLL3C"
static let sampleMoltenMismatchBarcodePayload = "PAF1-15-423@0N5L3C"
/// 実ラベル由来のサンプルペイロード(仕向地 デンソー・品番 860150-7722)。
/// JAMA自己記述形式のかんばん。かんばん連番(項目152)が箱ごとに異なるため、
/// 重複判定は澤井製作所と同じくQR全文で行う。
static let sampleDensoQRPayload = "JAMA501195000001021100021041011102112071210412406127041410214201144061520440205515015160151908520045210652606523105220640102208601507722000000024D850C01008D85045M 0140SWS 20260908S0010000720000009924543330454333M6"
static let sampleDensoBarcodePayload = "860150-7722@1DZ50O"
/// 同じ品番の2箱目。かんばん連番が0140から0141に変わる。
static let sampleDensoSecondBoxQRPayload = "JAMA501195000001021100021041011102112071210412406127041410214201144061520440205515015160151908520045210652606523105220640102208601507722000000024D850C01008D85045M 0141SWS 20260908S0010000720000009924543330454333M6"
static let sampleDensoSecondBoxBarcodePayload = "860150-7722@1DZB0O"
/// 別品番(860150-7791)の現品票。不一致の確認に使う。
static let sampleDensoMismatchBarcodePayload = "860150-7791@01335C"

var qrPartNumber: String? {
CodeMatcher.partNumber(fromQR: qrValue)
Expand Down Expand Up @@ -445,7 +455,9 @@ final class ScannerViewModel: ObservableObject {
camera.setActiveType(ExpectedCode.barcode.metadataType)
}
if let part = CodeMatcher.partNumber(fromQR: value) {
let partNumber = CodeMatcher.format(partNumber: part)
// 表記は仕向地ごとに違う(デンソーは6-4、それ以外は4-2-4/4-2-3)。
// ここでは受理したQRの仕向地をそのまま使う。
let partNumber = CodeMatcher.format(partNumber: part, destination: destination)
let isBluetooth = inputSource == .bluetooth
setLocalizedMessage {
let instruction = isBluetooth
Expand Down Expand Up @@ -686,6 +698,8 @@ final class ScannerViewModel: ObservableObject {
)
}
} else {
// 澤井製作所とデンソーはQR自体が箱ごとに異なる(カード番号/かんばん連番)ため、
// 納品番号での集計は使わず、品番ごとに「本セッションでN箱目」を数える。
deliverySummary = nil
let boxNumber = historyStore.activeSessionMatchCount(code: recordedCode)
sessionBoxNumber = boxNumber
Expand Down Expand Up @@ -751,9 +765,13 @@ final class ScannerViewModel: ObservableObject {
}

/// 履歴へ残す値。読み取れた品番を優先し、抽出できない場合はQRの生値を使う。
/// 表記は仕向地ごとに違う(デンソーは6-4、それ以外は4-2-4/4-2-3)ため、
/// セッションで固定済みの仕向地を使う。デモ判定などQRの受理を経ない経路では
/// まだ固定されていないので、そのQRから判定し直す。
private var recordedCode: String {
if let part = barcodePartNumber ?? qrPartNumber {
return CodeMatcher.format(partNumber: part)
let destination = destination ?? Destination.detect(qrPayload: qrValue)
return CodeMatcher.format(partNumber: part, destination: destination)
}
return qrValue
}
Expand Down
32 changes: 32 additions & 0 deletions ios/CodeMatch/Resources/Localizable.xcstrings
Original file line number Diff line number Diff line change
Expand Up @@ -2492,6 +2492,22 @@
}
}
},
"モックCode 128(デンソー)" : {
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "Mock Code 128 (Denso)"
}
},
"ja" : {
"stringUnit" : {
"state" : "translated",
"value" : "モックCode 128(デンソー)"
}
}
}
},
"モックCode 128(モルテン)" : {
"localizations" : {
"en" : {
Expand All @@ -2508,6 +2524,22 @@
}
}
},
"モックQR(デンソー)" : {
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "Mock QR (Denso)"
}
},
"ja" : {
"stringUnit" : {
"state" : "translated",
"value" : "モックQR(デンソー)"
}
}
}
},
"モックQR(モルテン)" : {
"localizations" : {
"en" : {
Expand Down
5 changes: 3 additions & 2 deletions ios/CodeMatch/Services/HistoryStore.swift
Original file line number Diff line number Diff line change
Expand Up @@ -93,8 +93,9 @@ final class HistoryStore: ObservableObject {
}

/// アクティブセッションの成功履歴に、今回の箱がすでに含まれるかを確認する。
/// 澤井製作所のQRは箱ごとにカード番号が異なるためQR全文だけで箱を識別できるが、
/// モルテンのQRは同じ納品番号の全箱で同一なので、現品票のCode 128全文まで含めて識別する。
/// 澤井製作所のQRは箱ごとにカード番号が、デンソーのかんばんQRは箱ごとにかんばん連番
/// (項目152)が異なるため、どちらもQR全文だけで箱を識別できる。
/// モルテンのQRだけは同じ納品番号の全箱で同一なので、現品票のCode 128全文まで含めて識別する。
func activeSessionContainsMatchedBox(qrPayload: String, barcodePayload: String) -> Bool {
guard Destination.detect(qrPayload: qrPayload) == .molten else {
return activeSessionContainsMatchedQRPayload(qrPayload)
Expand Down
Loading
Loading