ekmungai/eloquent-ifrs

专注于IFRS合规报告的Eloquent复式记账


README

Build Status Test Coverage Maintainability PHP 8.0 License: MIT Total Downloads Latest Stable Version

此包允许任何Laravel应用通过提供功能齐全且可配置的复式记账子系统来生成与国际财务报告准则兼容的财务报表。

该包支持多个实体(公司)、账户分类、交易分配、年度期初余额以及增值税交易的记账。交易还通过直接数据库更改来防止篡改,确保账簿的完整性。根据逾期时间长短,还可以显示客户和供应商的未结金额,使用可配置的时间段(当前、31-60天、61-90天等)。最后,该包还支持在报告期内自动过入外汇差异交易,以及在固定结算汇率下将外币账户余额进行转换。

此包是 microbooks.io 的社区倡议。

目录

安装

使用composer将包安装到您的laravel或lumen应用中。Eloquent IFRS需要PHP版本8.0.2和Eloquent版本8及以上。

用于生产

composer require "ekmungai/eloquent-ifrs"

如果使用Lumen,请确保通过在引导文件夹中的 app.php 中添加 IFRSServiceProvider 来将包注册到您的应用程序中。

<?php

use IFRS\IFRSServiceProvider;

require_once __DIR__.'/../vendor/autoload.php';
...

/*
|--------------------------------------------------------------------------
| Register Service Providers
|--------------------------------------------------------------------------
|
| Here we will register all of the application's service providers which
| are used to bind services into the container. Service providers are
| totally optional, so you are not required to uncomment this line.
|
*/

// $app->register(App\Providers\AppServiceProvider::class);
// $app->register(App\Providers\AuthServiceProvider::class);
// $app->register(App\Providers\EventServiceProvider::class);
$app->register(IFRSServiceProvider::class);
  ...
}
...
?>

然后运行迁移以创建数据库表。

php artisan migrate

用于开发

克隆此存储库,然后在本地存储库根目录中运行Composer以拉入依赖项。

git clone git@github.com/ekmungai/eloquent-ifrs eloquent-ifrs
cd eloquent-ifrs
composer update

要运行测试

cd eloquent-ifrs
vendor/bin/phpunit

配置

关于账户/交易类型、报告标题和部分名称以及账户代码的名称,该包安装时采用默认设置。要调整这些设置,请使用Laravel artisan publish命令将ifrs配置安装到您的应用程序的config文件夹中,您可以在此处编辑它。

php artisan vendor:publish

使用

有关此包的完整文档,请参阅 此处

DB 冲突

如果您的 User 模型与 App\User 不同,请使用 vendor:publish 发布配置文件,并更新您的 User 模型的命名空间。

打开您的 User 模型并实现以下接口,并包含该特质。

<?php

use IFRS\Traits\IFRSUser;
use IFRS\Traits\Recycling;

use IFRS\Interfaces\Recyclable;
...

class User ... implements Recyclable {
  ...
  use IFRSUser;
  use Recycling;
  ...
}
...
?>

示例

以下简单示例涵盖了四种场景,以演示包的使用。首先,描述向客户进行的现金销售,然后是向客户进行的信用销售(发票),然后是用于运营费用的现金采购,最后是从供应商处进行非运营目的(资产采购)的信用采购(账单)。

首先,我们将设置公司(报告实体)和记录交易所需的账户。(假设已存在已注册的用户)

use IFRS\Models\Entity;
use IFRS\Models\Currency;

$entity = Entity::create([
    "name" => "Example Company",
]);

//Entities require a reporting currency
$currency = Currency::create([
    "name" => "Euro",
    "currency_code" => "EUR"
]);

// Set the currency as the Entity's Reporting Currency 
$entity->currency_id = $currency->id;
$entity->save();

我们还需要适用于实体的增值税税率。

use IFRS\Models\Vat;

$outputVat = Vat::create([
    'name' => "Standard Output Vat",
    'code' => "O",
    'rate' => 20,
    'account_id' => Account::create([
        'name' => "Sales VAT Account",
        'account_type' => Account::CONTROL,
    ])
]);

$inputVat = Vat::create([
    'name' => "Standard Input Vat",
    'code' => "I",
    'rate' => 10,
    'account_id' =>  Account::create([
        'name' => "Input VAT Account",
        'account_type' => Account::CONTROL,
    ])
]);

现在,我们将设置一些账户

use IFRS\Models\Account;

$bankAccount = Account::create([
    'name' => "Bank Account",
    'account_type' => Account::BANK,
]);

$revenueAccount = Account::create([
    'name' => "Sales Account",
    'account_type' => Account::OPERATING_REVENUE,
]);

$clientAccount = Account::create([
    'name' => "Example Client Account",
    'account_type' => Account::RECEIVABLE,
]);

$supplierAccount = Account::create([
    'name' => "Example Supplier Account",
    'account_type' => Account::PAYABLE,
]);

$opexAccount = Account::create([
    'name' => "Operations Expense Account",
    'account_type' => Account::OPERATING_EXPENSE,
]);

$assetAccount = Account::create([
    'name' => "Office Equipment Account",
    'account_type' => Account::NON_CURRENT_ASSET,
]);

现在,我们将创建一些在账簿中的交易,之后我们将生成一些报告。但首先,需要一个报告期

use IFRS\Models\ReportingPeriod;

$period = ReportingPeriod::create([
    'period_count' => 1,
    'calendar_year' => 2022,
]);

现在所有账户都准备就绪,我们可以创建第一条交易,一笔现金销售

use IFRS\Transactions\CashSale;

$cashSale = CashSale::create([
    'account_id' => $bankAccount->id,
    'date' => Carbon::now(),
    'narration' => "Example Cash Sale",
]); // Intermediate save does not record the transaction in the Ledger

到目前为止,交易只有借贷方的单边,因此我们为另一方创建一个项目

use IFRS\models\LineItem;

$cashSaleLineItem = LineItem::create([
    'account_id' => $revenueAccount->id,
    'narration' => "Example Cash Sale Line Item",
    'quantity' => 1,
    'amount' => 100,
]);

$cashSaleLineItem->addVat($outputVat);
$cashSale->addLineItem($cashSaleLineItem);
$cashSale->post(); // This posts the Transaction to the Ledger

其余的交易

use IFRS\Transactions\ClientInvoice;

$clientInvoice = ClientInvoice::create([
    'account_id' => $clientAccount->id,
    'date' => Carbon::now(),
    'narration' => "Example Credit Sale",
]);

$clientInvoiceLineItem = LineItem::create([
    'account_id' => $revenueAccount->id,
    'narration' => "Example Credit Sale Line Item",
    'quantity' => 2,
    'amount' => 50,
]);

$clientInvoiceLineItem->addVat($outputVat);
$clientInvoice->addLineItem($clientInvoiceLineItem);

//Transaction save may be skipped as post() saves the Transaction automatically
$clientInvoice->post();

use IFRS\Transactions\CashPurchase;

$cashPurchase = CashPurchase::create([
    'account_id' => $clientAccount->id,
    'date' => Carbon::now(),
    'narration' => "Example Cash Purchase",
]);

$cashPurchaseLineItem = LineItem::create([
    'account_id' => $opexAccount->id,
    'narration' => "Example Cash Purchase Line Item",
    'quantity' => 4,
    'amount' => 25,
]);


$cashPurchaseLineItem->addVat($inputVat);
$cashPurchase->addLineItem($cashPurchaseLineItem);
$cashPurchase->post();

use IFRS\Transactions\SupplierBill;

$supplierBill = SupplierBill::create([
    'account_id' => $supplierAccount->id,
    'date' => Carbon::now(),
    'narration' => "Example Credit Purchase",
]);

$supplierBillLineItem = LineItem::create([
    'vat_id' => $inputVat->id,
    'account_id' => $assetAccount->id,
    'narration' => "Example Credit Purchase Line Item",
    'quantity' => 4,
    'amount' => 25,
]);

$supplierBillLineItem->addVat($inputVat);
$supplierBill->addLineItem($supplierBillLineItem);
$supplierBill->post();

use IFRS\Transactions\ClientReceipt;

$clientReceipt = ClientReceipt::create([
    'account_id' => $clientAccount->id,
    'date' => Carbon::now(),
    'narration' => "Example Client Payment",
]);

$clientReceiptLineItem = LineItem::create([
    'account_id' => $bankAccount->id,
    'narration' => "Part payment for Client Invoice",
    'quantity' => 1,
    'amount' => 50,
]);

$clientReceipt->addLineItem($clientReceiptLineItem);
$clientReceipt->post();

我们可以将收据分配给部分核销上述发票

use IFRS\Models\Assignment;

echo $clientInvoice->clearedAmount; //0: Currently the Invoice has not been cleared at all
echo $clientReceipt->balance; //50: The Receipt has not been assigned to clear any transaction

$assignment = Assignment::create([
    'assignment_date'=> Carbon::now(),
    'transaction_id' => $clientReceipt->id,
    'cleared_id' => $clientInvoice->id,
    'cleared_type'=> $clientInvoice->clearedType,
    'amount' => 50,
]);

echo $clientInvoice->clearedAmount; //50
echo $clientReceipt->balance; //0: The Receipt has been assigned fully to the Invoice

利润表(损益表)

use IFRS\Reports\IncomeStatement;

$incomeStatement = new IncomeStatement(
    "2021-01-01",   // Report start date
    "2021-12-31",   // Report end date
)->getSections();// Fetch balances from the ledger and store them internally

/**
* this function is only for demonstration and
* debugging use and should never be called in production
*/
dd($incomeStatement->toString());

Example Company
Income Statement
For the Period: Jan 01 2021 to Dec 31 2021

Operating Revenues
    Operating Revenue        200 (100 cash sales + 100 credit sales)

Operating Expenses
    Operating Expense        100 (cash purchase)
                        ---------------
Operations Gross Profit      100

Non Operating Revenues
    Non Operating Revenue    0
                        ---------------
Total Revenue                100

Non Operating Expenses
    Direct Expense           0
    Overhead Expense         0
    Other Expense            0
                        ---------------
Total Expenses               0
                        ---------------
Net Profit                   100
                        ===============

资产负债表

use IFRS\Reports\BalanceSheet;

$balanceSheet = new BalanceSheet(
    "2021-12-31"  // Report end date
)->getSections();

/**
* again to emphasize, this function is only for demonstration and
* debugging use and should never be called in production
*/
dd($balanceSheet->toString());

Example Company
Balance Sheet
As at: Dec 31 2021

Assets
    Non Current Asset        120 (asset purchase)
    Receivables              70  (100 credit sale + 20 VAT - 50 client receipt)
    Bank                     50  (120 cash sale - 120 cash purchase + 50 client receipt)
                        ---------------
Total Assets                 240

Liabilities
    Control Account          20  (VAT: 20 cash sale + 20 credit sale - 10 cash purchase - 10 credit purchase)
    Payable                  120 (100 credit purchase + 20 VAT)
                        ---------------
Total Liabilities            140

                        ---------------
Net Assets                   100
                        ===============

Equity
    Income Statement         100
                        ---------------
Total Equity                 100
                        ===============

虽然利润表和资产负债表是年末(IFRS)报告的最终目标,但该套件还提供了包括账户报表在内的中期报告,账户报表按时间顺序列出所有已记入账户的交易,并以账户当前余额结束;账户报表类似于账户报表,区别在于报告只显示未清账(未核销)的交易,而不是列出构成期末余额的所有交易。

在上面的例子中

use IFRS\Reports\AccountStatement;
use IFRS\Reports\AccountSchedule;

$transactions = new AccountStatement($clientAccount)->getTransactions();

dd($transactions);

array:2[
  ["transaction" => ClientInvoice, "debit" => 120, "credit" => 0, "balance" => 120],
  ["transaction" => ClientReceipt, "debit" => 0, "credit" => 50, "balance" => 70]
]

$transactions = new AccountSchedule($clientAccount, $currency)->getTransactions();

dd($transactions);

array:1[
  ["transaction" => ClientInvoice, "amount" => 120, "cleared" => 50, "balance" => 70],
]

变更日志

请参阅变更日志了解有关最近更改的更多信息。

参与其中

我非常清楚,作为一名受过专业训练的会计师,我可能使用了某些惯例、定义和样式,虽然对我来说看似显而易见,但对其他开发者可能并不那么清晰。因此,我非常欢迎并非常感谢任何关于该包使用简便性的反馈,以便我使它对尽可能多的人更有用。

贡献

  1. 进行Fork
  2. 创建功能分支(git checkout -b feature/fooBar
  3. 为该功能编写测试
  4. 提交您的更改(git commit -am '添加一些fooBar'
  5. 推送到分支(git push origin feature/fooBar
  6. 创建一个新的拉取请求

路线图

  • 添加现金流量表
  • Laravel 8 兼容性
  • 添加多货币支持
  • 扩展税务功能

许可证

本软件免费分发,遵循MIT许可证

参考文献