2022-09-12
(C) Questetra, Inc. (MIT License)
2
https://support.questetra.com/bpmn-icons/service-task-stripe-invoice-finalize/
https://support.questetra.com/ja/bpmn-icons/service-task-stripe-invoice-finalize/
This item finalizes a draft invoice on Stripe, which allows you to send the invoice or charge the customer.
この工程は、Stripe 上の請求書のドラフト(下書き)を確定します。請求書が確定すると、顧客に請求書の送付や課金ができるようになります。
iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAAXNSR0IArs4c6QAAAvJJREFUWEfF
l19I01EUxz/XKZqWNbVS6cH+UfSUGQlCD0EQRCkoFDkDUzENi6IgkB4sKEgjDStFnVlzalC9+BBR
IEFBEeVbFP3R/lhRpLRpKHO78dtv021u+pszfnv87Zzv+dxzzj33XoHOP6E1fvleGe9KJF/CDiSZ
CDIAo8d/BMkggn4BfVE27rX0ir9atOcEKC6WqdEOTkuoAOK0iALjAponY7jY0SF+zOYzK0CJSVYI
uAQkaAwcaDYm4VS7VTSH8g8JUFokryOpnGdgfzdBk7lTHAmmFRSgxCS7BBxYkOAeEQnd7VZRGKg5
A2BBVz4z2oxM+AF4at60kCsP1JJQ6dsTUwBKtxscvI+g4bRyjzljWOfdHVMAZSZZL+G4VpVI7AQ0
tFnFCUXDDaAMGWciv8PY55HEV3zHDTaSlWHlBigzySIJlvmoxsbBxHj4ngIOtllFpxug1CTNQMls
MjnbIS0d7t6etmpshe9DcKEmfACg3WwVpSpAoXyFIDNQZuMm2J2rfk1Ng6XL4NlTSE4Blwt6LOB0
QtEhkBKGvsCdHli9FnLzoe8h9L8MASfpN3eJLd4MDPscLFMeTTcgOhocDjXNi5fAr5+wYqUa+NOA
ClF9FiYnVdtHD2DnLpiYgNhYqKmGr5+DQoyYrSLJCyCDmdQ1gtEIdpv6r7LKbgscroKr9ZC/Dzpa
VIBr9VBeBYYoiDKotkLA/V7/svnGMVuFYuLugaAAx05C+ipIWa4KShe8eA7ZOdB4GQr2TwMMfoSM
NfDuLazfALY/YLdD9y148zp4GXwBgpag9goYk2BkGJ48hj15MDoK8QnQUAtZ26DrJrRaVMBRO9Sd
h7wC2JylAp87A9+G5ipBiCbU0ttbs6HiqFqCkA0XTCigCefchqFgFsWrO2TggxZcP5vpbRjJIAo7
rMfBbxDpPoo941i/w0gB0P04ViB0vZB4m0nXK5kXQtdL6X/JRLjXcp9M6Pcw8ULo+jTznXK6PU7n
O2q1+v0D2nRCMMki7aoAAAAASUVORK5CYII=
{
configs.put('conf_Auth', 'Stripe');
// 請求書 ID が保存されている文字型データ項目(単一行)を準備
const invoiceIdDef = engine.createDataDefinition('確定済み請求書の ID', 1, 'q_invoiceId', 'STRING_TEXTFIELD');
engine.setData(invoiceIdDef, invoiceId);
configs.putObject('conf_InvoiceId', invoiceIdDef);
// 支払い期日が保存されている日時型データ項目を準備
const dueDateDef = engine.createDataDefinition('支払い期日', 2, 'q_dueDatetime', 'DATETIME');
const dueDatetime = new com.questetra.bpms.util.AddableTimestamp().addMinutes(minutesUntilDueDate);
engine.setData(dueDateDef, dueDatetime);
configs.putObject('conf_DueDate', dueDateDef);
return Math.floor(dueDatetime.getTime() / 1000).toString();
};
const ONE_DAY = 60 * 24; // minutes
/**
* 請求書 ID が空
*/
test('Invoice ID is blank', () => {
prepareConfigs(null, ONE_DAY);
expect(execute).toThrow('Invoice ID is blank.');
});
/**
* 支払い期日が空
*/
test('Due date is not set', () => {
prepareConfigs('in_00001', ONE_DAY);
const dueDateDef = engine.createDataDefinition('新しい支払い期日', 3, 'q_newDueDatetime', 'DATETIME');
configs.putObject('conf_DueDate', dueDateDef);
expect(execute).toThrow('Due date is not set.');
});
/**
* 支払い期日が過去
*/
test('Due date is not in the future', () => {
prepareConfigs('in_00001', -1);
expect(execute).toThrow('Due date must be future.');
});
const MAX_DAYS = 1800;
/**
* 支払い期日が遠すぎる
*/
test('Due date is too far in the future', () => {
const maxDays = 1800;
prepareConfigs('in_00001', ONE_DAY * MAX_DAYS + 1);
expect(execute).toThrow('Number of days until due date must be less than or equal to 1800.');
});
/**
* 請求書ドラフトを更新する API リクエストのテスト
* @param {Object} request
* @param request.url
* @param request.method
* @param request.headers
* @param request.contentType
* @param request.body
* @param invoiceId
* @param dueDateTimestamp
*/
const assertUpdateInvoiceRequest = ({url, method, headers, contentType, body}, invoiceId, dueDateTimestamp) => {
expect(url).toEqual(`https://api.stripe.com/v1/invoices/${encodeURIComponent(invoiceId)}`);
expect(method).toEqual('POST');
expect(headers.get('Stripe-Version')).toEqual(STRIPE_VERSION);
expect(contentType).startsWith('application/x-www-form-urlencoded');
expect(body).toEqual(`collection_method=send_invoice&due_date=${dueDateTimestamp}`);
};
/**
* 請求書ドラフトを更新する HTTP リクエストで失敗
*/
test('Fail to update invoice', () => {
const dueDateTimestamp = prepareConfigs('in_00021', ONE_DAY);
httpClient.setRequestHandler((request) => {
assertUpdateInvoiceRequest(request, 'in_00021', dueDateTimestamp);
return httpClient.createHttpResponse(400, 'application/json', '{}');
});
expect(execute).toThrow('Failed to update invoice. status: 400');
});
/**
* 請求書ドラフトを確定する API リクエストのテスト
* @param {Object} request
* @param request.url
* @param request.method
* @param request.headers
* @param request.contentType
* @param request.body
* @param invoiceId
*/
const assertFinalizeInvoiceRequest = ({url, method, headers, contentType, body}, invoiceId) => {
expect(url).toEqual(`https://api.stripe.com/v1/invoices/${encodeURIComponent(invoiceId)}/finalize`);
expect(method).toEqual('POST');
expect(headers.get('Stripe-Version')).toEqual(STRIPE_VERSION);
expect(contentType).startsWith('application/x-www-form-urlencoded');
expect(body).toEqual('auto_advance=false');
};
/**
* 請求書ドラフトを確定する HTTP リクエストで失敗
*/
test('Fail to finalize invoice', () => {
const dueDateTimestamp = prepareConfigs('in_00031', ONE_DAY);
let reqCount = 0;
httpClient.setRequestHandler((request) => {
if (reqCount === 0) {
assertUpdateInvoiceRequest(request, 'in_00031', dueDateTimestamp);
reqCount++;
return httpClient.createHttpResponse(200, 'application/json', '{}');
}
assertFinalizeInvoiceRequest(request, 'in_00031');
return httpClient.createHttpResponse(400, 'application/json', '{}');
});
expect(execute).toThrow('Failed to finalize invoice. status: 400');
});
/**
* 成功 - 支払い期日まで 1 日
*/
test('Success - 1 day until due date', () => {
const dueDateTimestamp = prepareConfigs('in_00032', ONE_DAY);
let reqCount = 0;
httpClient.setRequestHandler((request) => {
if (reqCount === 0) {
assertUpdateInvoiceRequest(request, 'in_00032', dueDateTimestamp);
reqCount++;
return httpClient.createHttpResponse(200, 'application/json', '{}');
}
assertFinalizeInvoiceRequest(request, 'in_00032');
return httpClient.createHttpResponse(200, 'application/json', '{}');
});
execute();
});
/**
* 成功 - 支払い期日まで最大日数
*/
test('Success - maximum days until due date', () => {
const dueDateTimestamp = prepareConfigs('in_00033', ONE_DAY * MAX_DAYS);
let reqCount = 0;
httpClient.setRequestHandler((request) => {
if (reqCount === 0) {
assertUpdateInvoiceRequest(request, 'in_00033', dueDateTimestamp);
reqCount++;
return httpClient.createHttpResponse(200, 'application/json', '{}');
}
assertFinalizeInvoiceRequest(request, 'in_00033');
return httpClient.createHttpResponse(200, 'application/json', '{}');
});
execute();
});
]]>