PHPackages                             vs-point/moneys3 - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [API Development](/categories/api)
4. /
5. vs-point/moneys3

ActiveLibrary[API Development](/categories/api)

vs-point/moneys3
================

A strictly typed PHP library for communication with the Money S3 accounting software via its GraphQL API.

v1.0.0(1mo ago)00MITPHPPHP &gt;=8.2

Since Jun 1Pushed 1mo agoCompare

[ Source](https://github.com/vs-point/moneys3)[ Packagist](https://packagist.org/packages/vs-point/moneys3)[ RSS](/packages/vs-point-moneys3/feed)WikiDiscussions main Synced 1w ago

READMEChangelog (1)Dependencies (11)Versions (2)Used By (0)

vs-point/moneys3
================

[](#vs-pointmoneys3)

Striktně typovaná PHP knihovna pro komunikaci s účetním softwarem **Money S3** (Seyfor) přes jeho **GraphQL API**. Poskytuje typovaný PHP interface pro čtení a zápis dokladů, adresáře, skladů, deníků a dalších agend — bez ručního skládání GraphQL řetězců.

- 🔒 **Striktně typované** — vstupy (mutace) i filtry jsou PHP objekty, ne pole/řetězce.
- 🧠 **Inteligentní GraphQL builder** — typované objekty se samy serializují do platné GraphQL syntaxe (literály, enum tokeny, vnořené objekty, seznamy).
- 🔌 **Framework-agnostické jádro** + tenký **Symfony bundle**.
- ☁️ **Cloud i lokál** — `CloudClient` (`{domain}.api.moneys3.eu`) a `Client` (`localhost:85`).

> Money S3 API je GraphQL-based s OAuth2 autentizací. Čtení je synchronní; **zápis je asynchronní** — doklad vstupuje do importní fronty a mutace vrací `guid` + `isSuccess`. Oficiální dokumentace: , interaktivní schéma: .

Požadavky
---------

[](#požadavky)

- PHP &gt;= 8.2
- Money S3 s nainstalovaným a zakoupeným API modulem
- Vygenerovaný API klíč (Client ID + Client Secret) a Application ID (`api@money.cz`)

Instalace
---------

[](#instalace)

```
composer config repositories.moneys3 git git@git.vs-point.cz:vspoint/package/moneys3.git
composer require vs-point/moneys3:^1.0
```

Při použití Dockeru je potřeba GitLab token:

```
composer config --auth gitlab-token.git.vs-point.cz
```

Připojení
---------

[](#připojení)

Knihovna nabízí dvě konkrétní třídy klienta se společným předkem `MoneyS3Api`, takže si explicitně volíte, ke které instanci se připojujete:

TřídaCílová instanceEndpoint`CloudClient`cloud`https://{domain}.api.moneys3.eu/graphql/``Client`lokální`http://localhost:85/graphql/`### Cloud

[](#cloud)

```
use VsPoint\MoneyS3\Auth\Credentials;
use VsPoint\MoneyS3\Client\CloudClient;

$client = new CloudClient(
    domain: 'mojefirma',
    appId: 'APP-ID-Z-MONEY',
    credentials: Credentials::clientCredentials('client-id', 'client-secret'),
);
```

### Lokální Money S3

[](#lokální-money-s3)

```
use VsPoint\MoneyS3\Auth\Credentials;
use VsPoint\MoneyS3\Client\Client;

$client = new Client(
    appId: 'APP-ID-Z-MONEY',
    credentials: Credentials::clientCredentials('client-id', 'client-secret'),
    // host: 'localhost', port: 85, secure: false  // výchozí
);
```

### Autentizace

[](#autentizace)

```
// Client Credentials (z nastavení API klíče)
Credentials::clientCredentials('client-id', 'client-secret');

// Resource Owner Password Credentials
Credentials::password('client-id', 'client-secret', 'uzivatel', 'heslo');
```

Token se získá přes `connect/token`, drží se v paměti a automaticky obnovuje před expirací.

Použití
-------

[](#použití)

Klient přímo vystavuje jednu službu na agendu:

```
$client->issuedInvoices       // faktury vystavené   — R / C / U / D
$client->receivedInvoices     // faktury přijaté      — R / C / U / D
$client->bankStatements       // bankovní doklady     — R / C / U / D
$client->cashVouchers         // pokladní doklady     — R / C / U / D
$client->receivedOrders       // objednávky přijaté   — R / C / U / D
$client->issuedOrders         // objednávky vystavené — R / C / U / D
$client->receivedSlips        // skladové příjemky    — R / C / U / D
$client->issuedSlips          // skladové výdejky     — R / C / U / D
$client->stockTakingDocuments // inventurní doklady   — R / C / U / D
$client->wages                // mzdy                 — C / U / D
$client->cashJournal          // peněžní deník        — R
$client->accountingJournal    // účetní deník         — R
$client->warehouseStocks      // skladové zásoby      — R
$client->agendas              // agendy / firmy       — R
```

### Čtení (query) — typované DTO

[](#čtení-query--typované-dto)

```
use VsPoint\MoneyS3\DTO\Journal\CashJournalAttribute;
use VsPoint\MoneyS3\Filter\FilterOperator;
use VsPoint\MoneyS3\Filter\Order;
use VsPoint\MoneyS3\Filter\OrderDirection;
use VsPoint\MoneyS3\Filter\Where;

// Peněžní deník za rok 2026, řazený podle data sestupně, prvních 20
$result = $client->cashJournal->query(
    where: Where::field(CashJournalAttribute::year, FilterOperator::eq, 2026),
    order: Order::by(CashJournalAttribute::date, OrderDirection::desc),
    take: 20,
);

foreach ($result as $transaction) {
    echo $transaction->id . ' ' . $transaction->amountHc . ' ' . $transaction->companyName . PHP_EOL;
}
```

`$result` je `Collection` — typovaná, iterovatelná, s `first()`, `count()`, `isEmpty()`.

### Filtrování (`where`) — typované atributy

[](#filtrování-where--typované-atributy)

Pole se **nikdy nezadávají stringem** — odkazují se přes per-agenda atributový enum implementující `FieldName` (např. `CashJournalAttribute`, `IssuedInvoiceAttribute`, `WarehouseStockAttribute`). Díky tomu nelze odkázat na pole, které neexistuje:

```
Where::field(CashJournalAttribute::year, FilterOperator::eq, 2026);
Where::field(CashJournalAttribute::companyIdentificationNumber, FilterOperator::eq, '01572377'); // vnořené přes tečku
Where::and(
    Where::field(CashJournalAttribute::year, FilterOperator::eq, 2026),
    Where::field(CashJournalAttribute::amount, FilterOperator::gt, 0),
);
Where::or(/* ... */);
Where::allOf([[CashJournalAttribute::year, 2026], [CashJournalAttribute::amount, 100]]); // konjunkce přes `eq`
```

Stejně tak řazení: `Order::by(CashJournalAttribute::date, OrderDirection::desc)`.

> IDE i PHPStan tak hlídají správnost: `CashJournalAttribute::yaer` se nezkompiluje. Názvy polí v enumech jsou navíc **ověřené proti živému schématu** (filter input typy) — viz [Validace proti schématu](#validace-proti-sch%C3%A9matu).
>
> Pro pole, které zatím nemá atributový enum, existuje únikový poklop `Where::path('nejake.pole', …)` / `Order::path('nejake.pole', …)`.

Operátory (`FilterOperator`): `eq`, `neq`, `gt`, `gte`, `lt`, `lte`, `in`, `nin`, `contains`, `ncontains`, `startsWith`, `nstartsWith`, `endsWith`, `nendsWith`.

### Vlastní výběr polí

[](#vlastní-výběr-polí)

Read-only agendy mají výchozí selekci pokrývající celé DTO, ale můžete si zvolit vlastní:

```
use VsPoint\MoneyS3\GraphQL\Field;

$result = $client->warehouseStocks->query(
    fields: [
        Field::leaf('description'),
        Field::leaf('stockQuantity'),
        Field::nested('warehouse', ['code', 'name']),
    ],
    take: 100,
);
```

U dokladových agend (faktury, banka, …) je `query()` typově bezpečný „raw" čteč — zvolíte selekci a hodnoty čtete přes `Data`:

```
$invoices = $client->issuedInvoices->query(
    fields: [Field::leaf('documentNumber'), Field::leaf('dateOfIssue')],
    where: Where::field('variableSymbol', FilterOperator::eq, '202603'),
    take: 5,
);

foreach ($invoices as $row) {           // $row je VsPoint\MoneyS3\Hydration\Data
    echo $row->string('documentNumber') . PHP_EOL;
}
```

### Vytvoření dokladu (mutace)

[](#vytvoření-dokladu-mutace)

```
use VsPoint\MoneyS3\DTO\Common\Address;
use VsPoint\MoneyS3\DTO\Common\CodeRef;
use VsPoint\MoneyS3\DTO\Common\DefinitionXMLTransfer;
use VsPoint\MoneyS3\DTO\Common\PartnerAddress;
use VsPoint\MoneyS3\DTO\Common\PostalCode;
use VsPoint\MoneyS3\DTO\Common\ShortCutRef;
use VsPoint\MoneyS3\DTO\Common\VatRateSummary;
use VsPoint\MoneyS3\DTO\Invoice\InvoiceItem;
use VsPoint\MoneyS3\DTO\Invoice\IssuedInvoiceInput;
use VsPoint\MoneyS3\Enum\PriceType;

$result = $client->issuedInvoices->create(
    new IssuedInvoiceInput(
        dateOfIssue: '2026-03-02',
        dateOfTaxing: '2026-03-02',
        dateOfMaturity: '2026-03-12',
        documentNumber: '20260203',
        variableSymbol: '202603',
        description: 'Popis faktury',
        accountAssignment: new ShortCutRef('FV001'),
        vatClassification: new ShortCutRef('19Ř01,02'),
        payOn: new ShortCutRef('BAN'),
        vatRateSummaryHc: new VatRateSummary(vatRate: 21, totalWithoutVat: 100, totalVat: 50),
        partnerAddress: new PartnerAddress(
            businessAddress: new Address(
                name: 'Seyfor, a. s.',
                country: new CodeRef('CZ'),
                municipality: 'Brno',
                municipalityPostalCode: new PostalCode('60200'),
                street: 'Drobného 555/49',
            ),
            identificationNumber: '01572377',
            vatIdentificationNumber: 'CZ01572377',
        ),
        paymentMethod: 'převodem',
        items: [
            new InvoiceItem(
                description: 'Vývoj software',
                amount: 1,
                unitPriceHc: 100,
                vatRate: 21,
                priceType: PriceType::withoutVat,
            ),
        ],
    ),
    new DefinitionXMLTransfer('_FP+FV'), // definice importu
);

if ($result->isSuccess) {
    echo 'GUID v importní frontě: ' . $result->guid;
}

// nebo vyhoďte výjimku, pokud Money S3 doklad nepřijalo:
$result->assertSuccess();
```

Datová pole přijímají `string` (`"2026-03-02"`), `DateTimeInterface` i `Brick\DateTime\LocalDate`. Peněžní/číselné hodnoty přijímají `int|float|string` i `Brick\Math\BigNumber`.

### Skladová položka faktury

[](#skladová-položka-faktury)

```
use VsPoint\MoneyS3\DTO\Common\ArticleRef;
use VsPoint\MoneyS3\DTO\Common\StockItem;
use VsPoint\MoneyS3\DTO\Common\WarehouseRef;
use VsPoint\MoneyS3\DTO\Invoice\InvoiceItem;

new InvoiceItem(
    description: 'Bota goretex',
    amount: 1,
    stockItem: new StockItem(
        warehouse: new WarehouseRef(code: 'PRODEJ'),
        article: new ArticleRef(catalogue: 'K50'),
    ),
);
```

### Úprava dokladu

[](#úprava-dokladu)

Update používá stejné vstupní DTO jako `create`; doklad se identifikuje přes `guid`(případně `documentNumber`/symboly podle nastavení importu):

```
$client->issuedInvoices->update(
    new IssuedInvoiceInput(
        guid: 'FFBD0FF4-31D0-41C2-9210-823A6DA92A47',
        description: 'Opravený popis',
    ),
);
```

### Smazání dokladu

[](#smazání-dokladu)

```
$client->issuedInvoices->delete(id: 52, year: 2025);
$client->receivedInvoices->delete(id: 10, year: 2025);
$client->wages->delete(id: 7); // mzda se maže jen podle id
```

Přehled agend a CRUD
--------------------

[](#přehled-agend-a-crud)

Stav byl **ověřen proti živému schématu** (`s3api.api.moneys3.eu/graphql/`) — viz [Validace proti schématu](#validace-proti-sch%C3%A9matu). Zápis je vždy asynchronní (importní fronta), mutace vrací `{ guid, isSuccess }`.

AgendaSlužbaCRUDFaktura vystavená`issuedInvoices`✓✓✓✓Faktura přijatá`receivedInvoices`✓✓✓✓Bankovní doklad`bankStatements`✓✓✓✓Pokladní doklad`cashVouchers`✓✓✓✓Objednávka přijatá`receivedOrders`✓✓✓✓Objednávka vystavená`issuedOrders`✓✓✓✓Skladová příjemka`receivedSlips`✓✓✓✓Skladová výdejka`issuedSlips`✓✓✓✓Inventurní doklad`stockTakingDocuments`✓✓✓✓Mzda`wages`✓—✓✓Peněžní deník`cashJournal`—✓——Účetní deník`accountingJournal`—✓——Skladová zásoba`warehouseStocks`—✓——Agendy / firmy`agendas`—✓——> Money S3 GraphQL API vystavuje **`create` / `update` / `delete` + query pro desítky dalších agend** (adresář `companies`, kmenové karty `articles`, dodací listy, nabídky, poptávky, interní doklady, závazky/pohledávky, číselníky…). Ty zatím nemají vlastní typované DTO, ale jdou číst generickým `query(fields: […])` patternem a snadno doplnit — viz [Rozšíření o další agendu](#roz%C5%A1%C3%AD%C5%99en%C3%AD-o-dal%C5%A1%C3%AD-agendu).

Validace proti schématu
-----------------------

[](#validace-proti-schématu)

Knihovna je ověřena proti **živému GraphQL schématu** Money S3 pomocí introspekce (`__schema` / `__type` nevyžadují OAuth token). Testovací sada `Schema`(`tests/Schema/LiveSchemaContractTest.php`) kontroluje, že:

- všechny query root fieldy (`issuedInvoices`, `journalTrs`, …) ve schématu existují,
- všechny `create*` / `update*` / `delete*` mutace agend existují,
- enum tokeny, které knihovna posílá (`PriceType`, `AbsenceType`, řazení `SortEnumType`), jsou platné hodnoty schématu,
- pole vstupu `IssuedInvoiceInput` odpovídají schématu,
- názvy polí v atributových enumech (`CashJournalAttribute`, `IssuedInvoiceAttribute`, …) jsou reálná filtrovatelná pole (`I…FilterInput`).

Pokud je endpoint nedostupný (offline CI), se test sám přeskočí (`markTestSkipped`), takže nikdy nerozbije pipeline. Spuštění jen této sady:

```
docker run --rm -v "$(pwd):/app" -w /app vspoint/php:8.5-fpm-alpine ./vendor/bin/phpunit --testsuite Schema
```

Jak funguje typovaný GraphQL builder
------------------------------------

[](#jak-funguje-typovaný-graphql-builder)

Jádro je v `src/GraphQL`:

- **`InputObject`** — kontrakt: `toGraphQL(): array` vrací mapu `pole => hodnota`. Implementují ho všechna vstupní DTO (`IssuedInvoiceInput`, `Address`, `ShortCutRef`, …).
- **`ValueEncoder`** — serializuje PHP hodnoty do **GraphQL literálů** (ne JSON): řetězce v uvozovkách s escapováním, čísla/bool/null bez uvozovek, **enumy jako holé tokeny** (`WITHOUT_VAT`), `InputObject`/vnořená pole jako `{ key: value }`, seznamy jako `[ … ]`. `null` pole se vynechávají.
- **`Field`** — uzel selekce (`documentNumber` nebo `company { identificationNumber }`).
- **`QueryBuilder` / `MutationBuilder`** — složí celý dokument: `query { root(where: …, order: …, skip: …, take: …) { items { …fields } } }`, resp. `mutation { createX(x: { … }, definitionXMLTransfer: { … }) { guid isSuccess } }`.
- **`Where` / `Order`** (`src/Filter`) — kompozičně skládané, typované argumenty.

Enumy, které vyžadují jiný token než název case, implementují `GraphQLEnumValue`. Pro ojedinělý surový fragment existuje `RawGraphQL` (používat střídmě).

Symfony bundle
--------------

[](#symfony-bundle)

Jádro je framework-agnostické; bundle jen registruje a autowiruje připojení.

```
// config/bundles.php
return [
    // ...
    VsPoint\MoneyS3\Bridge\Symfony\MoneyS3Bundle::class => ['all' => true],
];
```

```
# config/packages/money_s3.yaml
money_s3:
    connection: cloud            # cloud | local
    app_id: '%env(MONEYS3_APP_ID)%'
    cloud:
        domain: '%env(MONEYS3_DOMAIN)%'
    # local:
    #     host: localhost
    #     port: 85
    #     secure: false
    auth:
        grant_type: client_credentials   # client_credentials | password
        client_id: '%env(MONEYS3_CLIENT_ID)%'
        client_secret: '%env(MONEYS3_CLIENT_SECRET)%'
        # username: '%env(MONEYS3_USERNAME)%'
        # password: '%env(MONEYS3_PASSWORD)%'
```

```
use VsPoint\MoneyS3\Client\MoneyS3Api;

final class InvoiceImporter
{
    public function __construct(private readonly MoneyS3Api $money) {}

    public function run(): void
    {
        $this->money->issuedInvoices->create(/* ... */);
    }
}
```

Autowiruje se `MoneyS3Api` i konkrétní třída (`CloudClient` / `Client`) podle `connection`.

Rozšíření o další agendu
------------------------

[](#rozšíření-o-další-agendu)

1. **Atributový enum** v `src/DTO/{Agenda}/{Agenda}Attribute.php` implementující `FieldName`(mapuje PHP název → reálné GraphQL filtrovatelné pole, vnořené přes tečku) — pro typované `Where` / `Order`.
2. **Vstupní DTO** v `src/DTO/{Agenda}/` implementující `InputObject` (jen `toGraphQL()`s `pole => hodnota`; `null` pole se automaticky vynechají).
3. **Response DTO** (u read agend) s `public static fromData(Data $d): self` a `public static fields(): array` (selekce `Field[]`).
4. **Služba** v `src/Agenda/` rozšiřující `AbstractAgendaService` — `query()` přes `queryCollection()` / `queryRaw()`, `create()` / `update()` / `delete()` přes `mutate()`.
5. Přidat `public readonly` property + inicializaci do `src/Client/MoneyS3Api.php`.

Přesné názvy root fieldů, mutací, vstupních polí a enum tokenů ověřte v interaktivním schématu:  („Browse Schema").

Vývoj
-----

[](#vývoj)

Vše běží přes Docker image z CI (`vspoint/php:8.5-fpm-alpine`):

```
# Instalace závislostí
docker run --rm -v "$(pwd):/app" -w /app vspoint/php:8.5-fpm-alpine composer install

# Testy
docker run --rm -v "$(pwd):/app" -w /app vspoint/php:8.5-fpm-alpine ./vendor/bin/phpunit --testdox

# Statická analýza (PHPStan level 6)
docker run --rm -v "$(pwd):/app" -w /app vspoint/php:8.5-fpm-alpine ./vendor/bin/phpstan analyse

# Code style (ECS) — kontrola / oprava
docker run --rm -v "$(pwd):/app" -w /app vspoint/php:8.5-fpm-alpine ./vendor/bin/ecs check
docker run --rm -v "$(pwd):/app" -w /app vspoint/php:8.5-fpm-alpine ./vendor/bin/ecs check --fix
```

Testy jsou **unit** — neprovádějí žádné síťové volání (HTTP je mockované přes Guzzle `MockHandler`, transport přes `RecordingTransport`). Ověřují sestavování GraphQL dokumentů, serializaci typovaných vstupů, parsování odpovědí, OAuth2 a resolving endpointů.

CI (`.gitlab-ci.yml`) má fáze `analyse` (validate + phpstan + ecs) a `test` (phpunit).

Licence
-------

[](#licence)

MIT

###  Health Score

37

—

LowBetter than 81% of packages

Maintenance89

Actively maintained with recent releases

Popularity0

Limited adoption so far

Community6

Small or concentrated contributor base

Maturity46

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Unknown

Total

1

Last Release

53d ago

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/1543645?v=4)[Vít Steklý](/maintainers/vitek499)[@vitek499](https://github.com/vitek499)

---

Top Contributors

[![vitek499](https://avatars.githubusercontent.com/u/1543645?v=4)](https://github.com/vitek499 "vitek499 (4 commits)")

---

Tags

apimoneygraphqlAccountingmoneys3seyforucetnictvi

###  Code Quality

TestsPHPUnit

Static AnalysisPHPStan

Code StyleECS

Type Coverage Yes

### Embed Badge

![Health badge](/badges/vs-point-moneys3/health.svg)

```
[![Health](https://phpackages.com/badges/vs-point-moneys3/health.svg)](https://phpackages.com/packages/vs-point-moneys3)
```

###  Alternatives

[craftcms/cms

Craft CMS

3.6k3.6M3.2k](/packages/craftcms-cms)[api-platform/core

Build a fully-featured hypermedia or GraphQL API in minutes!

2.6k51.2M353](/packages/api-platform-core)[sylius/sylius

E-Commerce platform for PHP, based on Symfony framework.

8.5k5.9M754](/packages/sylius-sylius)[api-platform/symfony

Symfony API Platform integration

404.5M135](/packages/api-platform-symfony)[api-platform/serializer

API Platform core Serializer

274.8M88](/packages/api-platform-serializer)[oro/platform

Business Application Platform (BAP)

645143.5k116](/packages/oro-platform)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
