using FluentAssertions; using foodmarket.Api.Infrastructure.Invoices; using Xunit; namespace foodmarket.UnitTests; /// Разбор JSON-ответа модели для фото-приёмки (handoff §5): к обычной /// шапке добавляются photo, barcode_source (invoice|decoded|read), /// comment → Note, и unmatched_photos → Warnings. /// barcode_source=null (или отсутствует) означает «цифры не прочитаны уверенно» /// и мы обнуляем Barcode, чтобы не подставить что-то наугад. public class ClaudeCliInvoicePhotosParseTests { [Fact] public void Photos_decoded_source_passes_through() { var json = """ { "supplier":"ТОО X","number":"7","date":"2026-10-05","total":4500, "invoice_photos":[1], "lines":[ {"name":"Молоко 3.2%","qty":10,"price":450,"sum":4500, "barcode":"4870001234561","barcode_source":"decoded","photo":2,"comment":null} ], "unmatched_photos":[] } """; var inv = ClaudeCliInvoiceExtractor.FromPhotosJson(json); inv.Lines.Should().HaveCount(1); var l = inv.Lines[0]; l.Barcode.Should().Be("4870001234561"); l.BarcodeSource.Should().Be("decoded"); l.Photo.Should().Be(2); inv.Warnings.Should().BeEmpty(); } [Fact] public void Photos_source_null_clears_barcode() { // Если модель не уверена в цифрах, barcode_source=null → штрихкод не берём, // чтобы не привязать строку к чужому товару. var json = """ {"supplier":"X","lines":[ {"name":"A","qty":1,"price":10,"barcode":"4870000000000","barcode_source":null,"photo":null} ]} """; var inv = ClaudeCliInvoiceExtractor.FromPhotosJson(json); inv.Lines[0].Barcode.Should().BeNull(); inv.Lines[0].BarcodeSource.Should().BeNull(); } [Fact] public void Unmatched_photos_become_warning() { var json = """ {"supplier":"X","lines":[{"name":"A","qty":1,"price":10}], "unmatched_photos":[5,7]} """; var inv = ClaudeCliInvoiceExtractor.FromPhotosJson(json); inv.Warnings.Should().ContainMatch("*5*7*"); } [Fact] public void Comment_lands_in_note() { var json = """ {"supplier":"X","lines":[ {"name":"А","qty":1,"price":10,"barcode_source":"invoice","comment":"сверьте вес"} ]} """; var inv = ClaudeCliInvoiceExtractor.FromPhotosJson(json); inv.Lines[0].Note.Should().Be("сверьте вес"); } }