1271 lines
50 KiB
C#
1271 lines
50 KiB
C#
using System;
|
||
using System.Collections.Generic;
|
||
using System.Linq;
|
||
using System.Net;
|
||
using System.Net.Http;
|
||
using System.Web.Http;
|
||
using PagedList;
|
||
using Newtonsoft.Json;
|
||
using System.Collections;
|
||
using MyWeb;
|
||
using System.Web.WebPages;
|
||
using System.Data.Entity;
|
||
|
||
[ezAuthorize]
|
||
public class transfer_registerController : ApiController
|
||
{
|
||
private Model.ezEntities _db = new Model.ezEntities();
|
||
|
||
// GET api/transfer_register
|
||
public IEnumerable<Model.transfer_register> Get()
|
||
{
|
||
var list = _db.transfer_register.ToList();
|
||
if (list == null) throw new HttpResponseException(HttpStatusCode.NotFound);
|
||
return list;
|
||
}
|
||
|
||
// GET api/transfer_register?page=1&pageSize=10
|
||
public IEnumerable<Model.transfer_register> Get(int page, int pageSize = 10,
|
||
string sortBy = "", bool sortDesc = false)
|
||
{
|
||
var list = _db.transfer_register.OrderBy(o => o.id).ToPagedList(page, pageSize);
|
||
if (list == null) throw new HttpResponseException(HttpStatusCode.NotFound);
|
||
return list;
|
||
}
|
||
|
||
// GET api/transfer_register/5
|
||
public Model.transfer_register Get(int id)
|
||
{
|
||
var item = _db.transfer_register.Where(q => q.id == id).FirstOrDefault();
|
||
if (item == null) throw new HttpResponseException(HttpStatusCode.NotFound);
|
||
return item;
|
||
}
|
||
|
||
// POST api/transfer_register
|
||
[HttpPost]
|
||
public IHttpActionResult Post()
|
||
{
|
||
try
|
||
{
|
||
var request = System.Web.HttpContext.Current.Request;
|
||
var item = new Model.transfer_register();
|
||
|
||
item.activity_num = Convert.ToInt32(request.Form["activity_num"]);
|
||
item.name = request.Form["name"];
|
||
item.phone = request.Form["phone"];
|
||
item.pay_type = request.Form["pay_type"];
|
||
item.account_last5 = request.Form["account_last5"];
|
||
item.amount = Convert.ToDecimal(request.Form["amount"]);
|
||
item.pay_mode = request.Form["pay_mode"];
|
||
item.note = request.Form["note"];
|
||
item.draft = request.Form["draft"];
|
||
item.create_time = DateTime.Now;
|
||
|
||
// 查詢 followers
|
||
var follower = _db.followers
|
||
//.FirstOrDefault(f => f.u_name == item.name && f.phone == item.phone);
|
||
.FirstOrDefault(f => f.u_name == item.name);
|
||
//先檢查姓名就好, 電話有加密, 待處理
|
||
//若有同名, 先全抓, 解密, 再比對電話或手機
|
||
|
||
if (follower != null)
|
||
{
|
||
item.f_num = follower.num;
|
||
}
|
||
|
||
// 檔案處理,只允許 JPG, PDF
|
||
if (request.Files.Count > 0)
|
||
{
|
||
var file = request.Files[0];
|
||
var ext = System.IO.Path.GetExtension(file.FileName).ToLower();
|
||
if (ext != ".jpg" && ext != ".jpeg" && ext != ".pdf")
|
||
{
|
||
return BadRequest("只允許上傳 JPG 或 PDF 檔案");
|
||
}
|
||
var fileName = Guid.NewGuid().ToString("N") + ext;
|
||
var savePath = System.Web.HttpContext.Current.Server.MapPath("~/upload/transfer_proof/");
|
||
if (!System.IO.Directory.Exists(savePath))
|
||
System.IO.Directory.CreateDirectory(savePath);
|
||
file.SaveAs(System.IO.Path.Combine(savePath, fileName));
|
||
item.proof_img = fileName;
|
||
}
|
||
|
||
_db.transfer_register.Add(item);
|
||
_db.SaveChanges();
|
||
|
||
return CreatedAtRoute("DefaultApi", new { id = item.id }, item);
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
return InternalServerError(ex);
|
||
}
|
||
}
|
||
|
||
// PUT api/transfer_register/5
|
||
public IHttpActionResult Put(int id, [FromBody] Model.transfer_register item)
|
||
{
|
||
if (item == null || id != item.id)
|
||
return BadRequest("Invalid data");
|
||
|
||
try
|
||
{
|
||
var existingItem = _db.transfer_register.Where(q => q.id == id).FirstOrDefault();
|
||
if (existingItem == null)
|
||
return NotFound();
|
||
|
||
// 更新欄位
|
||
existingItem.activity_num = item.activity_num;
|
||
existingItem.name = item.name;
|
||
existingItem.phone = item.phone;
|
||
existingItem.pay_type = item.pay_type;
|
||
existingItem.account_last5 = item.account_last5;
|
||
existingItem.amount = item.amount;
|
||
existingItem.pay_mode = item.pay_mode;
|
||
existingItem.note = item.note;
|
||
existingItem.proof_img = item.proof_img;
|
||
existingItem.status = item.status;
|
||
existingItem.f_num_match = item.f_num_match;
|
||
existingItem.f_num = item.f_num;
|
||
existingItem.acc_num = item.acc_num;
|
||
existingItem.check_date = item.check_date;
|
||
existingItem.check_amount = item.check_amount;
|
||
existingItem.check_memo = item.check_memo;
|
||
existingItem.check_status = item.check_status;
|
||
existingItem.acc_kind = item.acc_kind;
|
||
existingItem.member_num = item.member_num;
|
||
existingItem.verify_time = item.verify_time;
|
||
existingItem.verify_note = item.verify_note;
|
||
existingItem.draft = item.draft;
|
||
|
||
_db.SaveChanges();
|
||
|
||
// 記錄操作日誌
|
||
Model.admin_log admin_log = new Model.admin_log();
|
||
MyWeb.admin admin = new MyWeb.admin();
|
||
if (admin.isLoign())
|
||
{
|
||
admin_log.writeLog(admin.info.u_id, (int)Model.admin_log.Systems.Accounting,
|
||
(int)Model.admin_log.Status.Update,
|
||
$"更新匯款登記: {item.name} {item.amount}");
|
||
}
|
||
|
||
return Ok();
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
return InternalServerError(ex);
|
||
}
|
||
}
|
||
|
||
// DELETE api/transfer_register/5
|
||
public IHttpActionResult Delete(int id)
|
||
{
|
||
try
|
||
{
|
||
var item = _db.transfer_register.Where(q => q.id == id).FirstOrDefault();
|
||
if (item == null)
|
||
return NotFound();
|
||
|
||
_db.transfer_register.Remove(item);
|
||
_db.SaveChanges();
|
||
|
||
// 記錄操作日誌
|
||
Model.admin_log admin_log = new Model.admin_log();
|
||
MyWeb.admin admin = new MyWeb.admin();
|
||
if (admin.isLoign())
|
||
{
|
||
admin_log.writeLog(admin.info.u_id, (int)Model.admin_log.Systems.Accounting,
|
||
(int)Model.admin_log.Status.Delete,
|
||
$"刪除匯款登記: {item.name} {item.amount}");
|
||
}
|
||
|
||
return Ok();
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
return InternalServerError(ex);
|
||
}
|
||
}
|
||
|
||
// GET api/transfer_register/count
|
||
[HttpGet]
|
||
[Route("api/transfer_register/count")]
|
||
public int Count()
|
||
{
|
||
return _db.transfer_register.Count();
|
||
}
|
||
|
||
// GET api/transfer_register/pending
|
||
[HttpGet]
|
||
[Route("api/transfer_register/pending")]
|
||
public IHttpActionResult GetPending()
|
||
{
|
||
var encrypt = new MyWeb.encrypt();
|
||
|
||
var list = _db.transfer_register
|
||
.Where(x => (
|
||
x.status == null ||
|
||
x.status == "" ||
|
||
x.status == ((int)Model.transfer_register.Status.Pending).ToString()
|
||
) && (
|
||
x.check_status == null ||
|
||
x.check_status == "" ||
|
||
x.check_status == ((int)Model.transfer_register.CheckStatus.Unchecked).ToString()
|
||
))
|
||
.ToList()
|
||
.Select(x => new
|
||
{
|
||
x.id,
|
||
x.activity_num,
|
||
x.name,
|
||
x.phone,
|
||
x.f_num,
|
||
x.pay_type,
|
||
x.amount,
|
||
x.account_last5,
|
||
x.pay_mode,
|
||
x.status,
|
||
x.note,
|
||
x.proof_img,
|
||
x.create_time,
|
||
x.check_memo,
|
||
x.check_status,
|
||
x.verify_note,
|
||
x.acc_num,
|
||
x.check_date,
|
||
x.check_amount,
|
||
x.draft,
|
||
follower = x.f_num != null ? _db.followers
|
||
.Where(f => f.num == x.f_num)
|
||
.AsEnumerable()
|
||
.Select(f => new {
|
||
f.num,
|
||
f.u_name,
|
||
phone = encrypt.DecryptAutoKey(f.phone),
|
||
cellphone = encrypt.DecryptAutoKey(f.cellphone)
|
||
}).FirstOrDefault() : null
|
||
})
|
||
.ToList();
|
||
/*
|
||
f_num_match, acc_num, check_date, check_amount,
|
||
acc_kind, member_num, verify_time,
|
||
*/
|
||
|
||
return Ok(list);
|
||
}
|
||
|
||
public class transfer_register_update_dto
|
||
{
|
||
public int id { get; set; }
|
||
public int? f_num { get; set; }
|
||
public string status { get; set; }
|
||
public string check_status { get; set; }
|
||
public string verify_note { get; set; }
|
||
public int? acc_num { get; set; }
|
||
public DateTime? check_date { get; set; }
|
||
public decimal? check_amount { get; set; }
|
||
public string check_memo { get; set; }
|
||
public string draft { get; set; }
|
||
public int? acc_kind { get; set; } // 新增關聯欄位
|
||
}
|
||
|
||
[HttpPost]
|
||
[Route("api/transfer_register/batch_update")]
|
||
public IHttpActionResult BatchUpdate(List<transfer_register_update_dto> list)
|
||
{
|
||
try
|
||
{
|
||
foreach (var dto in list)
|
||
{
|
||
var item = _db.transfer_register.Find(dto.id);
|
||
if (item != null)
|
||
{
|
||
// 如果狀態改為核對(2)且還沒有會計記錄,則新增會計記錄
|
||
if (dto.check_status == "2" && item.acc_kind == null)
|
||
{
|
||
// 取得活動名稱
|
||
string activityName = "";
|
||
if (item.activity_num.HasValue)
|
||
{
|
||
var activity = _db.activities.FirstOrDefault(a => a.num == item.activity_num.Value);
|
||
activityName = activity?.subject ?? "";
|
||
}
|
||
|
||
// 取得信眾資訊
|
||
string followerName = "";
|
||
string followerPhone = "";
|
||
if (item.f_num.HasValue)
|
||
{
|
||
var follower = _db.followers.FirstOrDefault(f => f.num == item.f_num.Value);
|
||
if (follower != null)
|
||
{
|
||
followerName = follower.u_name ?? "";
|
||
var encrypt = new MyWeb.encrypt();
|
||
followerPhone = encrypt.DecryptAutoKey(follower.phone) ?? encrypt.DecryptAutoKey(follower.cellphone) ?? "";
|
||
}
|
||
}
|
||
|
||
// 組合 demo 欄位
|
||
string demo = $"法會:{activityName}\n姓名:{followerName}\n電話:{followerPhone}";
|
||
|
||
// 新增會計記錄
|
||
var accounting = new Model.accounting
|
||
{
|
||
uptime = dto.check_date,
|
||
category = 1, // 收入
|
||
kind = 27, // 固定值:法會收入/功德項目
|
||
kind2 = dto.acc_num,
|
||
price = (float)(dto.check_amount ?? 0),
|
||
tax = 0,
|
||
demo = demo,
|
||
excerpt = dto.check_memo,
|
||
activity_num = item.activity_num,
|
||
reg_time = DateTime.Now,
|
||
mem_num = null, // 不設定 mem_num,避免外鍵約束衝突
|
||
debtor = item.name,
|
||
pro_order_detail_num = null
|
||
};
|
||
|
||
_db.accountings.Add(accounting);
|
||
_db.SaveChanges(); // 先儲存以取得 accounting.num
|
||
|
||
// 設定關聯
|
||
dto.acc_kind = accounting.num;
|
||
}
|
||
|
||
// 更新 transfer_register 記錄
|
||
item.f_num = dto.f_num;
|
||
item.status = dto.status;
|
||
item.check_status = dto.check_status;
|
||
item.verify_note = dto.verify_note;
|
||
item.acc_num = dto.acc_num;
|
||
item.check_date = dto.check_date;
|
||
item.check_amount = dto.check_amount;
|
||
item.check_memo = dto.check_memo;
|
||
item.draft = dto.draft;
|
||
item.acc_kind = dto.acc_kind;
|
||
}
|
||
}
|
||
_db.SaveChanges();
|
||
return Ok(new { success = true });
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
return InternalServerError(ex);
|
||
}
|
||
}
|
||
|
||
// GET api/transfer_register/personal_reconcile_list
|
||
[HttpGet]
|
||
[Route("api/transfer_register/personal_reconcile_list")]
|
||
public IHttpActionResult GetPersonalReconcileList()
|
||
{
|
||
var list = _db.transfer_register
|
||
.Where(tr =>
|
||
tr.status == "2" &&
|
||
tr.check_status == "2" &&
|
||
tr.pay_mode == "個人"
|
||
)
|
||
.Select(tr => new
|
||
{
|
||
tr.id,
|
||
tr.f_num,
|
||
follower = tr.follower != null ? tr.follower.u_name : "",
|
||
tr.acc_num,
|
||
acc_name = tr.acc_num != null ? _db.accounting_kind2.Where(a => a.num == tr.acc_num).Select(a => a.kind).FirstOrDefault() : "",
|
||
tr.check_date,
|
||
tr.check_amount,
|
||
tr.check_memo,
|
||
tr.check_status,
|
||
tr.verify_note,
|
||
tr.activity_num,
|
||
tr.name,
|
||
tr.phone,
|
||
tr.pay_type,
|
||
tr.account_last5,
|
||
tr.pay_mode,
|
||
tr.status,
|
||
tr.note,
|
||
tr.proof_img,
|
||
tr.create_time,
|
||
tr.draft
|
||
})
|
||
.ToList();
|
||
return Ok(list);
|
||
}
|
||
|
||
// GET api/transfer_register/follower_orders?f_num=123
|
||
[HttpGet]
|
||
[Route("api/transfer_register/follower_orders")]
|
||
public IHttpActionResult GetFollowerOrders(int f_num)
|
||
{
|
||
// 取得該信眾的所有訂單及明細,並關聯活動名稱與品項名稱
|
||
var details = _db.pro_order
|
||
.Where(o => o.f_num == f_num)
|
||
.SelectMany(o => o.pro_order_detail.Select(d => new {
|
||
o.order_no,
|
||
o.activity_num,
|
||
activity_name = o.activity != null ? o.activity.subject : "",
|
||
d.num,
|
||
d.actItem_num,
|
||
actitem_name = d.actItem != null ? d.actItem.subject : "",
|
||
price = d.price,
|
||
paid = d.pro_order_record.Select(r => r.price).DefaultIfEmpty(0).Sum(),
|
||
d.pay,
|
||
d.pay_date,
|
||
d.due_date,
|
||
d.demo,
|
||
reg_time = o.reg_time // 報名日期
|
||
}))
|
||
.AsEnumerable()
|
||
.Select(x => new {
|
||
x.order_no,
|
||
x.activity_num,
|
||
x.activity_name,
|
||
x.num,
|
||
x.actItem_num,
|
||
x.actitem_name,
|
||
price = (decimal?)x.price,
|
||
paid = (decimal?)x.paid,
|
||
due = ((decimal?)x.price ?? 0) - ((decimal?)x.paid ?? 0),
|
||
x.pay,
|
||
x.pay_date,
|
||
x.due_date,
|
||
x.demo,
|
||
x.reg_time
|
||
})
|
||
.Where(x => Math.Round(x.due, 2) > 0)
|
||
.OrderBy(x => x.reg_time)
|
||
.ToList();
|
||
return Ok(details);
|
||
}
|
||
|
||
[HttpGet]
|
||
[Route("api/transfer_register/step2_list")]
|
||
public IHttpActionResult GetStep2List()
|
||
{
|
||
var encrypt = new MyWeb.encrypt();
|
||
var list = _db.transfer_register
|
||
.Where(x =>
|
||
x.status == ((int)Model.transfer_register.Status.Confirmed).ToString() &&
|
||
(
|
||
x.check_status == null ||
|
||
x.check_status == "" ||
|
||
x.check_status == ((int)Model.transfer_register.CheckStatus.Unchecked).ToString() ||
|
||
x.check_status == ((int)Model.transfer_register.CheckStatus.AmountMismatch).ToString() ||
|
||
x.check_status == ((int)Model.transfer_register.CheckStatus.OtherIssue).ToString()
|
||
)
|
||
)
|
||
.ToList()
|
||
.Select(x => new
|
||
{
|
||
x.id,
|
||
x.activity_num,
|
||
x.name,
|
||
x.phone,
|
||
x.f_num,
|
||
x.pay_type,
|
||
x.amount,
|
||
x.account_last5,
|
||
x.pay_mode,
|
||
x.status,
|
||
x.note,
|
||
x.proof_img,
|
||
x.create_time,
|
||
x.check_memo,
|
||
x.check_status,
|
||
x.verify_note,
|
||
x.acc_num,
|
||
x.check_date,
|
||
x.check_amount,
|
||
x.draft,
|
||
follower = x.f_num != null ? _db.followers
|
||
.Where(f => f.num == x.f_num)
|
||
.AsEnumerable()
|
||
.Select(f => new {
|
||
f.num,
|
||
f.u_name,
|
||
phone = encrypt.DecryptAutoKey(f.phone),
|
||
cellphone = encrypt.DecryptAutoKey(f.cellphone)
|
||
}).FirstOrDefault() : null
|
||
})
|
||
.ToList();
|
||
return Ok(list);
|
||
}
|
||
|
||
public class ReconcileDetail
|
||
{
|
||
public int pro_order_detail_num { get; set; }
|
||
public decimal amount { get; set; }
|
||
public int? acc_num { get; set; } // 帳戶
|
||
public DateTime? reg_time { get; set; } // 日期
|
||
}
|
||
|
||
public class ReconcileRequest
|
||
{
|
||
public int transfer_register_id { get; set; }
|
||
public List<ReconcileDetail> details { get; set; }
|
||
public decimal over_payment { get; set; }
|
||
}
|
||
|
||
[HttpPost]
|
||
[Route("api/transfer_register/reconcile")]
|
||
public IHttpActionResult Reconcile([FromBody] ReconcileRequest request)
|
||
{
|
||
var details = request.details;
|
||
if (details == null || details.Count == 0)
|
||
return BadRequest("無沖帳明細");
|
||
|
||
using (var transaction = _db.Database.BeginTransaction())
|
||
{
|
||
try
|
||
{
|
||
var transferRegister = _db.transfer_register.FirstOrDefault(tr => tr.id == request.transfer_register_id);
|
||
if (transferRegister == null)
|
||
return BadRequest("找不到對應的入帳記錄");
|
||
|
||
decimal totalReconcileAmount = details.Sum(d => d.amount);
|
||
decimal checkAmount = transferRegister.check_amount ?? 0;
|
||
|
||
if (totalReconcileAmount > checkAmount)
|
||
{
|
||
return BadRequest($"沖帳總額 ({totalReconcileAmount:N0}) 不可大於入帳金額 ({checkAmount:N0})");
|
||
}
|
||
|
||
// 移除會計科目檢查 - 不再需要建立 accounting 記錄
|
||
// var accountingKind = _db.accounting_kind.FirstOrDefault(ak => ak.num == 27);
|
||
// if (accountingKind == null)
|
||
// {
|
||
// return BadRequest("找不到會計科目設定 (kind=27)");
|
||
// }
|
||
|
||
// 移除 accounting 變數宣告 - 不再需要建立 accounting 記錄
|
||
// Model.accounting firstAccountingRecord = null;
|
||
|
||
foreach (var d in details)
|
||
{
|
||
var proOrderDetail = _db.pro_order_detail
|
||
.Include(pod => pod.pro_order)
|
||
.FirstOrDefault(x => x.num == d.pro_order_detail_num);
|
||
|
||
if (proOrderDetail == null)
|
||
return BadRequest($"找不到訂單明細編號: {d.pro_order_detail_num}");
|
||
|
||
decimal paidAmount = proOrderDetail.pro_order_record?.Select(r => (decimal)r.price).DefaultIfEmpty(0).Sum() ?? 0;
|
||
decimal dueAmount = (decimal)proOrderDetail.price - paidAmount;
|
||
if (d.amount > Math.Round(dueAmount, 2))
|
||
return BadRequest($"沖帳金額 ({d.amount:N0}) 超過應繳金額 ({dueAmount:N0})");
|
||
|
||
// get session user
|
||
MyWeb.admin admin = new MyWeb.admin();
|
||
Model.admin adminInfo = null;
|
||
if (admin.isLoign())
|
||
{
|
||
|
||
}
|
||
|
||
// 原本的 accounting 建立 (已移除)
|
||
/*
|
||
var acc = new Model.accounting
|
||
{
|
||
pro_order_detail_num = d.pro_order_detail_num, // 報名明細編號
|
||
price = (float)d.amount,// 沖帳金額
|
||
reg_time = d.reg_time ?? DateTime.Now, // 登記時間
|
||
kind = 27,// 固定會計科目
|
||
category = 1,//1:收入, 2:支出,
|
||
kind2 = transferRegister.acc_num,// 入帳銀行帳戶
|
||
mem_num = null,// 沖帳人編號:目前登入的使用者
|
||
activity_num = proOrderDetail.pro_order.activity_num,// 活動編號
|
||
uptime = DateTime.Today,// 更新時間
|
||
tax = 0, //??
|
||
excerpt = ""// 摘要
|
||
};
|
||
_db.accountings.Add(acc);
|
||
|
||
if (firstAccountingRecord == null)
|
||
{
|
||
firstAccountingRecord = acc;
|
||
}
|
||
*/
|
||
|
||
// 更改後的 pro_order_record 建立 (正確的付款記錄)
|
||
var proOrderRecord = new Model.pro_order_record
|
||
{
|
||
detail_num = d.pro_order_detail_num, // 報名明細編號
|
||
price = (float)d.amount, // 付款金額 (沖帳金額)
|
||
payment = transferRegister.acc_num, // 付款機構
|
||
reg_time = d.reg_time ?? DateTime.Now, // 登記時間
|
||
pay_date = transferRegister.check_date, // 付款日期
|
||
bank_code = transferRegister.account_last5, // 帳號後5碼
|
||
transfer_id = transferRegister.id, // 匯款登記編號
|
||
reconcile_memo = transferRegister.check_memo // 沖帳備註
|
||
};
|
||
_db.pro_order_record.Add(proOrderRecord);
|
||
}
|
||
|
||
decimal remainAmount = checkAmount - totalReconcileAmount;
|
||
|
||
// 設定剩餘金額
|
||
transferRegister.remain_amount = remainAmount;
|
||
|
||
// 重新生成 draft 作為沖帳記錄依據,包含額外欄位以提升查詢效率
|
||
// admin\transfer\personal_reconcile.aspx : saveDraft()
|
||
var reconcileRecord = details
|
||
.Where(d => d.amount > 0)
|
||
.Select(d => {
|
||
var proOrderDetail = _db.pro_order_detail
|
||
.Include(pod => pod.actItem)
|
||
.Include(pod => pod.pro_order)
|
||
.Include(pod => pod.pro_order.activity)
|
||
.FirstOrDefault(x => x.num == d.pro_order_detail_num);
|
||
|
||
return new {
|
||
pro_order_detail_num = d.pro_order_detail_num,
|
||
reconcile = d.amount,
|
||
// 額外欄位,避免後續查詢
|
||
actitem_name = proOrderDetail?.actItem?.subject ?? "",
|
||
activity_name = proOrderDetail?.pro_order?.activity?.subject ?? "",
|
||
register_date = proOrderDetail?.pro_order?.reg_time,
|
||
order_no = proOrderDetail?.order_no ?? "",
|
||
price = proOrderDetail?.price ?? 0
|
||
};
|
||
})
|
||
.ToList();
|
||
transferRegister.draft = Newtonsoft.Json.JsonConvert.SerializeObject(reconcileRecord);
|
||
|
||
string statusMessage;
|
||
if (remainAmount == 0)
|
||
{
|
||
// 沖帳完成且無剩餘
|
||
transferRegister.check_status = "99";
|
||
statusMessage = "沖帳完成";
|
||
}
|
||
else
|
||
{
|
||
// 沖帳完成但有剩餘
|
||
transferRegister.check_status = "90";
|
||
statusMessage = $"沖帳完成但有剩餘 NT$ {remainAmount:N0}";
|
||
}
|
||
|
||
_db.SaveChanges();
|
||
transaction.Commit();
|
||
return Ok(new { success = true, message = statusMessage });
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
transaction.Rollback();
|
||
return InternalServerError(ex);
|
||
}
|
||
}
|
||
}
|
||
|
||
// GET api/transfer_register/reconcile_detail?transfer_register_id=123
|
||
[HttpGet]
|
||
[Route("api/transfer_register/reconcile_detail")]
|
||
public IHttpActionResult GetReconcileDetail(int transfer_register_id)
|
||
{
|
||
var transferRegister = _db.transfer_register.FirstOrDefault(tr => tr.id == transfer_register_id);
|
||
if (transferRegister == null)
|
||
return NotFound();
|
||
|
||
var result = new List<object>();
|
||
|
||
if (!string.IsNullOrEmpty(transferRegister.draft))
|
||
{
|
||
try
|
||
{
|
||
// 如果 draft 已包含額外欄位,直接返回
|
||
var draftData = Newtonsoft.Json.JsonConvert.DeserializeObject<dynamic[]>(transferRegister.draft);
|
||
foreach (var item in draftData)
|
||
{
|
||
// 檢查是否已有額外欄位
|
||
if (item.actitem_name != null)
|
||
{
|
||
result.Add(item);
|
||
}
|
||
else
|
||
{
|
||
// 舊格式,需要查詢額外資訊
|
||
int proOrderDetailNum = item.pro_order_detail_num;
|
||
var proOrderDetail = _db.pro_order_detail
|
||
.Include(pod => pod.actItem)
|
||
.Include(pod => pod.pro_order)
|
||
.Include(pod => pod.pro_order.activity)
|
||
.FirstOrDefault(x => x.num == proOrderDetailNum);
|
||
|
||
result.Add(new {
|
||
pro_order_detail_num = proOrderDetailNum,
|
||
reconcile = item.reconcile,
|
||
actitem_name = proOrderDetail?.actItem?.subject ?? "",
|
||
activity_name = proOrderDetail?.pro_order?.activity?.subject ?? "",
|
||
register_date = proOrderDetail?.pro_order?.reg_time,
|
||
order_no = proOrderDetail?.order_no ?? "",
|
||
price = proOrderDetail?.price ?? 0
|
||
});
|
||
}
|
||
}
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
return InternalServerError(ex);
|
||
}
|
||
}
|
||
|
||
return Ok(result);
|
||
}
|
||
|
||
// GET api/transfer_register/balance_reconcile_list
|
||
// DTO for balance update
|
||
public class BalanceUpdateDto
|
||
{
|
||
public int id { get; set; }
|
||
public string check_status { get; set; }
|
||
public int? balance_act_item { get; set; }
|
||
public string verify_note { get; set; }
|
||
}
|
||
|
||
[HttpPost]
|
||
[Route("api/transfer_register/update_balance")]
|
||
public IHttpActionResult UpdateBalance([FromBody] BalanceUpdateDto dto)
|
||
{
|
||
try
|
||
{
|
||
var item = _db.transfer_register.Find(dto.id);
|
||
if (item == null)
|
||
return NotFound();
|
||
|
||
// 更新狀態、餘額項目和核對記錄
|
||
item.check_status = dto.check_status;
|
||
item.balance_act_item = dto.balance_act_item;
|
||
item.verify_note = dto.verify_note;
|
||
|
||
_db.SaveChanges();
|
||
|
||
// 記錄操作日誌
|
||
Model.admin_log admin_log = new Model.admin_log();
|
||
MyWeb.admin admin = new MyWeb.admin();
|
||
if (admin.isLoign())
|
||
{
|
||
string actItemName = "未知項目";
|
||
if (dto.balance_act_item.HasValue)
|
||
{
|
||
var actItem = _db.actItems.Find(dto.balance_act_item.Value);
|
||
if (actItem != null)
|
||
actItemName = actItem.subject;
|
||
}
|
||
|
||
string logMessage = $"更新餘額核銷: {item.name} 狀態:{dto.check_status} 項目:{actItemName}";
|
||
if (!string.IsNullOrEmpty(dto.verify_note))
|
||
{
|
||
logMessage += $" 核對記錄:{dto.verify_note}";
|
||
}
|
||
admin_log.writeLog(admin.info.u_id, (int)Model.admin_log.Systems.Accounting,
|
||
(int)Model.admin_log.Status.Update, logMessage);
|
||
}
|
||
|
||
return Ok(new { success = true, message = "餘額更新成功" });
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
return InternalServerError(ex);
|
||
}
|
||
}
|
||
|
||
[HttpGet]
|
||
[Route("api/transfer_register/balance_reconcile_list")]
|
||
public IHttpActionResult GetBalanceReconcileList()
|
||
{
|
||
var encrypt = new MyWeb.encrypt();
|
||
|
||
var list = _db.transfer_register
|
||
.Where(tr =>
|
||
tr.check_status != null &&
|
||
tr.check_status != "" &&
|
||
(tr.check_status == "90" || tr.check_status == "91" || tr.check_status == "92")
|
||
)
|
||
.Select(tr => new
|
||
{
|
||
tr.id,
|
||
tr.f_num,
|
||
tr.acc_num,
|
||
tr.check_date,
|
||
tr.check_amount,
|
||
tr.check_memo,
|
||
tr.check_status,
|
||
tr.verify_note,
|
||
tr.activity_num,
|
||
tr.name,
|
||
tr.phone,
|
||
tr.pay_type,
|
||
tr.account_last5,
|
||
tr.amount,
|
||
tr.pay_mode,
|
||
tr.note,
|
||
tr.proof_img,
|
||
tr.create_time,
|
||
tr.draft,
|
||
tr.status,
|
||
follower_info = tr.follower != null ? new {
|
||
u_name = tr.follower.u_name,
|
||
phone = tr.follower.phone,
|
||
cellphone = tr.follower.cellphone
|
||
} : null,
|
||
acc_name = tr.acc_num != null ? _db.accounting_kind2.Where(a => a.num == tr.acc_num).Select(a => a.kind).FirstOrDefault() : "",
|
||
activity_name = tr.activity != null ? tr.activity.subject : "",
|
||
activity_start_date = tr.activity != null ? tr.activity.startDate_solar : null,
|
||
tr.remain_amount,
|
||
tr.balance_act_item,
|
||
balance_actitem_name = tr.balance_act_item != null ? _db.actItems.Where(a => a.num == tr.balance_act_item).Select(a => a.subject).FirstOrDefault() : ""
|
||
})
|
||
.AsEnumerable()
|
||
.Select(tr => new
|
||
{
|
||
tr.id,
|
||
tr.f_num,
|
||
follower = tr.follower_info?.u_name ?? "",
|
||
phone = tr.follower_info != null ? encrypt.DecryptAutoKey(tr.follower_info.phone) : "",
|
||
phone2 = tr.follower_info != null ? encrypt.DecryptAutoKey(tr.follower_info.cellphone) : "",
|
||
tr.acc_name,
|
||
tr.check_date,
|
||
tr.check_amount,
|
||
remain_amount = tr.remain_amount ?? 0,
|
||
tr.check_status,
|
||
tr.verify_note,
|
||
tr.check_memo,
|
||
tr.activity_num,
|
||
tr.activity_name,
|
||
tr.activity_start_date,
|
||
tr.name,
|
||
tr.pay_type,
|
||
tr.account_last5,
|
||
tr.amount,
|
||
tr.pay_mode,
|
||
tr.note,
|
||
tr.proof_img,
|
||
tr.create_time,
|
||
tr.draft,
|
||
tr.status,
|
||
tr.balance_act_item
|
||
})
|
||
.Where(tr => tr.remain_amount > 0) // 只顯示有剩餘金額的記錄
|
||
.OrderBy(tr => tr.check_date)
|
||
.ToList();
|
||
|
||
return Ok(list);
|
||
}
|
||
|
||
|
||
|
||
[HttpGet]
|
||
[Route("api/transfer_register/balance_reconcile_query")]
|
||
public IHttpActionResult BalanceReconcileQuery(DateTime? start_date = null, DateTime? end_date = null, int? activity_num = null, int? follower_num = null, string is_reconcile = null)
|
||
{
|
||
var query = _db.transfer_register.AsQueryable();
|
||
|
||
// 只查狀態為95
|
||
query = query.Where(x => x.check_status == "95");
|
||
|
||
if (start_date.HasValue)
|
||
query = query.Where(x => x.check_date >= start_date.Value);
|
||
if (end_date.HasValue)
|
||
query = query.Where(x => x.check_date <= end_date.Value);
|
||
if (activity_num.HasValue)
|
||
query = query.Where(x => x.activity_num == activity_num.Value);
|
||
if (follower_num.HasValue)
|
||
query = query.Where(x => x.f_num == follower_num.Value);
|
||
|
||
var list = query
|
||
.OrderByDescending(x => x.check_date)
|
||
.Select(x => new {
|
||
x.id,
|
||
x.f_num,
|
||
follower = x.follower != null ? x.follower.u_name : "",
|
||
x.acc_num,
|
||
acc_name = x.acc_num != null ? _db.accounting_kind2.Where(a => a.num == x.acc_num).Select(a => a.kind).FirstOrDefault() : "",
|
||
x.check_date,
|
||
x.check_amount,
|
||
x.check_memo,
|
||
x.check_status,
|
||
x.verify_note,
|
||
x.activity_num,
|
||
activity_name = x.activity != null ? x.activity.subject : "",
|
||
balance_actitem_name = x.balance_act_item != null ? _db.actItems.Where(a => a.num == x.balance_act_item).Select(a => a.subject).FirstOrDefault() : "",
|
||
x.name,
|
||
x.pay_type,
|
||
x.account_last5,
|
||
x.amount,
|
||
x.pay_mode,
|
||
x.note,
|
||
x.proof_img,
|
||
x.create_time,
|
||
x.draft,
|
||
x.status,
|
||
x.balance_act_item,
|
||
reconcile_amount = x.remain_amount
|
||
})
|
||
.ToList();
|
||
|
||
return Ok(list);
|
||
}
|
||
|
||
[HttpGet]
|
||
[Route("api/transfer_register/verify_order_record_query")]
|
||
public IHttpActionResult VerifyOrderRecordQuery(DateTime? start_date = null, DateTime? end_date = null, int? activity_num = null, int? follower_num = null)
|
||
{
|
||
var query = _db.transfer_register.AsQueryable();
|
||
|
||
// 只查已完成沖帳的記錄 (狀態為 90 或 99)
|
||
query = query.Where(x => x.check_status == "90" || x.check_status == "99");
|
||
|
||
if (start_date.HasValue)
|
||
query = query.Where(x => x.check_date >= start_date.Value);
|
||
if (end_date.HasValue)
|
||
query = query.Where(x => x.check_date <= end_date.Value);
|
||
if (activity_num.HasValue)
|
||
query = query.Where(x => x.activity_num == activity_num.Value);
|
||
if (follower_num.HasValue)
|
||
query = query.Where(x => x.f_num == follower_num.Value);
|
||
|
||
var list = query
|
||
.OrderByDescending(x => x.check_date)
|
||
.Select(x => new {
|
||
// transfer_register 基本資訊
|
||
transfer_id = x.id,
|
||
transfer_name = x.name,
|
||
transfer_phone = x.phone,
|
||
transfer_pay_type = x.pay_type,
|
||
transfer_account_last5 = x.account_last5,
|
||
transfer_amount = x.amount,
|
||
transfer_pay_mode = x.pay_mode,
|
||
transfer_note = x.note,
|
||
transfer_proof_img = x.proof_img,
|
||
transfer_status = x.status,
|
||
transfer_create_time = x.create_time,
|
||
transfer_check_date = x.check_date,
|
||
transfer_check_amount = x.check_amount,
|
||
transfer_check_memo = x.check_memo,
|
||
transfer_check_status = x.check_status,
|
||
transfer_verify_note = x.verify_note,
|
||
transfer_remain_amount = x.remain_amount,
|
||
transfer_draft = x.draft,
|
||
|
||
// 關聯資訊
|
||
follower = x.follower != null ? x.follower.u_name : "",
|
||
follower_num = x.f_num,
|
||
activity_name = x.activity != null ? x.activity.subject : "",
|
||
activity_num = x.activity_num,
|
||
acc_name = x.acc_num != null ? _db.accounting_kind2.Where(a => a.num == x.acc_num).Select(a => a.kind).FirstOrDefault() : "",
|
||
|
||
// pro_order_record 資訊 (透過 transfer_id 關聯)
|
||
pro_order_records = x.pro_order_record.Select(pr => new {
|
||
pr.num,
|
||
pr.detail_num,
|
||
pr.price,
|
||
pr.payment,
|
||
pr.reg_time,
|
||
pr.pay_date,
|
||
pr.organization,
|
||
pr.bank_code,
|
||
pr.transfer_id,
|
||
pr.reconcile_memo,
|
||
|
||
// 關聯的 pro_order_detail 資訊
|
||
pro_order_detail = pr.pro_order_detail != null ? new {
|
||
pr.pro_order_detail.num,
|
||
pr.pro_order_detail.price,
|
||
pr.pro_order_detail.pay,
|
||
pr.pro_order_detail.pay_date,
|
||
pr.pro_order_detail.due_date,
|
||
pr.pro_order_detail.demo,
|
||
|
||
// 關聯的 pro_order 資訊
|
||
pro_order = pr.pro_order_detail.pro_order != null ? new {
|
||
pr.pro_order_detail.pro_order.order_no,
|
||
pr.pro_order_detail.pro_order.reg_time,
|
||
pr.pro_order_detail.pro_order.activity_num,
|
||
activity_name = pr.pro_order_detail.pro_order.activity != null ? pr.pro_order_detail.pro_order.activity.subject : ""
|
||
} : null,
|
||
|
||
// 關聯的 actItem 資訊
|
||
actitem_name = pr.pro_order_detail.actItem != null ? pr.pro_order_detail.actItem.subject : ""
|
||
} : null,
|
||
|
||
// 關聯的 accounting_kind2 資訊
|
||
payment_name = pr.accounting_kind2 != null ? pr.accounting_kind2.kind : ""
|
||
}).ToList()
|
||
})
|
||
.ToList();
|
||
|
||
return Ok(list);
|
||
}
|
||
|
||
// GET api/transfer_register/group_reconcile_list
|
||
[HttpGet]
|
||
[Route("api/transfer_register/group_reconcile_list")]
|
||
public IHttpActionResult GetGroupReconcileList()
|
||
{
|
||
var list = _db.transfer_register
|
||
.Where(tr =>
|
||
tr.status == "2" &&
|
||
tr.check_status == "2" &&
|
||
tr.pay_mode == "共同"
|
||
)
|
||
.Select(tr => new
|
||
{
|
||
tr.id,
|
||
tr.f_num,
|
||
follower = tr.follower != null ? tr.follower.u_name : "",
|
||
tr.acc_num,
|
||
acc_name = tr.acc_num != null ? _db.accounting_kind2.Where(a => a.num == tr.acc_num).Select(a => a.kind).FirstOrDefault() : "",
|
||
tr.check_date,
|
||
tr.check_amount,
|
||
tr.check_memo,
|
||
tr.check_status,
|
||
tr.verify_note,
|
||
tr.activity_num,
|
||
activity_name = tr.activity != null ? tr.activity.subject : "",
|
||
tr.name,
|
||
tr.phone,
|
||
tr.pay_type,
|
||
tr.account_last5,
|
||
tr.pay_mode,
|
||
tr.status,
|
||
tr.note,
|
||
tr.proof_img,
|
||
tr.create_time,
|
||
tr.draft
|
||
})
|
||
.ToList();
|
||
return Ok(list);
|
||
}
|
||
|
||
// GET api/transfer_register/activity_followers?activity_num=123
|
||
[HttpGet]
|
||
[Route("api/transfer_register/activity_followers")]
|
||
public IHttpActionResult GetActivityFollowers(int activity_num)
|
||
{
|
||
// 查詢該法會中有報名單且有未完成沖帳項目的信眾
|
||
var followers = _db.pro_order
|
||
.Where(o => o.activity_num == activity_num)
|
||
.SelectMany(o => o.pro_order_detail.Select(d => new {
|
||
o.f_num,
|
||
follower_name = o.follower != null ? o.follower.u_name : "",
|
||
d.num,
|
||
d.price,
|
||
paid = d.pro_order_record.Select(r => r.price).DefaultIfEmpty(0).Sum()
|
||
}))
|
||
.AsEnumerable()
|
||
.Select(x => new {
|
||
x.f_num,
|
||
x.follower_name,
|
||
x.num,
|
||
price = (decimal?)x.price,
|
||
paid = (decimal?)x.paid,
|
||
due = ((decimal?)x.price ?? 0) - ((decimal?)x.paid ?? 0)
|
||
})
|
||
.Where(x => Math.Round(x.due, 2) > 0) // 有未完成沖帳項目
|
||
.GroupBy(x => new { x.f_num, x.follower_name })
|
||
.Select(g => new {
|
||
f_num = g.Key.f_num,
|
||
follower_name = g.Key.follower_name,
|
||
total_due = g.Sum(x => x.due),
|
||
item_count = g.Count()
|
||
})
|
||
.OrderBy(x => x.follower_name)
|
||
.ToList();
|
||
|
||
return Ok(followers);
|
||
}
|
||
|
||
// GET api/transfer_register/group_follower_orders?activity_num=123&f_nums=123,456,789
|
||
[HttpGet]
|
||
[Route("api/transfer_register/group_follower_orders")]
|
||
public IHttpActionResult GetGroupFollowerOrders(int activity_num, string f_nums)
|
||
{
|
||
var followerNumList = f_nums.Split(',').Select(int.Parse).ToList();
|
||
|
||
// 取得多個信眾在指定法會的所有訂單及明細
|
||
var details = _db.pro_order
|
||
.Where(o => o.activity_num == activity_num && followerNumList.Contains(o.f_num ?? 0))
|
||
.SelectMany(o => o.pro_order_detail.Select(d => new {
|
||
o.order_no,
|
||
o.activity_num,
|
||
o.f_num,
|
||
follower_name = o.follower != null ? o.follower.u_name : "",
|
||
activity_name = o.activity != null ? o.activity.subject : "",
|
||
d.num,
|
||
d.actItem_num,
|
||
actitem_name = d.actItem != null ? d.actItem.subject : "",
|
||
price = d.price,
|
||
paid = d.pro_order_record.Select(r => r.price).DefaultIfEmpty(0).Sum(),
|
||
d.pay,
|
||
d.pay_date,
|
||
d.due_date,
|
||
d.demo,
|
||
reg_time = o.reg_time // 報名日期
|
||
}))
|
||
.AsEnumerable()
|
||
.Select(x => new {
|
||
x.order_no,
|
||
x.activity_num,
|
||
x.f_num,
|
||
x.follower_name,
|
||
x.activity_name,
|
||
x.num,
|
||
x.actItem_num,
|
||
x.actitem_name,
|
||
price = (decimal?)x.price,
|
||
paid = (decimal?)x.paid,
|
||
due = ((decimal?)x.price ?? 0) - ((decimal?)x.paid ?? 0),
|
||
x.pay,
|
||
x.pay_date,
|
||
x.due_date,
|
||
x.demo,
|
||
x.reg_time
|
||
})
|
||
.Where(x => Math.Round(x.due, 2) > 0)
|
||
.OrderBy(x => x.follower_name) // 同一信眾的在一起
|
||
.ThenBy(x => x.reg_time)
|
||
.ToList();
|
||
return Ok(details);
|
||
}
|
||
|
||
public class GroupReconcileDetail
|
||
{
|
||
public int f_num { get; set; }
|
||
public int pro_order_detail_num { get; set; }
|
||
public decimal amount { get; set; }
|
||
public DateTime? reg_time { get; set; }
|
||
}
|
||
|
||
public class GroupReconcileRequest
|
||
{
|
||
public int transfer_register_id { get; set; }
|
||
public List<GroupReconcileDetail> details { get; set; }
|
||
public decimal over_payment { get; set; }
|
||
}
|
||
|
||
[HttpPost]
|
||
[Route("api/transfer_register/group_reconcile")]
|
||
public IHttpActionResult GroupReconcile([FromBody] GroupReconcileRequest request)
|
||
{
|
||
var details = request.details;
|
||
if (details == null || details.Count == 0)
|
||
return BadRequest("無沖帳明細");
|
||
|
||
using (var transaction = _db.Database.BeginTransaction())
|
||
{
|
||
try
|
||
{
|
||
var transferRegister = _db.transfer_register.FirstOrDefault(tr => tr.id == request.transfer_register_id);
|
||
if (transferRegister == null)
|
||
return BadRequest("找不到對應的入帳記錄");
|
||
|
||
decimal totalReconcileAmount = details.Sum(d => d.amount);
|
||
decimal checkAmount = transferRegister.check_amount ?? 0;
|
||
|
||
if (totalReconcileAmount > checkAmount)
|
||
{
|
||
return BadRequest($"沖帳總額 ({totalReconcileAmount:N0}) 不可大於入帳金額 ({checkAmount:N0})");
|
||
}
|
||
|
||
foreach (var d in details)
|
||
{
|
||
var proOrderDetail = _db.pro_order_detail
|
||
.Include(pod => pod.pro_order)
|
||
.FirstOrDefault(x => x.num == d.pro_order_detail_num);
|
||
|
||
if (proOrderDetail == null)
|
||
return BadRequest($"找不到訂單明細編號: {d.pro_order_detail_num}");
|
||
|
||
decimal paidAmount = proOrderDetail.pro_order_record?.Select(r => (decimal)r.price).DefaultIfEmpty(0).Sum() ?? 0;
|
||
decimal dueAmount = (decimal)proOrderDetail.price - paidAmount;
|
||
if (d.amount > Math.Round(dueAmount, 2))
|
||
return BadRequest($"沖帳金額 ({d.amount:N0}) 超過應繳金額 ({dueAmount:N0})");
|
||
|
||
// 建立 pro_order_record 記錄(與個人沖帳相同邏輯)
|
||
var proOrderRecord = new Model.pro_order_record
|
||
{
|
||
detail_num = d.pro_order_detail_num, // 報名明細編號
|
||
price = (float)d.amount, // 付款金額 (沖帳金額)
|
||
payment = transferRegister.acc_num, // 付款機構
|
||
reg_time = d.reg_time ?? DateTime.Now, // 登記時間
|
||
pay_date = transferRegister.check_date, // 付款日期
|
||
bank_code = transferRegister.account_last5, // 帳號後5碼
|
||
transfer_id = transferRegister.id, // 匯款登記編號
|
||
reconcile_memo = transferRegister.check_memo // 沖帳備註
|
||
};
|
||
_db.pro_order_record.Add(proOrderRecord);
|
||
}
|
||
|
||
decimal remainAmount = checkAmount - totalReconcileAmount;
|
||
|
||
// 設定剩餘金額
|
||
transferRegister.remain_amount = remainAmount;
|
||
|
||
// 生成 draft 記錄,包含共同支付人資訊
|
||
var reconcileRecord = details
|
||
.Where(d => d.amount > 0)
|
||
.Select(d => {
|
||
var proOrderDetail = _db.pro_order_detail
|
||
.Include(pod => pod.actItem)
|
||
.Include(pod => pod.pro_order)
|
||
.Include(pod => pod.pro_order.activity)
|
||
.Include(pod => pod.pro_order.follower)
|
||
.FirstOrDefault(x => x.num == d.pro_order_detail_num);
|
||
|
||
return new {
|
||
f_num = d.f_num,
|
||
follower_name = proOrderDetail?.pro_order?.follower?.u_name ?? "",
|
||
pro_order_detail_num = d.pro_order_detail_num,
|
||
reconcile = d.amount,
|
||
actitem_name = proOrderDetail?.actItem?.subject ?? "",
|
||
activity_name = proOrderDetail?.pro_order?.activity?.subject ?? "",
|
||
register_date = proOrderDetail?.pro_order?.reg_time,
|
||
order_no = proOrderDetail?.order_no ?? "",
|
||
price = proOrderDetail?.price ?? 0
|
||
};
|
||
})
|
||
.ToList();
|
||
|
||
// 建立包含 follower_list 的 draft 格式
|
||
var draftData = new {
|
||
transfer_draft = new object[0], // 空陣列,因為這是共同沖帳
|
||
pro_order_detail_items = reconcileRecord,
|
||
follower_list = reconcileRecord
|
||
.GroupBy(x => new { x.f_num, x.follower_name })
|
||
.Select(g => new {
|
||
f_num = g.Key.f_num,
|
||
f_name = g.Key.follower_name,
|
||
activity_num = transferRegister.activity_num
|
||
})
|
||
.ToList()
|
||
};
|
||
transferRegister.draft = Newtonsoft.Json.JsonConvert.SerializeObject(draftData);
|
||
|
||
string statusMessage;
|
||
if (remainAmount == 0)
|
||
{
|
||
// 沖帳完成且無剩餘
|
||
transferRegister.check_status = "99";
|
||
statusMessage = "共同沖帳完成";
|
||
}
|
||
else
|
||
{
|
||
// 沖帳完成但有剩餘
|
||
transferRegister.check_status = "90";
|
||
statusMessage = $"共同沖帳完成但有剩餘 NT$ {remainAmount:N0}";
|
||
}
|
||
|
||
_db.SaveChanges();
|
||
transaction.Commit();
|
||
return Ok(new { success = true, message = statusMessage });
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
transaction.Rollback();
|
||
return InternalServerError(ex);
|
||
}
|
||
}
|
||
}
|
||
} |