ezesha/end-year-reports 问题修复 & 功能扩展

解决BUG、新增功能、兼容多环境部署,快速响应你的开发需求

邮箱:yvsm@zunyunkeji.com | QQ:316430983 | 微信:yvsm316

ezesha/end-year-reports

Composer 安装命令:

composer require ezesha/end-year-reports

包简介

Asynchronous end-year financial report generation module for CodeIgniter 4 (SQS-backed worker pipeline).

README 文档

README

Asynchronous end‑year financial report generation for CodeIgniter 4.

A user picks an office and a closure date and clicks Generate Package; the HTTP request enqueues the job on Amazon SQS (LocalStack‑friendly) and returns immediately, a background worker runs an ordered pipeline (Trial Balance → Income Statement → Balance Sheet), writes the results back, and the browser polls until the package is READY. Failed jobs self‑heal via a retry command.

This module is a self‑contained CodeIgniter 4 package: controllers, worker commands, model, migration, services, views and frontend assets, all under the Ezesha\EndYearReports\ namespace and auto‑discovered by the framework.

Requirements

  • PHP ^8.1
  • CodeIgniter 4 ^4.4
  • aws/aws-sdk-php ^3.0 (pulled in automatically)
  • An SQS queue — real AWS, or LocalStack for local dev
  • codeigniter4/tasks (optional) — only if you want the bundled scheduled workers

Installation

1. Require the package

Published to a Git host / Packagist:

composer require ezesha/end-year-reports

Or, while developing it locally, add a path repository to the application's composer.json and require it:

{
    "repositories": [
        { "type": "path", "url": "../packages/end-year-reports" }
    ],
    "require": {
        "ezesha/end-year-reports": "*"
    }
}
composer update ezesha/end-year-reports

CodeIgniter auto‑discovers the module's routes, commands, migrations, services and config as soon as Composer registers the namespace — no manual wiring in App\Config\* is required (Config\Modules::$discoverInComposer must stay true, which is the default).

2. Configure the environment

Add to the application .env:

# SQS / AWS
sqs_url                 = "http://sqs.eu-west-1.localhost.localstack.cloud:4566/000000000000/generate-reports"
aws.region              = "eu-west-1"
aws.credentials_profile = "default"
aws.endpoint            = "http://localhost:4566"   # LocalStack; drop for real AWS

# Optional — real AWS credentials (default to mock values for LocalStack)
# aws.access_key_id     = "AKIA..."
# aws.secret_access_key = "..."

3. Run the migration

The migration lives in the package namespace, so run migrations for all namespaces (or target this one):

php spark migrate --all
# or
php spark migrate -n "Ezesha\EndYearReports"

4. Publish the frontend assets

Copies the module's JS and CSS into the app's public/ directory:

php spark endyearreports:publish

This writes public/ezesha/js/end_year_report/* and public/ezesha/styles/end_year_report.css, which the shipped view references at /ezesha/js/... and /ezesha/styles/.... The ezesha/ sub-folder namespaces the assets so they never collide with the host app's own public/js or public/styles.

5. Run the worker

# Drain the queue once (good for a cron tick / supervisor loop)
php spark workers:process-reports --once

# Or drain a batch and exit early when empty
php spark workers:process-reports --max-messages 50

# Or run as a long-lived daemon (10s long-poll)
php spark workers:process-reports

Open /end_year_report in the browser, choose an office and closure date, and click Generate Package.

Usage summary

Route Purpose
GET /end_year_report The dashboard web page
GET /api/reports/office/{officeId}/{date} Enqueue + poll; returns PROCESSING/READY/FAILED
Command Purpose
workers:process-reports [--once] [--max-messages N] Consume the queue and run the compilation pipeline
workers:retry-failed [--max-age-hours N] [--dry-run] Re‑queue reports stuck in the failed state
endyearreports:publish Publish frontend assets into public/ezesha/

API states

The API is idempotent per (office_id, closure_date) (enforced by a unique key) and returns a queue_state:

  • PROCESSING (202) — queued / in flight; the frontend polls every 5s.
  • READY (200) — compiled; response carries the three statements under data.
  • FAILED (500) — pipeline rolled back, or the job stalled past the threshold.

A user "Generate" click sends ?retry=1 to clear a previous failure and re‑run; passive polls omit it so genuine failures surface instead of looping.

Configuration & extension

Everything tunable lives in Ezesha\EndYearReports\Config\EndYearReports. Override it by publishing an App\Config\EndYearReports class (same short name) in the host app — CodeIgniter's Factories resolve the app namespace first.

Property Default Meaning
$dataProvider MockFinancialDataProvider Class that supplies the raw financial package
$pipeline trial → income → balance Ordered stageKey => serviceClass map
$staleThresholdSeconds 240 When a pending job is treated as stalled/failed
$sqsUrl / $aws* env‑driven Connection settings (host .env overrides at construct time)

Plugging in real data (the important one)

The shipped MockFinancialDataProvider returns a static fixture so the module runs out of the box. To feed real ledger data, implement FinancialDataProviderInterface:

namespace App\Reports;

use Ezesha\EndYearReports\DataProviders\FinancialDataProviderInterface;

class LedgerDataProvider implements FinancialDataProviderInterface
{
    public function getPackage(int $officeId, string $closureDate): array
    {
        // Query your ledger for this office / period and return:
        return [
            'trial_balance'    => [ /* accounts, totals */ ],
            'income_statement' => [ /* revenues, expenses, ... */ ],
            'balance_sheet'    => [ /* assets, liabilities, equity */ ],
        ];
    }
}

Then point config at it (via your App\Config\EndYearReports):

public string $dataProvider = \App\Reports\LedgerDataProvider::class;

The pipeline services resolve the provider through service('financialDataProvider'), so no other change is needed.

Scheduling (optional, requires codeigniter4/tasks)

The package does not force a scheduler on you. To run the workers automatically, add these to the host app's App\Config\Tasks::init():

$schedule->command('workers:process-reports --max-messages 50')
         ->everyMinute()
         ->named('process-reports')
         ->singleInstance();

$schedule->command('workers:retry-failed --max-age-hours 24')
         ->everyFiveMinutes()
         ->named('retry-failed-reports');

…and wire the CodeIgniter task runner into system cron:

* * * * * cd /path/to/app && php spark tasks:run >> /dev/null 2>&1

Why bounded worker runs? A long‑lived PHP process caches every class in memory, so it keeps running stale code after you edit a service. Running a fresh, bounded process each tick (--max-messages) always loads current code.

Data model

Table end_year_report (see the migration):

  • Unique key unique_office_closure on (fk_office_id, end_year_report_closure_date) blocks duplicate placeholders under concurrency.
  • end_year_report_is_valid: 0 = pending, 1 = valid/ready, 2 = failed/rolled back.
  • The JSON column is physically named trail_balance (historical spelling) while the pipeline/API key is trial_balance; the code reads trail_balance ?? trial_balance and the model allows both.

Package layout

src/
├── Config/
│   ├── EndYearReports.php     # tunable config (data provider, pipeline, SQS)
│   ├── Services.php           # service('financialDataProvider' | 'endYearReportsConfig')
│   └── Routes.php             # auto-discovered module routes
├── Commands/
│   ├── ProcessReportQueue.php # workers:process-reports
│   ├── RetryFailedReports.php # workers:retry-failed
│   └── PublishAssets.php      # endyearreports:publish
├── Controllers/
│   ├── EndYearReport.php      # GET /end_year_report
│   └── Api/FinancialReportController.php
├── Services/FinancialReports/ # pipeline interface + 3 stage services
├── DataProviders/             # FinancialDataProviderInterface + mock default
├── Models/EndYearReportModel.php
├── Database/Migrations/
├── Support/Sqs.php            # shared SQS client / queue-url factory
└── Views/end_year_report.php
assets/                        # frontend JS + CSS (published to public/)

License

MIT — see LICENSE.

统计信息

  • 总下载量: 0
  • 月度下载量: 0
  • 日度下载量: 0
  • 收藏数: 0
  • 点击次数: 2
  • 依赖项目数: 0
  • 推荐数: 0

GitHub 信息

  • Stars: 0
  • Watchers: 0
  • Forks: 0
  • 开发语言: PHP

其他信息

  • 授权协议: MIT
  • 更新时间: 2026-07-07

承接程序开发

PHP开发

VUE

Vue开发

前端开发

小程序开发

公众号开发

系统定制

数据库设计

云部署

网站建设

安全加固