【问题标题】:What is a good approach for an accounting algorithm?会计算法的好方法是什么?
【发布时间】:2015-04-06 14:20:17
【问题描述】:

我需要在 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");
    }

【问题讨论】:

  • 尝试了什么?您究竟在哪里挣扎?
  • 您可以运行每日作业,从用户的余额表中减去每日金额并将其添加到付款表中。用户的余额可以为负数,并通过以后的付款变为正数。由于付款可能会出现分歧,因此始终添加数据行,不要更新它们 - 如果您丢失了历史记录,那么您将无法解决财务纠纷。
  • (投票结束,但是上面应该给你一些继续的东西。我们可以先看看你的数据库模式吗?那将是一个好的开始)。
  • 感谢您的编辑 - 大多数被提示输入代码的人再也不会回来了!您现在能概括一下这段代码的问题吗? (随时在 cmets 中回复,但此信息也可以添加到问题中,因此新读者无需费力浏览 cmets 即可发现实际问题。
  • @halfer 我添加了我最初拥有的代码段,contributionDetails 数组包含每个用户的每个贡献的详细信息,并将其作为一行插入以供将来参考 defaulter 数组包含另一行 defaulter 详细信息例如默认金额等

标签: php algorithm sorting accounting


【解决方案1】:

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

用户的余额可以为负数,并通过以后的付款变为正数。

当然。您将需要一个付款表,并且由于您每天收费,因此您需要每天输入一个条目。您同样可以每周收费,然后每周收费 - 这取决于您。

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

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

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

【讨论】:

  • 谢谢@halfer,因为这让我实现了这个逻辑,我一定会给你反馈。问候
猜你喜欢
  • 1970-01-01
  • 2014-10-06
  • 2021-06-26
  • 2014-02-20
  • 1970-01-01
  • 2017-06-27
  • 2012-05-14
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多