feat(android): add attachment API methods and result classes
Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -372,6 +372,248 @@ void main() {
|
||||
expect(missing.errorMessage, '指定装箱明细不存在');
|
||||
});
|
||||
});
|
||||
|
||||
group('ApiService attachment APIs', () {
|
||||
test('fetchAttachmentCategories parses list', () async {
|
||||
final mockClient = _MockClient((request) async {
|
||||
return http.Response(
|
||||
jsonEncode([
|
||||
{'id': 1, 'name': '检验证书', 'sort_order': 1},
|
||||
{'id': 2, 'name': '增发', 'sort_order': 2},
|
||||
]),
|
||||
200,
|
||||
headers: {'content-type': 'application/json; charset=utf-8'},
|
||||
);
|
||||
});
|
||||
final svc = ApiService(client: mockClient);
|
||||
final result = await svc.fetchAttachmentCategories(
|
||||
baseUrl: 'http://localhost',
|
||||
);
|
||||
expect(result.success, isTrue);
|
||||
expect(result.categories.length, 2);
|
||||
expect(result.categories.first.name, '检验证书');
|
||||
});
|
||||
|
||||
test('fetchAttachmentCategories handles network failure', () async {
|
||||
final mockClient = _MockClient((request) async {
|
||||
throw Exception('Connection refused');
|
||||
});
|
||||
final svc = ApiService(client: mockClient);
|
||||
final result = await svc.fetchAttachmentCategories(
|
||||
baseUrl: 'http://localhost',
|
||||
);
|
||||
expect(result.success, isFalse);
|
||||
expect(result.errorMessage, '网络异常,请检查网络连接');
|
||||
});
|
||||
|
||||
test('fetchAttachmentStatus parses undetermined zongpai', () async {
|
||||
final mockClient = _MockClient((request) async {
|
||||
return http.Response(
|
||||
jsonEncode({
|
||||
'zongpai_no': '26BW0011',
|
||||
'determination': 'undetermined',
|
||||
'all_complete': false,
|
||||
'items': [],
|
||||
}),
|
||||
200,
|
||||
headers: {'content-type': 'application/json; charset=utf-8'},
|
||||
);
|
||||
});
|
||||
final svc = ApiService(client: mockClient);
|
||||
final result = await svc.fetchAttachmentStatus(
|
||||
baseUrl: 'http://localhost',
|
||||
zongpaiNo: '26BW0011',
|
||||
);
|
||||
expect(result.success, isTrue);
|
||||
expect(result.determination, 'undetermined');
|
||||
expect(result.items, isEmpty);
|
||||
});
|
||||
|
||||
test('putAttachmentConfig sends full payload', () async {
|
||||
late Map<String, dynamic> body;
|
||||
final mockClient = _MockClient((request) async {
|
||||
final req = request as http.Request;
|
||||
body = jsonDecode(req.body) as Map<String, dynamic>;
|
||||
return http.Response(
|
||||
jsonEncode({
|
||||
'zongpai_no': '26BW0011',
|
||||
'determination': 'has',
|
||||
'all_complete': false,
|
||||
'items': [
|
||||
{
|
||||
'category_id': 1,
|
||||
'name': '检验证书',
|
||||
'expected_qty': 80,
|
||||
'boxed_qty': 0,
|
||||
'location_code': null,
|
||||
'complete': false,
|
||||
},
|
||||
],
|
||||
}),
|
||||
200,
|
||||
headers: {'content-type': 'application/json; charset=utf-8'},
|
||||
);
|
||||
});
|
||||
final svc = ApiService(client: mockClient);
|
||||
final result = await svc.putAttachmentConfig(
|
||||
baseUrl: 'http://localhost',
|
||||
zongpaiNo: '26BW0011',
|
||||
determination: 'has',
|
||||
items: [AttachmentConfigItemData(categoryId: 1, expectedQty: 80)],
|
||||
);
|
||||
expect(result.success, isTrue);
|
||||
expect(result.items.single.complete, isFalse);
|
||||
expect(body['items'], [
|
||||
{'category_id': 1, 'expected_qty': 80},
|
||||
]);
|
||||
});
|
||||
|
||||
test('registerAttachmentLocation returns 200 with data', () async {
|
||||
final mockClient = _MockClient((request) async {
|
||||
return http.Response(
|
||||
jsonEncode({
|
||||
'zongpai_no': '26BW0011',
|
||||
'category_id': 1,
|
||||
'location_code': 'A01-01-01',
|
||||
'created_at': '2026-08-12T10:00:00',
|
||||
'previous_location': null,
|
||||
}),
|
||||
200,
|
||||
headers: {'content-type': 'application/json; charset=utf-8'},
|
||||
);
|
||||
});
|
||||
final svc = ApiService(client: mockClient);
|
||||
final result = await svc.registerAttachmentLocation(
|
||||
baseUrl: 'http://localhost',
|
||||
zongpaiNo: '26BW0011',
|
||||
categoryId: 1,
|
||||
locationCode: 'A01-01-01',
|
||||
);
|
||||
expect(result.success, isTrue);
|
||||
expect(result.locationCode, 'A01-01-01');
|
||||
});
|
||||
|
||||
test('saveAttachmentBox sends request with category_id', () async {
|
||||
late Map<String, dynamic> body;
|
||||
final mockClient = _MockClient((request) async {
|
||||
final req = request as http.Request;
|
||||
body = jsonDecode(req.body) as Map<String, dynamic>;
|
||||
return http.Response(
|
||||
jsonEncode({
|
||||
'box_item_id': 1,
|
||||
'paichan_no': 'W00009',
|
||||
'box_no': 10,
|
||||
'zongpai_no': '26BW0011',
|
||||
'category_id': 1,
|
||||
'quantity': 30,
|
||||
'created_at': '2026-08-12T10:00:00',
|
||||
}),
|
||||
200,
|
||||
headers: {'content-type': 'application/json; charset=utf-8'},
|
||||
);
|
||||
});
|
||||
final svc = ApiService(client: mockClient);
|
||||
final result = await svc.saveAttachmentBox(
|
||||
baseUrl: 'http://localhost',
|
||||
zongpaiNo: '26BW0011',
|
||||
categoryId: 1,
|
||||
boxNo: 10,
|
||||
quantity: 30,
|
||||
);
|
||||
expect(result.success, isTrue);
|
||||
expect(result.boxItemId, 1);
|
||||
expect(body['category_id'], 1);
|
||||
});
|
||||
|
||||
test('saveAttachmentBox returns duplicate on 409', () async {
|
||||
final mockClient = _MockClient((request) async {
|
||||
return http.Response(
|
||||
jsonEncode({
|
||||
'error_code': 'DUPLICATE_BOX_NO',
|
||||
'message': '排产号 W00009 下箱号 10 已存在',
|
||||
'paichan_no': 'W00009',
|
||||
'box_no': 10,
|
||||
}),
|
||||
409,
|
||||
headers: {'content-type': 'application/json; charset=utf-8'},
|
||||
);
|
||||
});
|
||||
final svc = ApiService(client: mockClient);
|
||||
final result = await svc.saveAttachmentBox(
|
||||
baseUrl: 'http://localhost',
|
||||
zongpaiNo: '26BW0011',
|
||||
categoryId: 1,
|
||||
boxNo: 10,
|
||||
quantity: 30,
|
||||
);
|
||||
expect(result.success, isFalse);
|
||||
expect(result.isDuplicate, isTrue);
|
||||
});
|
||||
|
||||
test('updateAttachmentBox sends PATCH with box_no and quantity', () async {
|
||||
late Map<String, dynamic> body;
|
||||
final mockClient = _MockClient((request) async {
|
||||
final req = request as http.Request;
|
||||
body = jsonDecode(req.body) as Map<String, dynamic>;
|
||||
return http.Response(
|
||||
jsonEncode({
|
||||
'box_item_id': 1,
|
||||
'paichan_no': 'W00009',
|
||||
'box_no': 11,
|
||||
'zongpai_no': '26BW0011',
|
||||
'category_id': 1,
|
||||
'quantity': 20,
|
||||
'updated_at': '2026-08-12T10:00:00',
|
||||
}),
|
||||
200,
|
||||
headers: {'content-type': 'application/json; charset=utf-8'},
|
||||
);
|
||||
});
|
||||
final svc = ApiService(client: mockClient);
|
||||
final result = await svc.updateAttachmentBox(
|
||||
baseUrl: 'http://localhost',
|
||||
boxItemId: 1,
|
||||
boxNo: 11,
|
||||
quantity: 20,
|
||||
);
|
||||
expect(result.success, isTrue);
|
||||
expect(body, {'box_no': 11, 'quantity': 20});
|
||||
});
|
||||
|
||||
test('deleteAttachmentBox handles success and not found', () async {
|
||||
var calls = 0;
|
||||
final mockClient = _MockClient((request) async {
|
||||
calls += 1;
|
||||
if (calls == 1) {
|
||||
return http.Response(
|
||||
jsonEncode({'box_item_id': 1, 'deleted': true}),
|
||||
200,
|
||||
headers: {'content-type': 'application/json; charset=utf-8'},
|
||||
);
|
||||
}
|
||||
return http.Response(
|
||||
jsonEncode({
|
||||
'error_code': 'BOX_ITEM_NOT_FOUND',
|
||||
'message': '指定装箱明细不存在',
|
||||
}),
|
||||
404,
|
||||
headers: {'content-type': 'application/json; charset=utf-8'},
|
||||
);
|
||||
});
|
||||
final svc = ApiService(client: mockClient);
|
||||
final ok = await svc.deleteAttachmentBox(
|
||||
baseUrl: 'http://localhost',
|
||||
boxItemId: 1,
|
||||
);
|
||||
final missing = await svc.deleteAttachmentBox(
|
||||
baseUrl: 'http://localhost',
|
||||
boxItemId: 999,
|
||||
);
|
||||
expect(ok.success, isTrue);
|
||||
expect(missing.success, isFalse);
|
||||
expect(missing.errorMessage, '指定装箱明细不存在');
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
class _MockClient extends http.BaseClient {
|
||||
|
||||
Reference in New Issue
Block a user