532 lines
23 KiB
C#
532 lines
23 KiB
C#
using NP.Base;
|
|
using NP.Dao;
|
|
using NP.Model;
|
|
using Popbill;
|
|
using Popbill.Taxinvoice;
|
|
using System;
|
|
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Web;
|
|
using System.Web.Configuration;
|
|
|
|
namespace NP.Base.Popbill
|
|
{
|
|
public class PopbillService
|
|
{
|
|
#region 세금계산서 mgtKey(문서번호) 사용여부
|
|
/// <summary>
|
|
/// 세금계산서 mgtKey(문서번호) 사용여부
|
|
/// </summary>
|
|
/// <param name="mgtkey">mgtkey</param>
|
|
/// <param name="keyType">세금계산서 유형 : SELL = 매출, BUY = 매입, TRUSTEE = 위수탁</param>
|
|
/// <returns>bool</returns>
|
|
public static Result<bool> CheckMgtKeyInUse(string mgtkey, MgtKeyType keyType = MgtKeyType.SELL)
|
|
{
|
|
Result<bool> result = new Result<bool>();
|
|
try
|
|
{
|
|
result.IsUse = PopbillConfig.taxinvoiceService.CheckMgtKeyInUse(PopbillConfig.CorpNum, keyType, mgtkey);
|
|
}
|
|
catch (PopbillException ex)
|
|
{
|
|
result.IsSuccess = false;
|
|
result.Code = ex.code;
|
|
result.Message = ex.Message;
|
|
Logger.TryError(ex.Message, ex);
|
|
}
|
|
return result;
|
|
}
|
|
#endregion
|
|
|
|
#region 세금계산서 mgtKey(문서번호) 생성
|
|
/// <summary>
|
|
/// 세금계산서 mgtKey(문서번호) 생성
|
|
/// </summary>
|
|
/// <param name="Dao">CommonDao</param>
|
|
/// <param name="taxno">PayTax.taxno</param>
|
|
/// <param name="writeDate">발행일</param>
|
|
/// <param name="keyType">세금계산서 유형 : SELL = 매출, BUY = 매입, TRUSTEE = 위수탁</param>
|
|
/// <returns>mgtKey</returns>
|
|
public static string MakeMgtKey(CommonDao Dao, long taxno, DateTime writeDate, MgtKeyType keyType = MgtKeyType.SELL)
|
|
{
|
|
int no = 1;
|
|
string mgtkey = string.Empty;
|
|
var nowPayTax = Dao.Get<PayTax>("cr.paytaxes", new Hashtable() { { "taxno", taxno } }).FirstOrDefault();
|
|
//이미 mgtkey 발급되어 있으면 발급된 mgtkey 사용
|
|
if (nowPayTax != null && !string.IsNullOrEmpty(nowPayTax.mgtkey))
|
|
{
|
|
mgtkey = nowPayTax.mgtkey;
|
|
}
|
|
else
|
|
{
|
|
var payTax = Dao.Get<PayTax>("cr.paytax.formgtkey", new Hashtable() { { "writeDate", writeDate.ToString("yyyy-MM-dd") } }).FirstOrDefault();
|
|
if (payTax != null && !string.IsNullOrEmpty(payTax.mgtkey))
|
|
{
|
|
var strNo = payTax.mgtkey.Substring(payTax.mgtkey.IndexOf("L") + 1);
|
|
|
|
if (int.TryParse(strNo, out no))
|
|
{
|
|
++no;
|
|
}
|
|
}
|
|
|
|
mgtkey = $"{writeDate:yyyy-MM-dd}-L{no:D5}";
|
|
|
|
bool isUse = true;
|
|
int checkLimit = 50;
|
|
while (isUse && checkLimit > 0)
|
|
{
|
|
isUse = PopbillConfig.taxinvoiceService.CheckMgtKeyInUse(PopbillConfig.CorpNum, keyType, mgtkey);
|
|
if (isUse)
|
|
{
|
|
++no;
|
|
mgtkey = $"{writeDate:yyyy-MM-dd}-L{no:D5}";
|
|
}
|
|
else
|
|
{
|
|
break;
|
|
}
|
|
--checkLimit;
|
|
}
|
|
}
|
|
return mgtkey;
|
|
}
|
|
#endregion
|
|
|
|
#region 세금계산서 Taxinvoice 생성
|
|
/// <summary>
|
|
/// 세금계산서 Taxinvoice 생성
|
|
/// </summary>
|
|
/// <param name="taxinvoice">Taxinvoice</param>
|
|
/// <param name="payTax">PayTax</param>
|
|
/// <param name="payItems">payItems</param>
|
|
/// <returns>Taxinvoice</returns>
|
|
public static Taxinvoice MakeTaxinvoice(Taxinvoice taxinvoice, PayTax payTax, IList<PayItem> payItems)
|
|
{
|
|
taxinvoice.issueType = "정발행"; //"정발행" / "역발행" / "위수탁" 중 택 1
|
|
taxinvoice.taxType = "면세"; //"과세" / "영세" / "면세" 중 택 1
|
|
taxinvoice.chargeDirection = "정과금"; //"정과금" / "역과금" 중 택 1
|
|
taxinvoice.writeDate = payTax.taxdate?.ToString("yyyyMMdd");
|
|
taxinvoice.purposeType = payTax.isreceipt == 0 ? "청구" : "영수"; //0:청구, 1:영수 {"영수" / "청구" / "없음" 중 택 1}
|
|
taxinvoice.supplyCostTotal = payTax.taxamt.ToString();
|
|
taxinvoice.taxTotal = "0";
|
|
taxinvoice.totalAmount = payTax.taxamt.ToString();
|
|
taxinvoice.invoiceeType = "사업자";
|
|
taxinvoice.invoiceeCorpNum = payTax.brno;
|
|
taxinvoice.invoiceeCorpName = payTax.asname;
|
|
taxinvoice.invoiceeCEOName = payTax.ceoname;
|
|
taxinvoice.invoiceeAddr = payTax.asaddr;
|
|
taxinvoice.invoiceeBizType = payTax.btype;
|
|
taxinvoice.invoiceeBizClass = payTax.bkind;
|
|
taxinvoice.invoiceeContactName1 = payTax.manname;
|
|
taxinvoice.invoiceeTEL1 = payTax.telno;
|
|
taxinvoice.invoiceeEmail1 = payTax.email;
|
|
//taxinvoice.serialNum = payTax.taxno.ToString();
|
|
|
|
#region 상세항목(품목) 정보
|
|
if (payItems != null)
|
|
{
|
|
/**************************************************************************
|
|
* 상세항목(품목) 정보 *
|
|
* - 상세항목 정보는 세금계산서 필수기재사항이 아니므로 작성하지 않더라도 *
|
|
* 세금계산서 발행이 가능합니다. *
|
|
* - 최대 99건까지 작성가능 *
|
|
**************************************************************************/
|
|
|
|
taxinvoice.detailList = new List<TaxinvoiceDetail>();
|
|
var serialNum = 1;
|
|
foreach (var payItem in payItems)
|
|
{
|
|
TaxinvoiceDetail detail = new TaxinvoiceDetail();
|
|
detail.serialNum = serialNum; // 일련번호, 1부터 순차기재
|
|
detail.purchaseDT = payTax.taxdate?.ToString("yyyyMMdd"); // 거래일자
|
|
detail.itemName = payItem.itemname; // 품목명
|
|
detail.spec = payItem.username; // 규격(이름)
|
|
detail.qty = payItem.pcnt.ToString(); // 수량
|
|
detail.unitCost = payItem.payamt.ToString(); // 단가
|
|
detail.supplyCost = payItem.payamt.ToString(); // 공급가액
|
|
detail.tax = "0"; // 세액
|
|
detail.remark = ""; // 비고
|
|
taxinvoice.detailList.Add(detail);
|
|
++serialNum;
|
|
}
|
|
}
|
|
#endregion
|
|
|
|
return taxinvoice;
|
|
}
|
|
#endregion
|
|
|
|
#region 세금계산서 상태
|
|
/// <summary>
|
|
/// 세금계산서 상태
|
|
/// </summary>
|
|
/// <param name="stateCode">상태코드</param>
|
|
/// <returns>상태</returns>
|
|
public static string GetTaxinvoiceState(int stateCode)
|
|
{
|
|
string state = string.Empty;
|
|
switch (stateCode)
|
|
{
|
|
case 100:
|
|
state = "임시저장";
|
|
break;
|
|
case 300:
|
|
state = "발행완료";
|
|
break;
|
|
case 301:
|
|
state = "국세청-전송전";
|
|
break;
|
|
case 302:
|
|
state = "국세청-전송대기";
|
|
break;
|
|
case 303:
|
|
state = "국세청-전송중";
|
|
break;
|
|
case 304:
|
|
state = "국세청-전송성공";
|
|
break;
|
|
case 305:
|
|
state = "국세청-전송실패";
|
|
break;
|
|
case 600:
|
|
state = "발행취소";
|
|
break;
|
|
default:
|
|
state = $"stateCode:{stateCode}";
|
|
break;
|
|
}
|
|
return state;
|
|
}
|
|
#endregion
|
|
|
|
#region 세금계산서 상세정보
|
|
/// <summary>
|
|
/// 세금계산서 상세정보
|
|
/// </summary>
|
|
/// <param name="payTax">PayTax</param>
|
|
/// <param name="payItems">payItems</param>
|
|
/// <param name="keyType">세금계산서 유형 : SELL = 매출, BUY = 매입, TRUSTEE = 위수탁</param>
|
|
/// <returns>Taxinvoice</returns>
|
|
public static Result<Taxinvoice> GetTaxinvoice(PayTax payTax, IList<PayItem> payItems = null, MgtKeyType keyType = MgtKeyType.SELL)
|
|
{
|
|
Result<Taxinvoice> result = new Result<Taxinvoice>();
|
|
try
|
|
{
|
|
if (!string.IsNullOrEmpty(payTax.mgtkey) && PopbillConfig.taxinvoiceService.CheckMgtKeyInUse(PopbillConfig.CorpNum, keyType, payTax.mgtkey))
|
|
{
|
|
result.Data = PopbillConfig.taxinvoiceService.GetDetailInfo(PopbillConfig.CorpNum, keyType, payTax.mgtkey);
|
|
}
|
|
else
|
|
{
|
|
CorpInfo corpInfo = PopbillConfig.taxinvoiceService.GetCorpInfo(PopbillConfig.CorpNum, PopbillConfig.UserID);
|
|
Contact contact = PopbillConfig.taxinvoiceService.ListContact(PopbillConfig.CorpNum, PopbillConfig.UserID).Where(w => w.mgrYN == true).FirstOrDefault();
|
|
result.Data = new Taxinvoice
|
|
{
|
|
invoicerAddr = corpInfo?.addr,
|
|
invoicerCEOName = corpInfo?.ceoname,
|
|
invoicerCorpName = corpInfo?.corpName,
|
|
invoicerMgtKey = payTax.mgtkey,
|
|
invoicerCorpNum = PopbillConfig.CorpNum,
|
|
invoicerBizClass = corpInfo?.bizClass,
|
|
invoicerBizType = corpInfo?.bizType,
|
|
invoicerContactName = contact?.personName,
|
|
invoicerEmail = contact?.email,
|
|
invoicerHP = contact?.hp,
|
|
invoicerTEL = contact?.tel
|
|
};
|
|
}
|
|
result.Data = MakeTaxinvoice(result.Data, payTax, payItems);
|
|
}
|
|
catch (PopbillException ex)
|
|
{
|
|
result.IsSuccess = false;
|
|
result.Code = ex.code;
|
|
result.Message = ex.Message;
|
|
Logger.TryError(ex.Message, ex);
|
|
}
|
|
return result;
|
|
}
|
|
#endregion
|
|
|
|
#region 세금계산서 상태정보
|
|
/// <summary>
|
|
/// 세금계산서 상태정보
|
|
/// </summary>
|
|
/// <param name="payTax">PayTax</param>
|
|
/// <param name="keyType">세금계산서 유형 : SELL = 매출, BUY = 매입, TRUSTEE = 위수탁</param>
|
|
/// <returns>Taxinvoice</returns>
|
|
public static Result<TaxinvoiceInfo> GetTaxinvoiceInfo(PayTax payTax, MgtKeyType keyType = MgtKeyType.SELL)
|
|
{
|
|
Result<TaxinvoiceInfo> result = new Result<TaxinvoiceInfo>();
|
|
try
|
|
{
|
|
result.Data = PopbillConfig.taxinvoiceService.GetInfo(PopbillConfig.CorpNum, keyType, payTax.mgtkey);
|
|
}
|
|
catch (PopbillException ex)
|
|
{
|
|
result.IsSuccess = false;
|
|
result.Code = ex.code;
|
|
result.Message = ex.Message;
|
|
Logger.TryError(ex.Message, ex);
|
|
}
|
|
return result;
|
|
}
|
|
#endregion
|
|
|
|
#region 세금계산서 파일등록(사업자등록증)
|
|
/// <summary>
|
|
/// 세금계산서 파일등록(사업자등록증)
|
|
/// </summary>
|
|
/// <param name="Dao"></param>
|
|
/// <param name="payTax"></param>
|
|
/// <param name="keyType"></param>
|
|
/// <returns></returns>
|
|
public static Response AttachFile(CommonDao Dao, PayTax payTax, MgtKeyType keyType = MgtKeyType.SELL)
|
|
{
|
|
Response response = new Response();
|
|
if (payTax.fgno != null && payTax.fgno != 0)
|
|
{
|
|
IList<File> files = Dao.GetFiles(payTax.fgno.Value);
|
|
#region 기존 등록된 파일삭제(사업자등록증)
|
|
if (files.Count > 0)
|
|
{
|
|
var attachedFiles = PopbillConfig.taxinvoiceService.GetFiles(PopbillConfig.CorpNum, keyType, payTax.mgtkey);
|
|
foreach (var attachedFile in attachedFiles)
|
|
{
|
|
response = PopbillConfig.taxinvoiceService.DeleteFile(PopbillConfig.CorpNum, keyType, payTax.mgtkey, attachedFile.attachedFile, PopbillConfig.UserID);
|
|
}
|
|
}
|
|
#endregion
|
|
|
|
|
|
#region #region 파일등록(사업자등록증)
|
|
foreach (var file in files)
|
|
{
|
|
var filePath = HttpContext.Current.Server.MapPath(file.fullurl);
|
|
if (System.IO.File.Exists(filePath))
|
|
{
|
|
response = PopbillConfig.taxinvoiceService.AttachFile(PopbillConfig.CorpNum, keyType, payTax.mgtkey, filePath, PopbillConfig.UserID);
|
|
}
|
|
}
|
|
#endregion
|
|
}
|
|
return response;
|
|
}
|
|
#endregion
|
|
|
|
#region 세금계산서 임시저장(수정)
|
|
/// <summary>
|
|
/// 세금계산서 임시저장(수정)
|
|
/// </summary>
|
|
/// <param name="Dao">CommonDao</param>
|
|
/// <param name="payTax">payTax</param>
|
|
/// <param name="payItems">payItems</param>
|
|
/// <param name="keyType">세금계산서 유형 : SELL = 매출, BUY = 매입, TRUSTEE = 위수탁</param>
|
|
/// <returns>mgtkey</returns>
|
|
/// <remarks>작성된 세금계산서 데이터를 팝빌에 저장합니다.</remarks>
|
|
public static Result<Response> TempSave(CommonDao Dao, PayTax payTax, IList<PayItem> payItems, MgtKeyType keyType = MgtKeyType.SELL)
|
|
{
|
|
Result<Response> result = new Result<Response>();
|
|
try
|
|
{
|
|
var taxinvoice = GetTaxinvoice(payTax, payItems).Data;
|
|
if (PopbillConfig.taxinvoiceService.CheckMgtKeyInUse(PopbillConfig.CorpNum, keyType, payTax.mgtkey))
|
|
{
|
|
result.Data = PopbillConfig.taxinvoiceService.Update(PopbillConfig.CorpNum, keyType, payTax.mgtkey, taxinvoice, PopbillConfig.UserID);
|
|
}
|
|
else
|
|
{
|
|
result.Data = PopbillConfig.taxinvoiceService.Register(PopbillConfig.CorpNum, taxinvoice);
|
|
}
|
|
|
|
if (result.Data.code == 1)
|
|
{
|
|
AttachFile(Dao, payTax, keyType);
|
|
}
|
|
|
|
result.Code = result.Data.code;
|
|
result.Message = result.Data.message;
|
|
}
|
|
catch (PopbillException ex)
|
|
{
|
|
result.IsSuccess = false;
|
|
result.Code = ex.code;
|
|
result.Message = ex.Message;
|
|
Logger.TryError(ex.Message, ex);
|
|
}
|
|
return result;
|
|
}
|
|
#endregion
|
|
|
|
#region 세금계산서 발행
|
|
/// <summary>
|
|
/// 세금계산서 발행
|
|
/// </summary>
|
|
/// <param name="mgtkey">파트너가 할당한 문서번호</param>
|
|
/// <param name="keyType">세금계산서 유형 : SELL = 매출, BUY = 매입, TRUSTEE = 위수탁</param>
|
|
/// <param name="forceIssue">지연발행 가능여부</param>
|
|
/// <param name="memo">메모</param>
|
|
/// <returns>IssueResponse</returns>
|
|
/// <remarks>"임시저장" 또는 "(역)발행대기" 상태의 세금계산서를 발행(전자서명)하며, "발행완료" 상태로 처리합니다</remarks>
|
|
public static Result<IssueResponse> Issue(string mgtkey, MgtKeyType keyType = MgtKeyType.SELL, bool forceIssue = false, string memo = "")
|
|
{
|
|
Result<IssueResponse> result = new Result<IssueResponse>();
|
|
try
|
|
{
|
|
result.Data = PopbillConfig.taxinvoiceService.Issue(PopbillConfig.CorpNum, keyType, mgtkey, memo, forceIssue, PopbillConfig.UserID);
|
|
result.Code = result.Data.code;
|
|
result.Message = result.Data.message;
|
|
}
|
|
catch (PopbillException ex)
|
|
{
|
|
result.IsSuccess = false;
|
|
result.Code = ex.code;
|
|
result.Message = ex.Message;
|
|
Logger.TryError(ex.Message, ex);
|
|
}
|
|
return result;
|
|
}
|
|
#endregion
|
|
|
|
#region 세금계산서 발행취소
|
|
/// <summary>
|
|
/// 세금계산서 발행취소
|
|
/// </summary>
|
|
/// <param name="mgtkey">파트너가 할당한 문서번호</param>
|
|
/// <param name="memo">메모</param>
|
|
/// <param name="keyType">세금계산서 유형 : SELL = 매출, BUY = 매입, TRUSTEE = 위수탁</param>
|
|
/// <returns>IssueResponse</returns>
|
|
/// <remarks>국세청 전송 이전 "발행완료" 상태의 전자세금계산서를 "발행취소"하고, 해당 건은 국세청 신고 대상에서 제외됩니다.</remarks>
|
|
public static Result<Response> CancelIssue(string mgtkey, string memo = "", MgtKeyType keyType = MgtKeyType.SELL)
|
|
{
|
|
Result<Response> result = new Result<Response>();
|
|
try
|
|
{
|
|
result.Data = PopbillConfig.taxinvoiceService.CancelIssue(PopbillConfig.CorpNum, keyType, mgtkey, memo, PopbillConfig.UserID);
|
|
result.Code = result.Data.code;
|
|
result.Message = result.Data.message;
|
|
}
|
|
catch (PopbillException ex)
|
|
{
|
|
result.IsSuccess = false;
|
|
result.Code = ex.code;
|
|
result.Message = ex.Message;
|
|
Logger.TryError(ex.Message, ex);
|
|
}
|
|
return result;
|
|
}
|
|
#endregion
|
|
|
|
#region 세금계산서 즉시 발행
|
|
/// <summary>
|
|
/// 세금계산서 즉시 발행
|
|
/// </summary>
|
|
/// <param name="Dao">Dao</param>
|
|
/// <param name="payTax">payTax</param>
|
|
/// <param name="payItems">payItems</param>
|
|
/// <param name="forceIssue">지연발행 가능여부</param>
|
|
/// <param name="memo">메모</param>
|
|
/// <returns>IssueResponse</returns>
|
|
/// <remarks>작성된 세금계산서 데이터를 팝빌에 저장과 동시에 발행(전자서명)하여 "발행완료" 상태로 처리합니다.</remarks>
|
|
public static Result<IssueResponse> RegistIssue(CommonDao Dao, PayTax payTax, IList<PayItem> payItems, MgtKeyType keyType = MgtKeyType.SELL, bool forceIssue = false, string memo = "")
|
|
{
|
|
Result<IssueResponse> result = new Result<IssueResponse>(); ;
|
|
try
|
|
{
|
|
//첨부파일이 있으면 임시저장 후 발행
|
|
if (payTax.fgno != null && payTax.fgno != 0)
|
|
{
|
|
var resultResponse = TempSave(Dao, payTax, payItems, keyType);
|
|
if (resultResponse.IsSuccess)
|
|
{
|
|
result = Issue(payTax.mgtkey, keyType, forceIssue, memo);
|
|
}
|
|
else
|
|
{
|
|
result.IsSuccess = false;
|
|
result.Code = resultResponse.Code;
|
|
result.Message = resultResponse.Message;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
var taxinvoice = GetTaxinvoice(payTax, payItems, keyType).Data;
|
|
result.Data = PopbillConfig.taxinvoiceService.RegistIssue(PopbillConfig.CorpNum, taxinvoice, forceIssue, memo);
|
|
result.Code = result.Data.code;
|
|
result.Message = result.Data.message;
|
|
}
|
|
}
|
|
catch (PopbillException ex)
|
|
{
|
|
result.IsSuccess = false;
|
|
result.Code = ex.code;
|
|
result.Message = ex.Message;
|
|
Logger.TryError(ex.Message, ex);
|
|
}
|
|
return result;
|
|
}
|
|
#endregion
|
|
|
|
#region 세금계산서 인쇄 팝업 URL 확인
|
|
/// <summary>
|
|
/// 세금계산서 인쇄 팝업 URL 확인
|
|
/// </summary>
|
|
/// <param name="mgtkey">파트너가 할당한 문서번호</param>
|
|
/// <param name="keyType">세금계산서 유형 : SELL = 매출, BUY = 매입, TRUSTEE = 위수탁</param>
|
|
/// <returns>URL</returns>
|
|
public static Result<string> GetPrintURL(string mgtkey, MgtKeyType keyType = MgtKeyType.SELL)
|
|
{
|
|
Result<string> result = new Result<string>(); ;
|
|
try
|
|
{
|
|
result.Data = PopbillConfig.taxinvoiceService.GetPrintURL(PopbillConfig.CorpNum, keyType, mgtkey, PopbillConfig.UserID);
|
|
}
|
|
catch (PopbillException ex)
|
|
{
|
|
result.IsSuccess = false;
|
|
result.Code = ex.code;
|
|
result.Message = ex.Message;
|
|
Logger.TryError(ex.Message, ex);
|
|
}
|
|
return result;
|
|
}
|
|
#endregion
|
|
|
|
#region 세금계산서 인쇄 팝업 URL 확인 - 공급받는자용
|
|
/// <summary>
|
|
/// 세금계산서 인쇄 팝업 URL 확인 - 공급받는자용
|
|
/// </summary>
|
|
/// <param name="mgtkey">파트너가 할당한 문서번호</param>
|
|
/// <param name="keyType">세금계산서 유형 : SELL = 매출, BUY = 매입, TRUSTEE = 위수탁</param>
|
|
/// <returns>URL</returns>
|
|
public static Result<string> GetEPrintURL(string mgtkey, MgtKeyType keyType = MgtKeyType.SELL)
|
|
{
|
|
Result<string> result = new Result<string>(); ;
|
|
try
|
|
{
|
|
result.Data = PopbillConfig.taxinvoiceService.GetEPrintURL(PopbillConfig.CorpNum, keyType, mgtkey, PopbillConfig.UserID);
|
|
}
|
|
catch (PopbillException ex)
|
|
{
|
|
result.IsSuccess = false;
|
|
result.Code = ex.code;
|
|
result.Message = ex.Message;
|
|
Logger.TryError(ex.Message, ex);
|
|
}
|
|
return result;
|
|
}
|
|
#endregion
|
|
}
|
|
|
|
public class Result<T>
|
|
{
|
|
public bool IsSuccess = true;
|
|
public long Code = 1;
|
|
public String Message = string.Empty;
|
|
public T Data;
|
|
public bool IsUse = false;
|
|
}
|
|
}
|