eSPJ/Controllers/SpjDriverUpstController/DetailController.cs

247 lines
9.0 KiB
C#

using Microsoft.AspNetCore.Mvc;
using System.Globalization;
using System.Text;
using System.Text.Json;
using System.Text.RegularExpressions;
using eSPJ.Models;
using eSPJ.Services;
namespace eSPJ.Controllers.SpjDriverUpstController
{
[Route("upst/detail-penjemputan")]
public class DetailPenjemputanController : Controller
{
private readonly IHttpClientFactory _httpClientFactory;
private readonly IConfiguration _configuration;
private readonly DetailPenjemputanService _detailService;
private readonly ILogger<DetailPenjemputanController> _logger;
public DetailPenjemputanController(
IHttpClientFactory httpClientFactory,
IConfiguration configuration,
DetailPenjemputanService detailService,
ILogger<DetailPenjemputanController> logger)
{
_httpClientFactory = httpClientFactory;
_configuration = configuration;
_detailService = detailService;
_logger = logger;
}
[HttpGet("")]
public IActionResult Index()
{
return View("~/Views/Admin/Transport/SpjDriverUpst/DetailPenjemputan/Index.cshtml");
}
[HttpGet("tanpa-tps")]
public IActionResult TanpaTps()
{
return View("~/Views/Admin/Transport/SpjDriverUpst/DetailPenjemputan/TanpaTps.cshtml");
}
[HttpGet("batal")]
public IActionResult Batal()
{
return View("~/Views/Admin/Transport/SpjDriverUpst/DetailPenjemputan/Batal.cshtml");
}
[HttpPost("")]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Submit([FromForm] DetailPenjemputanRequest request)
{
try
{
var result = await _detailService.SubmitPenjemputanAsync(request);
if (result.Success)
{
TempData["Success"] = result.Message;
}
else
{
TempData["Error"] = result.Message;
}
return RedirectToAction(nameof(Index));
}
catch (Exception ex)
{
_logger.LogError(ex, "Error submitting penjemputan data");
TempData["Error"] = "Terjadi kesalahan saat menyimpan data.";
return RedirectToAction(nameof(Index));
}
}
[HttpPost("ocr-timbangan")]
[IgnoreAntiforgeryToken]
public async Task<IActionResult> OcrTimbangan(IFormFile? Foto)
{
if (Foto == null || Foto.Length == 0)
{
return BadRequest(new { success = false, message = "Foto tidak ditemukan." });
}
if (Foto.Length > 5 * 1024 * 1024)
{
return BadRequest(new { success = false, message = "Ukuran foto terlalu besar. Maksimal 5MB." });
}
var apiKey = _configuration["OpenRouter:OCRkey"];
if (string.IsNullOrWhiteSpace(apiKey))
{
return StatusCode(500, new { success = false, message = "OpenRouter API key belum diset." });
}
byte[] fileBytes;
await using (var ms = new MemoryStream())
{
await Foto.CopyToAsync(ms);
fileBytes = ms.ToArray();
}
var mimeType = string.IsNullOrWhiteSpace(Foto.ContentType) ? "image/jpeg" : Foto.ContentType;
var base64 = Convert.ToBase64String(fileBytes);
var dataUrl = $"data:{mimeType};base64,{base64}";
var payload = new
{
// model = "nvidia/nemotron-nano-12b-v2-vl:free",
model = "google/gemini-2.5-flash-image",
// model = "google/gemini-2.5-flash-lite",
// model = "google/gemini-2.5-flash-lite-preview-09-2025",
temperature = 0,
messages = new object[]
{
new
{
role = "user",
content = new object[]
{
new
{
type = "text",
text = @"
Baca angka berat timbangan digital pada foto.
Rules:
- Abaikan tulisan seperti ZERO, TARE, STABLE, AC, PACK, PCS, KG, ADD, HOLD.
- Jawab hanya angka dengan format 2 digit desimal pakai titik (contoh: 54.45).
- Jika tidak terbaca jawab: UNREADABLE
- Fokus pada angka layar LED merah yang menyala.
Saya berikan 3 contoh foto timbangan yang benar:
Foto 1 = 75.23
Foto 2 = 79.86
Foto 3 = 54.45
Sekarang baca angka pada foto terakhir."
},
new
{
type = "image_url",
image_url = new { url = "https://res.cloudinary.com/drejcprhe/image/upload/v1770888384/Notes_-_2026-02-11_08.52.31_wonhbm.jpg" }
},
new
{
type = "image_url",
image_url = new { url = "https://res.cloudinary.com/drejcprhe/image/upload/v1770888429/Notes_-_2026-02-11_08.52.34_xairzy.jpg" }
},
new
{
type = "image_url",
image_url = new { url = "https://res.cloudinary.com/drejcprhe/image/upload/v1770888473/ChatGPT_Image_Feb_11_2026_03_00_33_PM_ujhdlw.png" }
},
new
{
type = "image_url",
image_url = new { url = dataUrl }
}
}
}
}
};
var json = JsonSerializer.Serialize(payload);
var request = new HttpRequestMessage(HttpMethod.Post, "https://openrouter.ai/api/v1/chat/completions");
request.Headers.TryAddWithoutValidation("Authorization", $"Bearer {apiKey}");
request.Headers.TryAddWithoutValidation("Accept", "application/json");
request.Headers.TryAddWithoutValidation("HTTP-Referer", "https://yourdomain.com");
request.Headers.TryAddWithoutValidation("X-Title", "eSPJ OCR Timbangan");
request.Content = new StringContent(json, Encoding.UTF8, "application/json");
var client = _httpClientFactory.CreateClient();
using var response = await client.SendAsync(request);
var responseText = await response.Content.ReadAsStringAsync();
if (!response.IsSuccessStatusCode)
{
return StatusCode((int)response.StatusCode, new
{
success = false,
message = "OpenRouter request gagal.",
detail = responseText
});
}
using var doc = JsonDocument.Parse(responseText);
var content = doc.RootElement
.GetProperty("choices")[0]
.GetProperty("message")
.GetProperty("content")
.GetString() ?? "";
content = content.Trim();
if (content.Contains("UNREADABLE", StringComparison.OrdinalIgnoreCase))
{
return Ok(new
{
success = false,
message = "Angka tidak terbaca.",
raw = content
});
}
// cari format angka 2 desimal
var match = Regex.Match(content, @"-?\d{1,5}([.,]\d{2})");
if (!match.Success)
{
return Ok(new
{
success = false,
message = "AI tidak menemukan angka valid.",
raw = content
});
}
var normalized = match.Value.Replace(',', '.');
if (!decimal.TryParse(normalized, NumberStyles.Any, CultureInfo.InvariantCulture, out var weight))
{
return Ok(new
{
success = false,
message = "Format angka AI tidak valid.",
raw = content
});
}
return Ok(new
{
success = true,
weight = weight.ToString("0.00", CultureInfo.InvariantCulture),
raw = content
});
}
}
}