Episode 529: Making PayPal Operation into Subroutine

Monday, April 3, 2017

Isolation of Accounting Steps

It is very convenient if prepared "PayPal Billing Flow" as "Independent Subroutine Process".

Since it can be called from various business flows in the Workflow system, the process owner can focus on the design and maintenance of the main business flow.

Even from the perspective of the Accounting department on the downstream side, they will be able to perform efficient business since they can handle multiple business flows without distinction. (However, involvement to upstream will tend to decrease.) In addition, there is a need that "want to manage and maintain centrally" in the accounting system (*) in which the changes in the past one or two years were extremely vigorous.

* ※ "Cloud Accounting", "Bank API", "Accounting BPO", etc.


Processing of PayPal Invoice

The following business process definition (Workflow / App) is "PayPal billing process" which automatically collaborates with PayPal.

Various requests are made from the Workflow system side via "PayPal REST API", specifically "PayPal Invoicing API". That is, it is a mechanism that
  • let PayPal generate 'PayPal Invoice'
  • let PayPal send "PayPal Invoice"
  • check payment status of "PayPal Invoice" against PayPal.
(The opportunity to login directly to PayPal will be reduced.)

[PayPal-Invoice]

Significance of sub-processization

It can also be said that it is a Process which Steps not related to PayPal invoice has shredded off from the Process diagram in the previous article, "Episode 528: Automatic Confirmation of PayPal Status at Automatic Step".

In other words, this "PayPal billing process" is based on the assumption that it will be automatically Started by receiving the data in the Issues which the flow have been completed at Manufacturing or Sales department.

It may be necessary for you to "get used to it" regarding the parts that connect business processes with each other. However, it is not necessary to change the setting unless there is a change in the Data items to be transmitted and received, so you can effort for improvement with mobility on each Business Process.

* It sends data such as "Unit Price" "Quantity" "Email Address of Billing Party" with HTTP POST method. It's not that much difficult technology, if you've ever created a mechanism for sending data from web forms, while being as a web designer or a web programmer, etc.

Manual) M411 Auto-starting “Billing Process” Triggered by “Shipping Process”

Efficiency improvement from viewpoint of Accounting staff

In this flow, "Script Task" is provided to automatically generate "transfer slip CSV" to be registered in the accounting system.

However, the generation script to be set will also be unique, since "transfer slip CSV" to be generated there depends on the accounting system or accounting standard adopted by each company. In this example, on the premise that "posting start month" and "apportioning month number" are handed over from the upstream Steps for the months in which sales should be apportioned proportionally, the task of registering sales in "MF Cloud Accounting" has become more efficiently.

Incidentally, "MF Cloud Accounting" (itself) will be directly aware of "payment settlement status of PayPal". (Capable of OAuth federation)

Therefore, the workflow system 'Questetra' does not need to inform the settlement status of the payment system 'PayPal', to the accounting system 'MF Cloud Accounting'. (It is the same mechanism as the "Bank API" started in "Mizuho Bank" in 2016.)

<Setting example of Script Task "Generate CSV for Accounting">
// Sales Accounting (ver. 20170329)
// (c) 2017, Questetra, Inc. (the MIT License)

//// == ワークフローデータの参照 / Data Retrieving ==
var contractName = processInstance.getProcessInstanceTitle() + "";
var invoiceTag = data.get( "q_billingBusinessName" ) + "";

var dateOfPayment = data.get( "q_paymentTermDueDate" );
// instanceof com.questetra.bpms.util.AddableDate *Manual#M230
var dateOfInvoice = data.get( "q_invoiceDate" );
// instanceof com.questetra.bpms.util.AddableDate *Manual#M230
var amountOfInvoice = data.get( "q_totalAmount" ) - 0;
var cardFee = parseInt( amountOfInvoice * 0.039 ) + 40; // 3.9%+40円

var dateOfInitialSales = data.get( "q_salesBookStartMonth" );
// instanceof com.questetra.bpms.util.AddableDate *Manual#M230
var categoryOfInitialSales = ""; // 勘定補助科目名
var amountOfInitialSales = 0; // 按分対象外の売上高(初月計上)

var startMonthOfRunningSales = data.get( "q_salesBookStartMonth" );
// instanceof com.questetra.bpms.util.AddableDate *Manual#M230
var categoryOfRunningSales = "SaaS(オプション含)"; // 勘定補助科目名
var countOfRunningSales = data.get( "q_itemQuantity" ) - 0;
var amountOfRunningSales = data.get( "q_totalAmount" ) - 0;


//// == 演算 / Calculating ==
// <slip csv record sample> (16 cols)
// "1234501","2016/12/01","売掛金","","対象外","","3334","売上高","SaaS(オプション含)","課税売上 8%","","3334","2016-12 @ AAA corp","","",""
// "1234502","2017/01/01","前受金","","対象外","","3333","売上高","SaaS(オプション含)","課税売上 8%","","3333","2017-01 @ AAA corp","","",""
// "1234503","2017/02/01","前受金","","対象外","","3333","売上高","SaaS(オプション含)","課税売上 8%","","3333","2017-02 @ AAA corp","","",""
// "1234504","2016/12/31","普通預金","XXX銀行","対象外","","10000","売掛金","","対象外","","3334","2016-11 # AAA corp","","","未実現"
// "1234504","2016/12/31","","","","","","前受金","","対象外","","6666","2016-11 # @ AAA corp","","",""

var accountingDateFormat = new java.text.SimpleDateFormat( "yyyy/MM/dd" );
var yearMonthDateFormat = new java.text.SimpleDateFormat( "yyyy-MM" );

var slipTsv = "伝票番号\t取引日\t";
slipTsv += "借方勘定科目\t借方補助科目\t借方税区分\t借方部門\t借方金額(円)\t";
slipTsv += "貸方勘定科目\t貸方補助科目\t貸方税区分\t貸方部門\t貸方金額(円)\t";
slipTsv += "摘要\t仕訳メモ\tタグ\tMF仕訳タイプ\n";

var subnum = 1;
var receivableTotal = 0; // 売掛金の額の計算
var receivedTotal = 0;   // 前受金の額の計算


/// Sales Records
// Before Payment: "売掛金 1000 / 売上高 1000"
// After Payment:  "前受金 1000 / 売上高 1000"

if( amountOfInitialSales !== 0 ){
  if( dateOfInitialSales.before( dateOfPayment ) ){
    slipTsv += processInstance.getProcessInstanceId() + ("00" + subnum).slice(-2) + "\t";
    slipTsv += accountingDateFormat.format( dateOfInitialSales ) + "\t";
    slipTsv += "売掛金" + "\t" + "\t" + "対象外" + "\t" + "\t" + amountOfInitialSales + "\t";
    slipTsv += "売上高" + "\t" + categoryOfInitialSales + "\t" + "課税売上 8%" + "\t" + "\t" + amountOfInitialSales + "\t";
    slipTsv += yearMonthDateFormat.format( dateOfInitialSales ) + " @ " + contractName  + "\t" + "\t" + invoiceTag + "\t";
    slipTsv += "\n";
    receivableTotal += amountOfInitialSales;
  }else{ // rare case
    slipTsv += processInstance.getProcessInstanceId() + ("00" + subnum).slice(-2) + "\t";
    slipTsv += accountingDateFormat.format( dateOfInitialSales ) + "\t";
    slipTsv += "前受金" + "\t" + "\t" + "対象外" + "\t" + "\t" + amountOfInitialSales + "\t";
    slipTsv += "売上高" + "\t" + categoryOfInitialSales + "\t" + "課税売上 8%" + "\t" + "\t" + amountOfInitialSales + "\t";
    slipTsv += yearMonthDateFormat.format( dateOfInitialSales ) + " @ " + contractName  + "\t" + "\t" + invoiceTag + "\t";
    slipTsv += "\n";
    receivedTotal += amountOfInitialSales;
  }
  subnum++;
}

if( amountOfRunningSales !== 0 ){
  var amountOfAfterSecond = Math.floor( amountOfRunningSales / countOfRunningSales );
  var amountOfFirst = amountOfRunningSales - amountOfAfterSecond * (countOfRunningSales - 1);
  for( var i = 0; i < countOfRunningSales; i++ ){
    var tmp = new com.questetra.bpms.util.AddableDate( startMonthOfRunningSales.addMonths( i ).getTime() );
    if( tmp.before( dateOfPayment ) ){
      slipTsv += processInstance.getProcessInstanceId() + ("00" + subnum).slice(-2) + "\t";
      slipTsv += accountingDateFormat.format( tmp ) + "\t";
      if( i === 0 ){
        slipTsv += "売掛金" + "\t" + "\t" + "対象外" + "\t" + "\t" + amountOfFirst + "\t";
        slipTsv += "売上高" + "\t" + categoryOfRunningSales + "\t" + "課税売上 8%" + "\t" + "\t" + amountOfFirst + "\t";
        receivableTotal += amountOfFirst;
      }else{
        slipTsv += "売掛金" + "\t" + "\t" + "対象外" + "\t" + "\t" + amountOfAfterSecond + "\t";
        slipTsv += "売上高" + "\t" + categoryOfRunningSales + "\t" + "課税売上 8%" + "\t" + "\t" + amountOfAfterSecond + "\t";
        receivableTotal += amountOfAfterSecond;
      }
      slipTsv += yearMonthDateFormat.format( tmp ) + " @ " + contractName  + "\t" + "\t" + invoiceTag + "\t";
      slipTsv += "\n";
    }else{
      slipTsv += processInstance.getProcessInstanceId() + ("00" + subnum).slice(-2) + "\t";
      slipTsv += accountingDateFormat.format( tmp ) + "\t";
      if( i === 0 ){
        slipTsv += "前受金" + "\t" + "\t" + "対象外" + "\t" + "\t" + amountOfFirst + "\t";
        slipTsv += "売上高" + "\t" + categoryOfRunningSales + "\t" + "課税売上 8%" + "\t" + "\t" + amountOfFirst + "\t";
        receivedTotal += amountOfFirst;
      }else{
        slipTsv += "前受金" + "\t" + "\t" + "対象外" + "\t" + "\t" + amountOfAfterSecond + "\t";
        slipTsv += "売上高" + "\t" + categoryOfRunningSales + "\t" + "課税売上 8%" + "\t" + "\t" + amountOfAfterSecond + "\t";
        receivedTotal += amountOfAfterSecond;
      }
      slipTsv += yearMonthDateFormat.format( tmp ) + " @ " + contractName  + "\t" + "\t" + invoiceTag + "\t";
      slipTsv += "\n";
    }
  subnum++;
  }
}

/// Bank Records
// amountOfInvoice == receivableTotal + receivedTotal
// ( "CashIn" ==  amountOfInvoice - cardFee )

slipTsv += processInstance.getProcessInstanceId() + ("00" + subnum).slice(-2) + "\t";
slipTsv += accountingDateFormat.format( dateOfPayment ) + "\t";
slipTsv += "当座預金" + "\t" + "PayPal" + "\t" + "対象外" + "\t" + "\t" + (amountOfInvoice - cardFee) + "\t";
slipTsv += "売掛金" + "\t" + "\t" + "対象外" + "\t" + "\t" + receivableTotal + "\t";
slipTsv += yearMonthDateFormat.format( dateOfInvoice ) + " # " + contractName  + "\t" + "\t" + invoiceTag + "\t" + "未実現";
slipTsv += "\n";
if( receivedTotal > 0 ){
  slipTsv += processInstance.getProcessInstanceId() + ("00" + subnum).slice(-2) + "\t";
  slipTsv += accountingDateFormat.format( dateOfPayment ) + "\t";
  slipTsv += "\t" + "\t" + "\t" + "\t" + "\t";
  slipTsv += "前受金" + "\t" + "\t" + "対象外" + "\t" + "\t" + receivedTotal + "\t";
  slipTsv += yearMonthDateFormat.format( dateOfInvoice ) + " # " + contractName  + "\t" + "\t" + "\t" + "未実現";
  slipTsv += "\n";
}
if( cardFee > 0 ){
  slipTsv += processInstance.getProcessInstanceId() + ("00" + subnum).slice(-2) + "\t";
  slipTsv += accountingDateFormat.format( dateOfPayment ) + "\t";
  slipTsv += "支払手数料" + "\t" + "カード手数料(売上)" + "\t" + "非課税仕入" + "\t" + "\t" + cardFee + "\t";
  slipTsv += "\t" + "\t" + "\t" + "\t" + "\t";
  slipTsv += yearMonthDateFormat.format( dateOfInvoice ) + " # " + contractName  + "\t" + "\t" + "\t" + "未実現";
  slipTsv += "\n";
}


//// == ワークフローデータへの代入 / Data Updating ==
slipTsv = slipTsv.slice(0, -1); // remove "\n" code at the end of tsv
retVal.put( "q_slipTsv", slipTsv );
// Next to Converter (Tsv String to Excel-CSV File) *Manual#M415

[PayPal-Invoice:"1. Bill data check" screen]

[Data Items list]


[Free Download]
<Similar Models>
<<Related Articles>>

[Japanese Entry (和文記事)]