chippyash/simple-accounts

此包已被废弃,不再维护。未建议替代包。

简单复式记账

2.1.0 2018-01-14 10:04 UTC

This package is auto-updated.

Last update: 2022-02-01 12:47:47 UTC


README

通知

此项目已停止。没有足够的动力来维持它。如果您想接管它,请与我联系。或者简单地进行分支并继续。

质量保证

PHP 5.5 PHP 5.6 PHP 7 Build Status Test Coverage Code Climate

以上徽章和此文档代表当前的开发分支。
一般来说,我不会在没有测试、覆盖率和可用性可接受的情况下推送到GitHub。
这可能不会在短时间内成立;在假期,需要为其他下游项目编写代码等。如果您需要稳定的代码,请使用标记版本。有关标记版本的最终文档,请阅读该版本中的README文件。

查看测试合同

生命终结通知

2018年3月,将停止为此库提供PHP <5.6的开发者支持。PHP的老版本现在使用得很少,维护兼容性的额外努力并不有效。请参阅PHP版本统计了解具体数字。

什么是?

提供一个简单的复式记账系统,可以用作更大应用程序中的组件。

特性

  • 账户表(参见此处对账户表的合理解释)

    • 您可以定义自己的账户结构
  • 账户类型

    • DR
      • 资产
        • 银行
        • 客户
      • 费用
    • CR
      • 收入
      • 负债
        • 权益
        • 供应商
  • 可以通过简单的界面保存和检索账户表

  • 组织概念,可以拥有多个账户表

  • 考虑到了幻想货币

  • 可扩展的日记系统,允许记录账户交易

为什么?

虽然已经有了完整的会计系统,但需要巨大的集成工作,但某些应用程序只需要能够保持某种形式的内部账户。这个库是我多年前为客户编写的,用于记录网站上的游戏积分。使用复式记账范式允许网站所有者跟踪谁收集了积分以及如何收集,同时还可以看到这对其业务意味着什么,因为游戏积分通过折扣和奖品转化为客户的现实世界价值。

何时使用?

当前库支持组织、会计科目表、日记账和受控账户。

路线图

  • 会计
    • 关闭账户
  • 报告
    • 资产负债表
    • 试算平衡表
    • 损益表

如果您想了解更多,请提出建议,或者更好的是,分叉它并提供一个拉取请求。

查看ZF4 包获取更多包

如何

编码基础

创建新的会计科目表

手动创建
use SAccounts\Chart;
use SAccounts\Organisation;
use Chippyash\Currency\Factory as Currency;
use Chippyash\Type\Number\IntType;
use Chippyash\Type\String\StringType;

$org = new Organisation(new IntType(1), new StringType('Foo'), Currency::create('gbp'));
$chart = new Chart(new StringType('Foo Chart'), $org);
使用会计师

会计师是一个有用的“人”!但是,像往常一样,它们需要代价:他们需要一个文件管理员为他们做一些工作,您必须提供给他们作为报酬。
文件管理员实现了AccountStorageInterface。提供了一个简单的示例,允许将会计科目保存为序列化的PHP文件,以帮助您入门,但当然您也可以创建自己的。

use SAccounts\Accountant;
use SAccounts\Storage\Account\Serialized;

$fileClerk = new Serialized(new StringType('/path/To/My/Account/Store'));
$accountant = new Accountant($fileClerk);

要通过会计师创建会计科目,您仍然需要告诉它新会计科目是针对哪个组织的,以及您想使用哪个COA模板。提供了一个简单的“个人账户”模板,它是一个XML文件。您可以创建并提供自己的。

use SAccounts\ChartDefinition;
use SAccounts\Organisation;
use Chippyash\Type\String\StringType;
use Chippyash\Type\Number\IntType;
use Chippyash\Currency\Factory as Currency;

$def = new ChartDefinition(new StringType('/path/to/definitions/personal.xml'));
$org = new Organisation(new IntType(1), new StringType('Foo'), Currency::create('gbp'));
$chart = $accountant->createChart(new StringType('Name of Chart'), $org, $def);

向会计科目表添加账户

一旦您有了会计科目表,您可能想向其中添加新的账户。如果您从头开始手动创建了一个,它将没有根账户,因此您需要先添加那个。所有账户都通过一个“名义代码”来识别。这是Nominal类型(基于chippyash\Type\String\DigitType)的,是一个数字字符串。您可以使用任何名义代码结构,但请确保您为自己留下足够的空间来添加您想要的账户。查看definitions/personal.xml以获取一些见解。

账户还需要一个账户类型。这些在AccountType枚举类中定义,并且简单地通过调用类常量作为方法来创建。有关枚举的更多信息,请参阅致谢部分的链接。

  • 添加根账户
use SAccounts\Nominal;
use SAccounts\AccountType;

ac1 = new Account($chart, new Nominal('2000'), AccountType::ASSET(), new StringType('Asset'));
$chart->addAccount($ac)
  • 添加子账户
ac2 = new Account($chart, new Nominal('2100'), AccountType::BANK(), new StringType('Bank'));
$chart->addAccount($ac, $ac1->id())

保存会计科目表

$accountant->fileChart($chart));

检索会计科目表

在检索会计科目表时,您需要知道它所属组织的ID

$chart = $accountant->fetchChart(new StringType('Name of Chart'), new IntType(1));

这允许您为组织创建多个COA,这可能会让您能够保留特定任务的COA或不同货币的COA。

向账户中记录

您可以向任何账户进行借方和贷方记录。显然,为了维护复式记账规则,您通常会在任何交易中做一对借方和贷方记录。

您不需要跟踪账户,只需通过它们的ID从会计科目表中获取它们即可。

虽然这不是强制性的,但建议您在创建借方和贷方金额时使用与您组织相同的货币。

//can be used in most situations
$amount = Currency::create($chart->getOrg()->getCurrencyCode(), 12.26);

//use this method if locale issues are important or you are using a fantasy currency
$amount = clone $chart->getOrg()->getCurrency();
$amount->setAsFloat(12.26);
//or use set() if you know your currency precision
$amount->set(1226);

$chart->getAccount(new Nominal('1000'))->debit($amount);
$chart->getAccount(new Nominal('2000'))->credit($amount);

获取账户值

所有账户值均以 chippyash\Currency\Currency 对象表示。

  • 借方和贷方金额
$debitAsInt = $chart->getAccount(new Nominal('1000'))->getDebit()->get();
$debitAsFloat = $chart->getAccount(new Nominal('1000'))->getDebit()->getAsFloat()
echo $chart->getAccount(new Nominal('1000'))->getDebit()->display();
$creditAsInt = $chart->getAccount(new Nominal('1000'))->getCredit()->get();
$creditAsFloat = $chart->getAccount(new Nominal('1000'))->getCredit()->getAsFloat()
echo $chart->getAccount(new Nominal('1000'))->getCredit()->display();
  • 账户余额

对于所有账户类型(除DUMMY和REAL外),获取账户余额

$balanceAsInt = $chart->getAccount(new Nominal('1000'))->getBalance()->get();
$balanceAsFloat = $chart->getAccount(new Nominal('1000'))->getBalance()->getAsFloat();
echo $chart->getAccount(new Nominal('1000'))->getBalance()->display();

余额遵循DR和CR账户的惯例。

  • DR余额 = dr-cr
  • CR余额 = cr-dr

使用日记账

虽然账户记录了任何给定时间点的价值状态,而账簿持有账户集合(树)的状态,但日记账负责记录导致账户当前状态的交易历史。

您可以使用库而不使用日记账,但大多数系统将需要一个交易历史。会计师可以利用可选的'Journalist'来实现JournalStorageInterface,创建、保存和修改日记账及其所记录的交易。

您必须首先以JournalStorageInterface的形式提供一个Journalist。示例是提供的,Accounts\Storage\Journal\Xml将日记账及其交易存储到XML文件中。您可以提供自己的以存储您想要使用的任何其他存储机制。

use SAccounts\Storage\Journal\Xml as Journalist;

$accountant->setJournalist(new Journalist(new StringType('/path/to/my/journal/store/folder')));

创建日记账

use Chippyash\Currency\Factory as Currency;

$journal = $accountant->createJournal(new StringType('My Journal'), Currency::create('gbp'));

在大多数情况下,您会将组织、图表与日记账关联起来,因此使用相同的货币是有意义的

$journal = $accountant->createJournal(new StringType('My Journal'), $chart->getOrg()->getCurrency());

获取您已创建的日记账

use SAccounts\Storage\Journal\Xml as Journalist;

$accountant->setJournalist(new Journalist(new StringType('/path/to/my/journal/store/folder')));
$journal = $accountant->fetchJournal();

如果您修改了其定义,您还可以通过会计师存储日记账

在日记账中创建交易

您可以通过调用它们的适当存储机制(请参阅代码、测试和图表)自行管理日记账和图表之间的链接,或者更简单,请会计师为您做这件事。在任何情况下,您首先需要一个交易。交易通过SAccounts\Transaction\SplitTransactionSAccounts\Transaction\SimpleTransaction提供。SimpleTransaction作为创建和写入只包含一对平衡借方和贷方金额的交易的帮助器提供。SimpleTransaction

use SAccounts\Transaction\SimpleTransaction;
use SAccounts\Nominal;

$drAc = new Nominal('0000');
$crAc = new Nominal('1000');
$amount = Currency::create($chart->getOrg()->getCurrencyCode(), 12.26);
$txn = new  SimpleTransaction($drAc, $crAc, $amount);

在创建SimpleTransaction时,您可以设置可选的第四个参数

$txn = new  SimpleTransaction($drAc, $crAc, $amount, new StringType('This is a note'));

默认情况下,交易日期和时间设置为now().在创建SimpleTransaction时,您可以设置可选的第五个参数并提供您自己的DateTime对象。

$txn = new  SimpleTransaction($drAc, $crAc, $amount, new StringType(''), new \DateTime('2015-12-03T12:14:30Z));

要记录交易并更新账户图表,您现在可以使用会计师再次操作

$txn = $accountant->writeTransaction($txn, $chart, $journal);
//or
$accountant->writeTransaction($txn, $chart, $journal);

交易现在将设置其事务id,您可以通过以下方式恢复

$txnId = $txn->getId() //returns IntType

您不需要保存日记账,因为它本质上就是事务性的,但不要忘记在完成写入交易后保存您的图表。

交易的全部功能由SplitTransaction提供。记住,当你从日记账中读取交易时,它们将以SplitTransaction格式出现。拆分交易允许您拥有,比如说,一个借方条目和三个贷方条目。只要总借方条目金额等于总贷方条目金额,您就有一个平衡的交易,即有效的双重条目交易。

力量越大,复杂性也越大,正如您所期望的那样!

use SAccounts\Transaction\SimpleTransaction;
use SAccounts\Transaction\Entry;
use SAccounts\Nominal;
use Chippyash\Type\String\StringType;
use Chippyash\Currency\Factory as Currency;

$txn = new SplitTransaction() // date == now(), note == ''
$txn = new SplitTransaction(new DateTime());
$txn = new SplitTransaction(null, new StringType('foo'));
$txn = new SplitTransaction(new DateTime(), new StringType('foo'));

//the following is analogous to a SimpleTransaction
$note = new StringType('foo bar');
$dt = new \DateTime();
$amount = Currency::create('gbp', 12.26);
$txn = (new SplitTransaction($dt, $note))
    ->addEntry(new Entry(new Nominal('0000'), $amount, AccountType::DR()))
    ->addEntry(new Entry(new Nominal('1000'), $amount, AccountType::CR()));
    

在创建条目时,您需要告诉它

  • 使用哪个账户
  • 金额是多少
  • 是否借记或贷记

为了创建真正的拆分交易,让我们使用以下示例

  • 银行账户:3001
  • 增值税账户:6007
  • 项目账户:9056
  • 总交易金额为120.00英镑,商品100英镑,增值税20英镑
$txn = (new SplitTransaction($dt, $note))
    ->addEntry(new Entry(new Nominal('3001'), Currency::create('gbp', 120), AccountType::DR()))
    ->addEntry(new Entry(new Nominal('6007'), Currency::create('gbp', 20), AccountType::CR()))
    ->addEntry(new Entry(new Nominal('9056'), Currency::create('gbp', 100), AccountType::CR()));

总体来说,创建不平衡的交易是一个非常糟糕的主意,你可以使用checkBalance()来检查这一点,如果交易平衡则返回true,否则返回false。

你也可以使用isSimple()方法来简单地检查交易是否符合简单交易的要求。

$drAc = $txn->getDrAc();
if ($txn->isSimple()) {
    $actualDrAc = $drAc[0];
} else {
    //you have an array of debit accounts, so process them
}

getCrAc()获取交易中的贷方账户。

SplitTransaction的getEntries()方法返回一个SAccounts\Transaction\Entries集合的条目。

控制账户

在会计定义中的控制账户意义上,简单的账户控制账户可以用来指向你的账簿中的调整账户。然而,在实际应用中,控制账户有一个更广泛的使用范围;即指向账簿中的特定账户。因此,在这个意义上,简单的账户控制账户只是指向另一个账户的指针。

在编程术语中,我们设置一个控制账户的集合(Control\Links)。以下是一个例子:

你有一个系统,其中你想将通用现金交易发送到特定的账户

  • 银行账户的现金收付
  • 购买到“杂项”账户
  • 销售到“现金销售”账户

问题在于,随着你的COA(或业务)的增长,你想要在COA中使用的实际账户可能会发生变化。通过控制账户解引用实际账户,你的主代码可以保持不变,同时允许你随时重新配置。

use SAccounts\Control;

$linkArray = [
    new Control\Link(new StringType('bank'), new Nominal('1000')),
    new Control\Link(new StringType('sundries'), new Nominal('2000')),
    new Control\Link(new StringType('cash sales'), new Nominal('3000')),
];
$ctrlAcs = (new Control\Links($linkArray));

$txn = (new SplitTransaction($dt, $note))
    ->addEntry($ctrlAcs->getLinkId(new StringType('bank')), Currency::create('gbp', 120), AccountType::DR()))
    ->addEntry($ctrlAcs->getLinkId(new StringType('cash sales')), Currency::create('gbp', 120), AccountType::CR()));

$txn2 = (new SplitTransaction($dt, $note))
    ->addEntry($ctrlAcs->getLinkId(new StringType('bank')), Currency::create('gbp', 90), AccountType::CR()))
    ->addEntry($ctrlAcs->getLinkId(new StringType('sundries')), Currency::create('gbp', 90), AccountType::DR()));

这实际上非常简单。我没有包括控制账户的存储机制,因为在你的应用中可能会依赖注入它们,但是定义文件夹中有一个XML XSD,在docs目录中有示例XML文件。在实践中,你可能会在应用中使用多个控制账户集合。

类图

UML Diagram UML Diagram UML Diagram

修改库

  1. 分支它
  2. 编写测试
  3. 修改它
  4. 发起一个pull请求

发现了一个你无法解决的错误吗?

  1. 分支它
  2. 编写测试
  3. 发起一个pull请求

注意。在pull请求之前,确保你rebase到HEAD。

或者 - 提出一个问题票据。

在哪里?

该库托管在Github上。它可在Packagist.org找到。

安装

安装Composer

生产环境

    "chippyash/simple-accounts": "~2"

开发环境

克隆此仓库,然后在本地仓库根目录中运行Composer以拉取依赖项

    git clone git@github.com:chippyash/Simple-Accounts.git Accounts
    cd Accounts
    composer update

要运行测试

    cd Accounts
    vendor/bin/phpunit -c test/phpunit.xml test/

感谢

在早期,当首次编写Simple Accounts时,我不得不自己编写大量的支持代码。在这个版本中,我已经能够利用他人的工作成果。除了常规的PHPUnit和vfsStream(用于编写测试代码)之外,我还想突出一些其他的内容。

  • PHP Enum:PHP中枚举的优雅实现
  • Tree:支持访问者模式,便于扩展的简单树组件

许可证

此软件库在GNU GPL V3或更高版本的许可证下发布。

此软件库版权所有(c)2015-2018,Ashley Kitson,英国

此软件库可提供商业许可证,请联系作者。通常对有价值的用途是免费的,但这可以绕过GPL许可证的限制,该许可证不允许无限制地将此代码包含在商业作品中。

历史

V1.0.0 原始发布

V1.1.0 添加了期刊

V1.2.0

  • 将chippyash\Accounts命名空间替换为SAccounts
  • 废弃了Transaction,请使用SimpleTransaction(Transaction代理到SimpleTransaction,并将在未来被删除)
  • 引入了SplitTransactions,优先使用这些
  • 为了适应分割事务,对XML期刊文件格式进行了BC中断

V1.3.0 添加了控制账户

V1.4.0 更新依赖项

V1.4.1 添加到包的链接

V1.4.2 验证PHP 7兼容性

V1.4.3 代码清理

V1.4.4 更新依赖项

V1.4.5 更新PhpUnit测试套件

V1.4.6 更新构建脚本

V2.0.0 在某些接口定义中进行了BC中断,以支持基于数据库系统的实现。

V2.1.0 添加设置图表根节点的能力