[Add] MasterData Services.
This commit is contained in:
@@ -7,6 +7,7 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="ClosedXML" Version="0.105.0" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="9.0.6"/>
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="9.0.9" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="9.0.9">
|
||||
|
||||
187
AMREZ.EOP.API/Controllers/DataController.cs
Normal file
187
AMREZ.EOP.API/Controllers/DataController.cs
Normal file
@@ -0,0 +1,187 @@
|
||||
using AMREZ.EOP.Abstractions.Applications.UseCases.ImportData.Location;
|
||||
using AMREZ.EOP.Contracts.DTOs.ImportData.Location;
|
||||
using AMREZ.EOP.Domain.Shared.Data;
|
||||
using ClosedXML.Excel;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace AMREZ.EOP.API.Controllers;
|
||||
|
||||
public class AddressTemplateRow
|
||||
{
|
||||
public string CustomerName { get; set; } = ""; // ชื่อ
|
||||
public string Phone { get; set; } = ""; // เบอร์โทร
|
||||
public string Address { get; set; } = ""; // ที่อยู่ (เลขที่/หมู่/ซอย/ถนน ฯลฯ)
|
||||
public string Subdistrict { get; set; } = ""; // ตำบล
|
||||
public string District { get; set; } = ""; // อำเภอ
|
||||
public string Province { get; set; } = ""; // จังหวัด
|
||||
public string PostalCode { get; set; } = ""; // รหัสไปรษณีย์
|
||||
|
||||
public string? ProductCode { get; set; } // เผื่อใช้ต่อ
|
||||
public string? ProductName { get; set; }
|
||||
public int? Quantity { get; set; }
|
||||
}
|
||||
|
||||
[ApiController]
|
||||
[Route("api/[controller]")]
|
||||
public class DataController : ControllerBase
|
||||
{
|
||||
private readonly ILocationImportUseCase _locationImportUseCase;
|
||||
|
||||
public DataController(ILocationImportUseCase locationImportUseCase)
|
||||
{
|
||||
_locationImportUseCase = locationImportUseCase;
|
||||
}
|
||||
|
||||
// เซ็ต Fixed สินค้า 3 รายการตามตัวอย่าง
|
||||
private static readonly (string Code, string Name, decimal Price)[] FixedProducts =
|
||||
{
|
||||
("900-000-01-01", "LAVIESTE (DIETARY SUPPLEMENT PRODUCT) KATHY LABZ BRAND", 1590m),
|
||||
("900-000-01-02", "KARISTA (DIETARY SUPPLEMENT PRODUCT) KATHY LABZ BRAND", 1590m),
|
||||
("890-001-00-01", "KATHY LABZ AUTO STIRRING", 390m)
|
||||
};
|
||||
|
||||
[HttpPost("address-parse")]
|
||||
public async Task<IActionResult> ThaiParseAddress([FromForm(Name = "Image")] IFormFile? Image)
|
||||
{
|
||||
if (Image == null || Image.Length == 0)
|
||||
return BadRequest("กรุณาอัปโหลดไฟล์ Excel (.xlsx) ที่เป็น 'ข้อมูลจริง ครั้งที่1'");
|
||||
|
||||
using var stream = new MemoryStream();
|
||||
await Image.CopyToAsync(stream);
|
||||
stream.Position = 0;
|
||||
|
||||
using var wb = new XLWorkbook(stream);
|
||||
var ws = wb.Worksheets.First();
|
||||
|
||||
// row1 = header => "username", "Address"
|
||||
var lastRow = ws.LastRowUsed().RowNumber();
|
||||
|
||||
var rows = new List<AddressTemplateRow>();
|
||||
|
||||
for (int row = 2; row <= lastRow; row++)
|
||||
{
|
||||
var username = ws.Cell(row, 1).GetString().Trim(); // "username"
|
||||
var rawAddress = ws.Cell(row, 2).GetString().Trim(); // "Address"
|
||||
|
||||
if (string.IsNullOrWhiteSpace(username) && string.IsNullOrWhiteSpace(rawAddress))
|
||||
continue;
|
||||
|
||||
var parsed = ThaiAddressParser.Parse(rawAddress);
|
||||
|
||||
rows.Add(new AddressTemplateRow
|
||||
{
|
||||
CustomerName = string.IsNullOrWhiteSpace(parsed.Name)
|
||||
? username
|
||||
: parsed.Name,
|
||||
Phone = parsed.Phone,
|
||||
Address = parsed.AddressMain,
|
||||
Subdistrict = parsed.Subdistrict,
|
||||
District = parsed.District,
|
||||
Province = parsed.Province,
|
||||
PostalCode = parsed.PostalCode
|
||||
});
|
||||
}
|
||||
|
||||
// ================== สร้างไฟล์ Excel ตาม Template ==================
|
||||
using var outWb = new XLWorkbook();
|
||||
|
||||
var outWs = outWb.Worksheets.Add("template");
|
||||
|
||||
// Header แถวที่ 1 ให้ตรงกับไฟล์ตัวอย่าง
|
||||
outWs.Cell(1, 1).Value = "สถานะออเดอร์";
|
||||
outWs.Cell(1, 2).Value = "สถานะการชำระเงิน";
|
||||
outWs.Cell(1, 3).Value = "รหัสพนักงานขาย";
|
||||
outWs.Cell(1, 4).Value = "รหัสช่องทางการขาย";
|
||||
outWs.Cell(1, 5).Value = "ช่องทางการชำระเงิน";
|
||||
outWs.Cell(1, 6).Value = "กำหนดส่งสินค้า";
|
||||
outWs.Cell(1, 7).Value = "Order No";
|
||||
outWs.Cell(1, 8).Value = "ชื่อขนส่ง";
|
||||
outWs.Cell(1, 9).Value = "ชื่อ";
|
||||
outWs.Cell(1, 10).Value = "เบอร์โทร";
|
||||
outWs.Cell(1, 11).Value = "E-mail";
|
||||
outWs.Cell(1, 12).Value = "Line";
|
||||
outWs.Cell(1, 13).Value = "Facebook";
|
||||
outWs.Cell(1, 14).Value = "IG";
|
||||
outWs.Cell(1, 15).Value = "หมายเหตุ";
|
||||
outWs.Cell(1, 16).Value = "ที่อยู่";
|
||||
outWs.Cell(1, 17).Value = "ตำบล";
|
||||
outWs.Cell(1, 18).Value = "อำเภอ";
|
||||
outWs.Cell(1, 19).Value = "จังหวัด";
|
||||
outWs.Cell(1, 20).Value = "รหัสไปรษณีย์";
|
||||
outWs.Cell(1, 21).Value = "รหัสสินค้า/รหัสโปรโมชั่น (ตายตัว";
|
||||
outWs.Cell(1, 22).Value = "ชื่อสินค้า/ชื่อโปรโมชั่น (ตายตัว)";
|
||||
outWs.Cell(1, 23).Value = "ราคา/ชิ้น";
|
||||
outWs.Cell(1, 24).Value = "จำนวน";
|
||||
outWs.Cell(1, 25).Value = "ส่วนลด";
|
||||
outWs.Cell(1, 26).Value = "ราคารวมสินค้า";
|
||||
outWs.Cell(1, 27).Value = "ค่าขนส่ง";
|
||||
outWs.Cell(1, 28).Value = "ส่วนลดท้ายบิล";
|
||||
outWs.Cell(1, 29).Value = "ราคารวมออเดอร์";
|
||||
outWs.Cell(1, 30).Value = "Tracking No.";
|
||||
outWs.Cell(1, 31).Value = "วันอนุมัติ";
|
||||
|
||||
var outRow = 2;
|
||||
|
||||
foreach (var r in rows)
|
||||
{
|
||||
// 1 ลูกค้า → 3 แถวสินค้า fix
|
||||
foreach (var p in FixedProducts)
|
||||
{
|
||||
// ข้อมูลลูกค้า
|
||||
outWs.Cell(outRow, 9).Value = r.CustomerName ?? "";
|
||||
outWs.Cell(outRow, 10).Value = r.Phone ?? "";
|
||||
outWs.Cell(outRow, 16).Value = r.Address ?? "";
|
||||
outWs.Cell(outRow, 17).Value = r.Subdistrict ?? "";
|
||||
outWs.Cell(outRow, 18).Value = r.District ?? "";
|
||||
outWs.Cell(outRow, 19).Value = r.Province ?? "";
|
||||
outWs.Cell(outRow, 20).Value = r.PostalCode ?? "";
|
||||
|
||||
// สินค้า
|
||||
outWs.Cell(outRow, 21).Value = p.Code; // รหัสสินค้า
|
||||
outWs.Cell(outRow, 22).Value = p.Name; // ชื่อสินค้า hard-coded
|
||||
outWs.Cell(outRow, 23).Value = p.Price; // ราคา/ชิ้น
|
||||
outWs.Cell(outRow, 24).Value = 1; // จำนวน = 1
|
||||
|
||||
// ส่วนลด/รวม/ค่าขนส่ง/ส่วนลดท้ายบิล/ราคารวมออเดอร์ ปล่อยว่าง
|
||||
// คอลัมน์ 25–31 ไม่เซ็ตอะไร
|
||||
|
||||
outRow++;
|
||||
}
|
||||
}
|
||||
|
||||
outWs.Columns(1, 31).AdjustToContents();
|
||||
|
||||
using var outStream = new MemoryStream();
|
||||
outWb.SaveAs(outStream);
|
||||
outStream.Position = 0;
|
||||
|
||||
var fileName = $"import_SO_template_{DateTime.Now:yyyyMMddHHmmss}.xlsx";
|
||||
|
||||
return File(
|
||||
outStream.ToArray(),
|
||||
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
|
||||
fileName
|
||||
);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Import ตารางจังหวัด / อำเภอ / ตำบล จากไฟล์ Excel (กรมการปกครอง)
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// ส่งไฟล์ .xlsx ผ่าน multipart/form-data, field name = "file"
|
||||
/// </remarks>
|
||||
[HttpPost("import-th-location")]
|
||||
[Consumes("multipart/form-data")]
|
||||
[ProducesResponseType(typeof(LocationImportResultDto), StatusCodes.Status200OK)]
|
||||
[ProducesResponseType(StatusCodes.Status400BadRequest)]
|
||||
public async Task<IActionResult> ImportLocations(
|
||||
[FromForm(Name = "file")] IFormFile? file,
|
||||
CancellationToken ct)
|
||||
{
|
||||
if (file == null || file.Length == 0)
|
||||
return BadRequest("กรุณาอัปโหลดไฟล์ Excel (.xlsx) รหัสจังหวัด/อำเภอ/ตำบล");
|
||||
|
||||
var result = await _locationImportUseCase.ExecuteAsync(file, ct);
|
||||
return Ok(result);
|
||||
}
|
||||
}
|
||||
59
AMREZ.EOP.API/Controllers/MasterData/BrandsController.cs
Normal file
59
AMREZ.EOP.API/Controllers/MasterData/BrandsController.cs
Normal file
@@ -0,0 +1,59 @@
|
||||
using AMREZ.EOP.Abstractions.Applications.UseCases.MasterData.Brand;
|
||||
using AMREZ.EOP.Contracts.DTOs.Common;
|
||||
using AMREZ.EOP.Contracts.DTOs.MasterData.Brand;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace AMREZ.EOP.API.Controllers.MasterData;
|
||||
|
||||
[ApiController]
|
||||
[Route("api/master/brands")]
|
||||
public sealed class BrandsController : ControllerBase
|
||||
{
|
||||
private readonly IListBrandsUseCase _list;
|
||||
private readonly IGetBrandUseCase _get;
|
||||
private readonly ICreateBrandUseCase _create;
|
||||
private readonly IUpdateBrandUseCase _update;
|
||||
private readonly IDeleteBrandUseCase _delete;
|
||||
|
||||
public BrandsController(
|
||||
IListBrandsUseCase list,
|
||||
IGetBrandUseCase get,
|
||||
ICreateBrandUseCase create,
|
||||
IUpdateBrandUseCase update,
|
||||
IDeleteBrandUseCase delete)
|
||||
{
|
||||
_list = list; _get = get; _create = create; _update = update; _delete = delete;
|
||||
}
|
||||
|
||||
[HttpGet]
|
||||
public async Task<ActionResult<PagedResponse<BrandResponse>>> List([FromQuery] BrandListRequest query, CancellationToken ct)
|
||||
=> Ok(await _list.ExecuteAsync(query, ct));
|
||||
|
||||
[HttpGet("{id:guid}")]
|
||||
public async Task<IActionResult> Get(Guid id, CancellationToken ct)
|
||||
{
|
||||
var res = await _get.ExecuteAsync(id, ct);
|
||||
return res is null ? NotFound() : Ok(res);
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
public async Task<IActionResult> Create([FromBody] BrandCreateRequest body, CancellationToken ct)
|
||||
{
|
||||
var res = await _create.ExecuteAsync(body, ct);
|
||||
return CreatedAtAction(nameof(Get), new { id = res.Id }, res);
|
||||
}
|
||||
|
||||
[HttpPut("{id:guid}")]
|
||||
public async Task<IActionResult> Update(Guid id, [FromBody] BrandUpdateRequest body, CancellationToken ct)
|
||||
{
|
||||
var res = await _update.ExecuteAsync(id, body, ct);
|
||||
return res is null ? NotFound() : Ok(res);
|
||||
}
|
||||
|
||||
[HttpDelete("{id:guid}")]
|
||||
public async Task<IActionResult> Delete(Guid id, CancellationToken ct)
|
||||
{
|
||||
var ok = await _delete.ExecuteAsync(id, ct);
|
||||
return ok ? NoContent() : NotFound();
|
||||
}
|
||||
}
|
||||
@@ -28,13 +28,13 @@ public class SCBController : ControllerBase
|
||||
{
|
||||
if (Image is null || Image.Length == 0)
|
||||
return BadRequest(new { message = "Missing slip image" });
|
||||
|
||||
|
||||
var res = await _verifyFromImage.ExecuteAsync(new VerifyFromImageRequest
|
||||
{
|
||||
Image = Image,
|
||||
OverrideSendingBank = OverrideSendingBank
|
||||
}, ct);
|
||||
|
||||
|
||||
if (res is null) return NotFound(new { message = "Cannot extract transRef or verification failed" });
|
||||
return Ok(res);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user