会计算法的好方法是什么


What is a good approach for an accounting algorithm?

我需要在PHP中创建一个计算以下内容的会计算法。

我正在开发一个应用程序,供会员每天缴纳固定金额的款项。假设每天的捐款额是200美元,会员可以在给定的天数内预付。

例如,如果捐款的开始日期是2015年4月1日,并且会员支付了600美元,则算法应将金额从2015年4月份1日分配到2015年4季度3日。

如果他在2015年4月10日支付下一笔捐款并支付2000美元,则算法应首先支付2015年4月份4日至2015年4季度10日期间总计1400美元的赤字,然后分配2015年4月末11日至2015年度4月13日期间总计600美元的余额。

我尝试使用以下代码,它试图添加逻辑来检测用户何时多付了钱,如果多付了钱的话,则添加如上所述均匀分配金额的算法。如果他少付了工资,算法应该在"拖欠者"行中添加一行,最后一个支付日期应该选择为供款表中最近添加的行。

public function actionBackdate() {
        $start = new DateTime("2015-03-1");
        $now=new DateTime();
        $now->modify('+1 day');
        $days = $now->diff($start);
        echo $now->format('Y-m-d g:i a');
        echo "<br/>";
        echo $days->format('%a')." have passed since";
        echo "<br/>";
        $contributionAmount=200;
        $TotalContributed=5400;
        $amountContributed=0;
        $oustandingBalance=0;
        $contributionDetails=array(
                                  "memberid"    =>4,
                                  "payment_mode"=>"CASH",
                                  "payment_for" =>"Chama Daily",
                                  "payment_ref" =>rand(9,9999),
                                  "amount"      =>"",
                                  "currency"    =>"KSH",
                                  "created_at"  =>"",
                                  "updated_at"  =>""
                                  );
        $defaulter=array(
                                  "memberid"    =>4,
                                  "currency"    =>"KSH",
                                  "amount_defaulted"=>"",
                                  "date_defaulted" =>"Daily Contrib",
                                  "fine_amount" =>50,
                                  "note"      =>"Contribution defaulter",
                                  "status"    =>0
                                  );
        for( $i=0;$i<(int)$days->format('%a')+1;$i++){
            //underpayment from expeted contribution amount
            if($TotalContributed<$contributionAmount && $TotalContributed>0 ){              
                echo "He had a balance of ".($contributionAmount-$TotalContributed)." at date ".$start->format('Y-m-d g:i a')."<br/>";
                $oustandingBalance+=($contributionAmount-$TotalContributed);
            }elseif($TotalContributed==0){
                // paid 0                 
                $oustandingBalance+=($contributionAmount-$TotalContributed);
                $defaulter['amount_defaulted']=$contributionAmount;
                $defaulter['date_defaulted']  =$start->format('Y-m-d H:i:s');
                $model=new ChamaDefaulter;
                $model->attributes=$defaulter;
                if(!$model->save()){
                    throw new Exception("Error saving details", 1);
                }
            }elseif($TotalContributed<0){
                // he has balance expected              
                $oustandingBalance+=$contributionAmount;
                $defaulter['amount_defaulted']=$contributionAmount;
                $defaulter['date_defaulted']  =$start->format('Y-m-d H:i:s');
                $model=new ChamaDefaulter;
                $model->attributes=$defaulter;
                if(!$model->save()){
                    throw new Exception("Error saving details", 1);
                }
            }else{
                //Contribution received as expected;               
                $amountContributed+=$contributionAmount;
                $contributionDetails["amount"]=$contributionAmount;
                $contributionDetails["date_paid"]=$start->format('Y-m-d H:i:s');                
                $model=new ChamaContribution;
                $model->attributes=$contributionDetails;
               if(!$model->save()){
                    throw new Exception("Error saving details", 1);
                }
            }
            $TotalContributed-=$contributionAmount;
            $start->modify('+1 day');
        }
        exit("User oustanding Balance is KSH $oustandingBalance");
    }

您要求我澄清我的评论,因此:

用户的余额可以为负数,以后的付款也可以为正数。

当然。你需要一张付款表,由于你每天都要收费,所以你需要每天都记一笔账。你可以每周收费,然后每周收费——这取决于你。

假设您只维护一个付款记录,并在需要时动态计算余额。您的条目可能如下所示:

User     Value    Purpose    Date
1        600      Payment    2015-04-03
1        -200     Daily      2015-04-03
1        -200     Daily      2015-04-04
1        -200     Daily      2015-04-05
1        -200     Daily      2015-04-06

你可以在这里看到,这个用户在4月3日成为会员,每天被收取200多英镑的费用。他们的余额可以计算为-200(假设以上是该用户的所有记录);你是否允许他们在该州参加会员活动完全取决于你。例如,您可以允许用户默认一定的天数,或者只默认一定的数量。

当这个用户进行新的支付时,会以通常的方式添加,这可能会也可能不会让他们重新获得信用。

由于付款存在分歧,请始终添加数据行,不要更新它们-如果您丢失了历史记录,则无法解决财务纠纷

存储用户的余额不如存储他们的个人付款重要——你可以根据他们的付款减去他们的费用来计算他们的余额,但你不能根据他们的余额来计算他们。

让我们假设你不接受我的建议,只使用一个平衡表:

User     Balance    Last updated
1        -200       2015-04-06

现在用户声称他们昨天付款了,这可能是真的,也可能不是真的。你可以要求他们出示证明(例如支付网关收据),但如果你能在自己的系统中找到这些信息,那就容易多了。