Перейти к содержанию

Modules (Модули)

NPDTools

Bases: NPDToolsInvoice, NPDToolsIncome, NPDToolsBase

Объединяет методы всех модулей, чтобы не грузить всё в один большой и страшный файл.

Source code in npdtools/modules/__init__.py
 6
 7
 8
 9
10
11
class NPDTools(NPDToolsInvoice, NPDToolsIncome, NPDToolsBase):
    """
    Объединяет методы всех модулей, чтобы не грузить всё в один большой и страшный файл.
    """

    ...

NPDToolsIncome

Bases: NPDToolsBase

Source code in npdtools/modules/income.py
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
class NPDToolsIncome(NPDToolsBase):
    async def declare_income(
        self,
        *services: Service,
        client: ClientInfo | None = None,
        operation_time: datetime | str = None,
    ) -> NewIncome:
        """
        Метод для декларирования дохода. Иными словами, выдача чека.

        Notes: Список позиций чека
            Позиции чека передаются неименованными аргументами в количество 1+ штук. Вот пример:

            ```python
            services = [
                Service(name="Написание документации", amount=2500),
                Service(name="Настройка конфигов для документации", amount=1234.45, quantity=2),
                Service(name="Написание пайплайнов Gitlab CI", amount=Decimal("123.1")),
            ]
            service = Service(name="Капли для глаз", amount="12")

            await NPDTools.declare_income(*services)
            # or
            await NPDTools.declare_income(service, client=...)
            # or
            await NPDTools.declare_income(service, *services, client=...)
            ```

        Warning: Объект дохода
            Для получения полного объекта Income, следует обратиться к методу ``NPDTools.get_income(receipt_id=NewIncome.receipt_id)``

        [Примеры использования](https://npd-tools.readthedocs.io/en/dev/guide/example/#_4)

        Args:
            *services: Позиции в чеке: список товаров, услуг или подобного
            client: Объект сведений о клиенте
            operation_time: Дата и время получения дохода.

        Returns:
            NewIncome: Объект нового дохода, **содержащий на данный момент только номер чека**,
        """
        client = client if client is not None else ClientInfo()

        operation_time = (
            operation_time if operation_time is not None else datetime.now()
        )
        data = {
            "paymentType": "CASH",
            "ignoreMaxTotalIncomeRestriction": False,
            "client": client.fns_export(),
            "requestTime": datetime.now()
            .replace(microsecond=0)
            .astimezone()
            .isoformat(),
            "operationTime": operation_time
            if isinstance(operation_time, str)
            else operation_time.now().replace(microsecond=0).astimezone().isoformat(),
            "services": [s.model_dump() for s in services],
            "totalAmount": str(sum(s.service_amount for s in services)),
        }

        response = await self._request(
            "POST",
            url="/income",
            json=data,
        )
        print(response.json())

        return NewIncome(**response.json())

    async def cancel_income(
        self,
        receipt_id: str,
        comment: str = "Чек сформирован ошибочно",
        cancellation_time: datetime | str | None = None,
    ) -> CanceledIncome:
        """
        Метод для аннулирования задекларированного дохода.

        [Примеры использования](https://npd-tools.readthedocs.io/en/dev/guide/example/#_9)

        Args:
            receipt_id: Номер чека. Те самые буквы-цифры.
            comment: Комментарий, по какой причине происходит аннулирование
            cancellation_time: Время отмены. Например, если вы вернули деньги вчера. По умолчанию принимает значение ``datetime.now()``

        Returns:
            CanceledIncome: Сведения об аннулированном доходе
        """
        cancellation_time = (
            cancellation_time if cancellation_time is not None else datetime.now()
        )

        data = {
            "comment": comment,
            "requestTime": datetime.now()
            .replace(microsecond=0)
            .astimezone()
            .isoformat(),
            "operationTime": cancellation_time
            if isinstance(cancellation_time, str)
            else cancellation_time.replace(microsecond=0).astimezone().isoformat(),
            "receiptUuid": receipt_id,
        }

        response = await self._request(
            "POST",
            url="/cancel",
            json=data,
        )

        return CanceledIncome(**response.json()["incomeInfo"])

    async def get_incomes(
        self,
        from_date: datetime | str | int = 7,
        to_date: datetime | str | int | None = None,
        offset: int = 0,
        limit: int = 10,
        sort_type: SortTypes | str = SortTypes.time,
        is_sort_asc: bool = False,
    ) -> IncomesList:
        """
        Метод для получения списка задекларированных доходов с учётом фильтров.

        Args:
            from_date: Время начала поиск. Можно передать ``int``, тогда аргумент примет значение "``int`` дней назад", а время установится на ``0:00:00``
            to_date: Время окончания поиска. По умолчанию принимает значение ``datetime.now()``. Можно передать ``int``, тогда аргумент примет значение "``int`` дней назад", а время установится на ``23:59:59``
            offset: Сдвиг от начала найденных доходов (в т.ч. аннулированных)
            limit: Количество доходов в выдаче
            sort_type: Тип сортировки: по дате или сумме
            is_sort_asc: Сортировка по возрастанию?

        Returns:
            IncomesList: Список доходов и сведения о пагинации
        """
        if from_date is None:
            from_date: datetime = datetime.now()
        if isinstance(from_date, int):
            from_date: datetime = (datetime.now() - timedelta(days=from_date)).replace(
                hour=0,
                minute=0,
                second=0,
                microsecond=0,
            )

        if isinstance(to_date, int):
            to_date: datetime = (datetime.now() - timedelta(days=to_date)).replace(
                hour=23,
                minute=59,
                second=59,
                microsecond=999999,
            )

        params = {
            "from": (
                from_date
                if isinstance(from_date, str)
                else from_date.astimezone().isoformat()
            ),
            "to": (
                to_date
                if isinstance(to_date, str)
                else to_date.astimezone().isoformat()
            ),
            "offset": offset,
            "sortBy": f'{str(sort_type)}:{"asc" if is_sort_asc else "desc"}',
            "limit": limit,
        }
        response = await self._request(
            "GET",
            "/invoices",
            params=params,
        )

        return IncomesList(**response.json())

declare_income(*services, client=None, operation_time=None) async

Метод для декларирования дохода. Иными словами, выдача чека.

Список позиций чека

Позиции чека передаются неименованными аргументами в количество 1+ штук. Вот пример:

services = [
    Service(name="Написание документации", amount=2500),
    Service(name="Настройка конфигов для документации", amount=1234.45, quantity=2),
    Service(name="Написание пайплайнов Gitlab CI", amount=Decimal("123.1")),
]
service = Service(name="Капли для глаз", amount="12")

await NPDTools.declare_income(*services)
# or
await NPDTools.declare_income(service, client=...)
# or
await NPDTools.declare_income(service, *services, client=...)
Объект дохода

Для получения полного объекта Income, следует обратиться к методу NPDTools.get_income(receipt_id=NewIncome.receipt_id)

Примеры использования

Parameters:

Name Type Description Default
*services Service

Позиции в чеке: список товаров, услуг или подобного

()
client ClientInfo | None

Объект сведений о клиенте

None
operation_time datetime | str

Дата и время получения дохода.

None

Returns:

Name Type Description
NewIncome NewIncome

Объект нового дохода, содержащий на данный момент только номер чека,

Source code in npdtools/modules/income.py
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
async def declare_income(
    self,
    *services: Service,
    client: ClientInfo | None = None,
    operation_time: datetime | str = None,
) -> NewIncome:
    """
    Метод для декларирования дохода. Иными словами, выдача чека.

    Notes: Список позиций чека
        Позиции чека передаются неименованными аргументами в количество 1+ штук. Вот пример:

        ```python
        services = [
            Service(name="Написание документации", amount=2500),
            Service(name="Настройка конфигов для документации", amount=1234.45, quantity=2),
            Service(name="Написание пайплайнов Gitlab CI", amount=Decimal("123.1")),
        ]
        service = Service(name="Капли для глаз", amount="12")

        await NPDTools.declare_income(*services)
        # or
        await NPDTools.declare_income(service, client=...)
        # or
        await NPDTools.declare_income(service, *services, client=...)
        ```

    Warning: Объект дохода
        Для получения полного объекта Income, следует обратиться к методу ``NPDTools.get_income(receipt_id=NewIncome.receipt_id)``

    [Примеры использования](https://npd-tools.readthedocs.io/en/dev/guide/example/#_4)

    Args:
        *services: Позиции в чеке: список товаров, услуг или подобного
        client: Объект сведений о клиенте
        operation_time: Дата и время получения дохода.

    Returns:
        NewIncome: Объект нового дохода, **содержащий на данный момент только номер чека**,
    """
    client = client if client is not None else ClientInfo()

    operation_time = (
        operation_time if operation_time is not None else datetime.now()
    )
    data = {
        "paymentType": "CASH",
        "ignoreMaxTotalIncomeRestriction": False,
        "client": client.fns_export(),
        "requestTime": datetime.now()
        .replace(microsecond=0)
        .astimezone()
        .isoformat(),
        "operationTime": operation_time
        if isinstance(operation_time, str)
        else operation_time.now().replace(microsecond=0).astimezone().isoformat(),
        "services": [s.model_dump() for s in services],
        "totalAmount": str(sum(s.service_amount for s in services)),
    }

    response = await self._request(
        "POST",
        url="/income",
        json=data,
    )
    print(response.json())

    return NewIncome(**response.json())

cancel_income(receipt_id, comment='Чек сформирован ошибочно', cancellation_time=None) async

Метод для аннулирования задекларированного дохода.

Примеры использования

Parameters:

Name Type Description Default
receipt_id str

Номер чека. Те самые буквы-цифры.

required
comment str

Комментарий, по какой причине происходит аннулирование

'Чек сформирован ошибочно'
cancellation_time datetime | str | None

Время отмены. Например, если вы вернули деньги вчера. По умолчанию принимает значение datetime.now()

None

Returns:

Name Type Description
CanceledIncome CanceledIncome

Сведения об аннулированном доходе

Source code in npdtools/modules/income.py
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
async def cancel_income(
    self,
    receipt_id: str,
    comment: str = "Чек сформирован ошибочно",
    cancellation_time: datetime | str | None = None,
) -> CanceledIncome:
    """
    Метод для аннулирования задекларированного дохода.

    [Примеры использования](https://npd-tools.readthedocs.io/en/dev/guide/example/#_9)

    Args:
        receipt_id: Номер чека. Те самые буквы-цифры.
        comment: Комментарий, по какой причине происходит аннулирование
        cancellation_time: Время отмены. Например, если вы вернули деньги вчера. По умолчанию принимает значение ``datetime.now()``

    Returns:
        CanceledIncome: Сведения об аннулированном доходе
    """
    cancellation_time = (
        cancellation_time if cancellation_time is not None else datetime.now()
    )

    data = {
        "comment": comment,
        "requestTime": datetime.now()
        .replace(microsecond=0)
        .astimezone()
        .isoformat(),
        "operationTime": cancellation_time
        if isinstance(cancellation_time, str)
        else cancellation_time.replace(microsecond=0).astimezone().isoformat(),
        "receiptUuid": receipt_id,
    }

    response = await self._request(
        "POST",
        url="/cancel",
        json=data,
    )

    return CanceledIncome(**response.json()["incomeInfo"])

get_incomes(from_date=7, to_date=None, offset=0, limit=10, sort_type=SortTypes.time, is_sort_asc=False) async

Метод для получения списка задекларированных доходов с учётом фильтров.

Parameters:

Name Type Description Default
from_date datetime | str | int

Время начала поиск. Можно передать int, тогда аргумент примет значение "int дней назад", а время установится на 0:00:00

7
to_date datetime | str | int | None

Время окончания поиска. По умолчанию принимает значение datetime.now(). Можно передать int, тогда аргумент примет значение "int дней назад", а время установится на 23:59:59

None
offset int

Сдвиг от начала найденных доходов (в т.ч. аннулированных)

0
limit int

Количество доходов в выдаче

10
sort_type SortTypes | str

Тип сортировки: по дате или сумме

SortTypes.time
is_sort_asc bool

Сортировка по возрастанию?

False

Returns:

Name Type Description
IncomesList IncomesList

Список доходов и сведения о пагинации

Source code in npdtools/modules/income.py
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
async def get_incomes(
    self,
    from_date: datetime | str | int = 7,
    to_date: datetime | str | int | None = None,
    offset: int = 0,
    limit: int = 10,
    sort_type: SortTypes | str = SortTypes.time,
    is_sort_asc: bool = False,
) -> IncomesList:
    """
    Метод для получения списка задекларированных доходов с учётом фильтров.

    Args:
        from_date: Время начала поиск. Можно передать ``int``, тогда аргумент примет значение "``int`` дней назад", а время установится на ``0:00:00``
        to_date: Время окончания поиска. По умолчанию принимает значение ``datetime.now()``. Можно передать ``int``, тогда аргумент примет значение "``int`` дней назад", а время установится на ``23:59:59``
        offset: Сдвиг от начала найденных доходов (в т.ч. аннулированных)
        limit: Количество доходов в выдаче
        sort_type: Тип сортировки: по дате или сумме
        is_sort_asc: Сортировка по возрастанию?

    Returns:
        IncomesList: Список доходов и сведения о пагинации
    """
    if from_date is None:
        from_date: datetime = datetime.now()
    if isinstance(from_date, int):
        from_date: datetime = (datetime.now() - timedelta(days=from_date)).replace(
            hour=0,
            minute=0,
            second=0,
            microsecond=0,
        )

    if isinstance(to_date, int):
        to_date: datetime = (datetime.now() - timedelta(days=to_date)).replace(
            hour=23,
            minute=59,
            second=59,
            microsecond=999999,
        )

    params = {
        "from": (
            from_date
            if isinstance(from_date, str)
            else from_date.astimezone().isoformat()
        ),
        "to": (
            to_date
            if isinstance(to_date, str)
            else to_date.astimezone().isoformat()
        ),
        "offset": offset,
        "sortBy": f'{str(sort_type)}:{"asc" if is_sort_asc else "desc"}',
        "limit": limit,
    }
    response = await self._request(
        "GET",
        "/invoices",
        params=params,
    )

    return IncomesList(**response.json())

NPDToolsInvoice

Bases: NPDToolsBase

Source code in npdtools/modules/invoice.py
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
class NPDToolsInvoice(NPDToolsBase):
    async def get_invoices(
        self,
        from_date: datetime | str | int = 7,
        to_date: datetime | str | None = None,
        offset: int = 0,
        limit: int = 10,
        sort_type: Literal["createdAt"] = "createdAt",
        is_sort_asc: bool = False,
    ) -> InvoicesList:
        """
        Метод для получения списка счетов с учётом фильтров.

        [Примеры использования](https://npd-tools.readthedocs.io/en/dev/guide/example/#_12)

        Args:
            from_date: Время начала поиск. Можно передать ``int``, тогда аргумент примет значение "``int`` дней назад", а время установится на ``0:00:00``
            to_date: Время окончания поиска. По умолчанию принимает значение ``datetime.now()``. Можно передать ``int``, тогда аргумент примет значение "``int`` дней назад", а время установится на ``23:59:59``
            offset: Сдвиг от начала найденных счетов (в т.ч. аннулированных)
            limit: Количество счетов в выдаче
            sort_type: Тип сортировки: только по дате, другие пока что не реализованы
            is_sort_asc: Сортировка по возрастанию?

        Returns:
            InvoicesList: Список счетов и сведения о пагинации
        """
        if from_date is None:
            from_date: datetime = datetime.now()
        if isinstance(from_date, int):
            from_date: datetime = (datetime.now() - timedelta(days=from_date)).replace(
                hour=0,
                minute=0,
                second=0,
                microsecond=0,
            )

        if isinstance(to_date, int):
            to_date: datetime = (datetime.now() - timedelta(days=to_date)).replace(
                hour=23,
                minute=59,
                second=59,
                microsecond=999999,
            )

        data = {
            "limit": limit,
            "offset": offset,
            "sorted": [{"id": sort_type, "desc": not is_sort_asc}],
            "filtered": [
                {
                    "id": "status",
                    "value": "ALL",
                },
                {
                    "id": "from",
                    "value": (
                        from_date
                        if isinstance(from_date, str)
                        else from_date.astimezone().isoformat()
                    ),
                },
                {
                    "id": "to",
                    "value": (
                        to_date
                        if isinstance(to_date, str)
                        else to_date.astimezone().isoformat()
                    ),
                },
            ],
        }
        response = await self._request(
            "POST",
            url="/invoice/table",
            json=data,
        )

        return InvoicesList(**response.json())

    async def create_invoice(
        self,
        *services: Service,
        bank: BankPhone | BankAccount,
        client: ClientInfo,
    ) -> Invoice:
        """
        Метод выставления счёта.

        На указанный ClientInfo.email должен отправиться чек после его формирования,
        но вообще не факт, что это произойдет.

        [Примеры использования](https://npd-tools.readthedocs.io/en/dev/guide/example/#_11)

        Warning: Сведения о клиенте
            Для выставления счёта обязательно указать хоть какие-то сведения о контрагенте.

            Для физлиц обязательно указать ФИО. Инн, номер телефона и email по желанию

            Для юрлиц и ИП указать ИНН обязательно, остальное по желанию.

            Для иностранных компаний указать название обязательно.

        Примеры использования здесь: <<link>>

        Args:
            *services: Позиции в счёте: список товаров, услуг или подобного
            bank: Объект варианта приёма платежа: по номеру телефона или по реквизитам
            client: Объект сведений о клиенте

        Returns:
            Invoice: Полные сведения о счёте
        """
        if client.name is None:
            raise ValueError(
                "Невозможно создать счёт, если не указано имя клиента (или название"
                " компании)"
            )

        data = {
            "clientType": str(client.type),
            "clientName": client.name,
            "type": "MANUAL",
            "services": [s.model_dump() for s in services],
            "totalAmount": str(sum(s.service_amount for s in services)),
        }

        if isinstance(bank, BankPhone):
            data["paymentType"] = "PHONE"
            data["bankName"] = bank.name
            data["phone"] = bank.phone
        elif isinstance(bank, BankAccount):
            data["paymentType"] = "ACCOUNT"
            data["bankName"] = bank.name
            data["bankBik"] = bank.bik
            data["corrAccount"] = bank.corr
            data["currentAccount"] = bank.account

        if client.inn is not None:
            data["clientInn"] = client.inn

        if client.phone is not None:
            data["clientPhone"] = client.phone

        if client.email is not None:
            data["clientEmail"] = client.email

        response = await self._request(
            "POST",
            url="/invoice",
            json=data,
        )

        return Invoice(**response.json())

    async def cancel_invoice(self, invoice_id: int) -> Invoice:
        """
        Метод для отмены счёта. Выданный к счёту чек не отменяется, вроде, его надо руками отменять.

        [Примеры использования](https://npd-tools.readthedocs.io/en/dev/guide/example/#_11)

        Args:
            invoice_id: Номер счёта ``Invoice.invoice_id``

        Returns:
            Invoice: Актуальный полный объект счёта
        """
        response = await self._request(
            "POST",
            url=f"/invoice/{invoice_id}/cancel",
        )

        return Invoice(**response.json())

    async def invoice_paid(self, invoice_id: int) -> Invoice:
        """
        Метод, чтобы отметить счёт оплаченным. Чек можно выдать позже.

        [Примеры использования](https://npd-tools.readthedocs.io/en/dev/guide/example/#_11)

        Args:
            invoice_id: Номер счёта ``Invoice.invoice_id``

        Returns:
            Invoice: Актуальный полный объект счёта
        """
        response = await self._request(
            "POST",
            url=f"/invoice/{invoice_id}/approve",
        )

        return Invoice(**response.json())

    async def invoice_complete(
        self, invoice_id: int, operation_time: datetime | str = None
    ) -> Invoice:
        """
        Метод для выдачи чека к счёту. Счёт автоматически становится оплаченным.

        [Примеры использования](https://npd-tools.readthedocs.io/en/dev/guide/example/#_11)

        Args:
            invoice_id: Номер счёта ``Invoice.invoice_id``
            operation_time: Дата и время получения денег по счёту.

        Returns:
            Invoice: Актуальный полный объект счёта
        """
        operation_time = (
            operation_time if operation_time is not None else datetime.now()
        )
        data = {
            "invoiceId": invoice_id,
            "requestTime": datetime.now()
            .replace(microsecond=0)
            .astimezone()
            .isoformat(),
            "operationTime": operation_time
            if isinstance(operation_time, str)
            else operation_time.now().replace(microsecond=0).astimezone().isoformat(),
        }
        response = await self._request(
            "POST",
            url=f"/invoice/{invoice_id}/receipt",
            json=data,
        )

        return Invoice(**response.json())

    async def update_invoice_payment_type(
        self, invoice_id: int, bank: BankPhone | BankAccount
    ) -> Invoice:
        """
        Метод для смены способа получения денег по счёту

        [Примеры использования](https://npd-tools.readthedocs.io/en/dev/guide/example/#_11)

        Args:
            invoice_id: Номер счёта ``Invoice.invoice_id``
            bank: Сведения о способе получения денег. Можно создать руками или получить из ``NPDTools.get_payment_options()``

        Returns:
            Invoice: Актуальный полный объект счёта
        """
        data = {"invoiceId": invoice_id}

        if isinstance(bank, BankPhone):
            data["paymentType"] = "PHONE"
            data["bankName"] = bank.name
            data["phone"] = bank.phone
        elif isinstance(bank, BankAccount):
            data["paymentType"] = "ACCOUNT"
            data["bankName"] = bank.name
            data["bankBik"] = bank.bik
            data["corrAccount"] = bank.corr
            data["currentAccount"] = bank.account

        response = await self._request(
            "POST",
            url="/invoice/update-payment-info",
            json=data,
        )

        return Invoice(**response.json())

    async def get_payment_options(
        self, by_type: Literal["PHONE", "ACCOUNT"] | None = None
    ) -> PaymentOptions:
        """
        Метод для получения списка сохранённых способов получения денег по счёту

        [Примеры использования](https://npd-tools.readthedocs.io/en/dev/guide/example/#_11)

        Args:
            by_type: Отфильтровать по типу способа получения

        Returns:
            PaymentOptions: Итерируемый объект со списком способов
        """
        response = await self._request(
            "GET",
            url="/payment-type/table",
            params={"type": by_type} if by_type else None,
        )

        return PaymentOptions(**response.json())

get_invoices(from_date=7, to_date=None, offset=0, limit=10, sort_type='createdAt', is_sort_asc=False) async

Метод для получения списка счетов с учётом фильтров.

Примеры использования

Parameters:

Name Type Description Default
from_date datetime | str | int

Время начала поиск. Можно передать int, тогда аргумент примет значение "int дней назад", а время установится на 0:00:00

7
to_date datetime | str | None

Время окончания поиска. По умолчанию принимает значение datetime.now(). Можно передать int, тогда аргумент примет значение "int дней назад", а время установится на 23:59:59

None
offset int

Сдвиг от начала найденных счетов (в т.ч. аннулированных)

0
limit int

Количество счетов в выдаче

10
sort_type Literal['createdAt']

Тип сортировки: только по дате, другие пока что не реализованы

'createdAt'
is_sort_asc bool

Сортировка по возрастанию?

False

Returns:

Name Type Description
InvoicesList InvoicesList

Список счетов и сведения о пагинации

Source code in npdtools/modules/invoice.py
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
async def get_invoices(
    self,
    from_date: datetime | str | int = 7,
    to_date: datetime | str | None = None,
    offset: int = 0,
    limit: int = 10,
    sort_type: Literal["createdAt"] = "createdAt",
    is_sort_asc: bool = False,
) -> InvoicesList:
    """
    Метод для получения списка счетов с учётом фильтров.

    [Примеры использования](https://npd-tools.readthedocs.io/en/dev/guide/example/#_12)

    Args:
        from_date: Время начала поиск. Можно передать ``int``, тогда аргумент примет значение "``int`` дней назад", а время установится на ``0:00:00``
        to_date: Время окончания поиска. По умолчанию принимает значение ``datetime.now()``. Можно передать ``int``, тогда аргумент примет значение "``int`` дней назад", а время установится на ``23:59:59``
        offset: Сдвиг от начала найденных счетов (в т.ч. аннулированных)
        limit: Количество счетов в выдаче
        sort_type: Тип сортировки: только по дате, другие пока что не реализованы
        is_sort_asc: Сортировка по возрастанию?

    Returns:
        InvoicesList: Список счетов и сведения о пагинации
    """
    if from_date is None:
        from_date: datetime = datetime.now()
    if isinstance(from_date, int):
        from_date: datetime = (datetime.now() - timedelta(days=from_date)).replace(
            hour=0,
            minute=0,
            second=0,
            microsecond=0,
        )

    if isinstance(to_date, int):
        to_date: datetime = (datetime.now() - timedelta(days=to_date)).replace(
            hour=23,
            minute=59,
            second=59,
            microsecond=999999,
        )

    data = {
        "limit": limit,
        "offset": offset,
        "sorted": [{"id": sort_type, "desc": not is_sort_asc}],
        "filtered": [
            {
                "id": "status",
                "value": "ALL",
            },
            {
                "id": "from",
                "value": (
                    from_date
                    if isinstance(from_date, str)
                    else from_date.astimezone().isoformat()
                ),
            },
            {
                "id": "to",
                "value": (
                    to_date
                    if isinstance(to_date, str)
                    else to_date.astimezone().isoformat()
                ),
            },
        ],
    }
    response = await self._request(
        "POST",
        url="/invoice/table",
        json=data,
    )

    return InvoicesList(**response.json())

create_invoice(*services, bank, client) async

Метод выставления счёта.

На указанный ClientInfo.email должен отправиться чек после его формирования, но вообще не факт, что это произойдет.

Примеры использования

Сведения о клиенте

Для выставления счёта обязательно указать хоть какие-то сведения о контрагенте.

Для физлиц обязательно указать ФИО. Инн, номер телефона и email по желанию

Для юрлиц и ИП указать ИНН обязательно, остальное по желанию.

Для иностранных компаний указать название обязательно.

Примеры использования здесь: <>

Parameters:

Name Type Description Default
*services Service

Позиции в счёте: список товаров, услуг или подобного

()
bank BankPhone | BankAccount

Объект варианта приёма платежа: по номеру телефона или по реквизитам

required
client ClientInfo

Объект сведений о клиенте

required

Returns:

Name Type Description
Invoice Invoice

Полные сведения о счёте

Source code in npdtools/modules/invoice.py
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
async def create_invoice(
    self,
    *services: Service,
    bank: BankPhone | BankAccount,
    client: ClientInfo,
) -> Invoice:
    """
    Метод выставления счёта.

    На указанный ClientInfo.email должен отправиться чек после его формирования,
    но вообще не факт, что это произойдет.

    [Примеры использования](https://npd-tools.readthedocs.io/en/dev/guide/example/#_11)

    Warning: Сведения о клиенте
        Для выставления счёта обязательно указать хоть какие-то сведения о контрагенте.

        Для физлиц обязательно указать ФИО. Инн, номер телефона и email по желанию

        Для юрлиц и ИП указать ИНН обязательно, остальное по желанию.

        Для иностранных компаний указать название обязательно.

    Примеры использования здесь: <<link>>

    Args:
        *services: Позиции в счёте: список товаров, услуг или подобного
        bank: Объект варианта приёма платежа: по номеру телефона или по реквизитам
        client: Объект сведений о клиенте

    Returns:
        Invoice: Полные сведения о счёте
    """
    if client.name is None:
        raise ValueError(
            "Невозможно создать счёт, если не указано имя клиента (или название"
            " компании)"
        )

    data = {
        "clientType": str(client.type),
        "clientName": client.name,
        "type": "MANUAL",
        "services": [s.model_dump() for s in services],
        "totalAmount": str(sum(s.service_amount for s in services)),
    }

    if isinstance(bank, BankPhone):
        data["paymentType"] = "PHONE"
        data["bankName"] = bank.name
        data["phone"] = bank.phone
    elif isinstance(bank, BankAccount):
        data["paymentType"] = "ACCOUNT"
        data["bankName"] = bank.name
        data["bankBik"] = bank.bik
        data["corrAccount"] = bank.corr
        data["currentAccount"] = bank.account

    if client.inn is not None:
        data["clientInn"] = client.inn

    if client.phone is not None:
        data["clientPhone"] = client.phone

    if client.email is not None:
        data["clientEmail"] = client.email

    response = await self._request(
        "POST",
        url="/invoice",
        json=data,
    )

    return Invoice(**response.json())

cancel_invoice(invoice_id) async

Метод для отмены счёта. Выданный к счёту чек не отменяется, вроде, его надо руками отменять.

Примеры использования

Parameters:

Name Type Description Default
invoice_id int

Номер счёта Invoice.invoice_id

required

Returns:

Name Type Description
Invoice Invoice

Актуальный полный объект счёта

Source code in npdtools/modules/invoice.py
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
async def cancel_invoice(self, invoice_id: int) -> Invoice:
    """
    Метод для отмены счёта. Выданный к счёту чек не отменяется, вроде, его надо руками отменять.

    [Примеры использования](https://npd-tools.readthedocs.io/en/dev/guide/example/#_11)

    Args:
        invoice_id: Номер счёта ``Invoice.invoice_id``

    Returns:
        Invoice: Актуальный полный объект счёта
    """
    response = await self._request(
        "POST",
        url=f"/invoice/{invoice_id}/cancel",
    )

    return Invoice(**response.json())

invoice_paid(invoice_id) async

Метод, чтобы отметить счёт оплаченным. Чек можно выдать позже.

Примеры использования

Parameters:

Name Type Description Default
invoice_id int

Номер счёта Invoice.invoice_id

required

Returns:

Name Type Description
Invoice Invoice

Актуальный полный объект счёта

Source code in npdtools/modules/invoice.py
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
async def invoice_paid(self, invoice_id: int) -> Invoice:
    """
    Метод, чтобы отметить счёт оплаченным. Чек можно выдать позже.

    [Примеры использования](https://npd-tools.readthedocs.io/en/dev/guide/example/#_11)

    Args:
        invoice_id: Номер счёта ``Invoice.invoice_id``

    Returns:
        Invoice: Актуальный полный объект счёта
    """
    response = await self._request(
        "POST",
        url=f"/invoice/{invoice_id}/approve",
    )

    return Invoice(**response.json())

invoice_complete(invoice_id, operation_time=None) async

Метод для выдачи чека к счёту. Счёт автоматически становится оплаченным.

Примеры использования

Parameters:

Name Type Description Default
invoice_id int

Номер счёта Invoice.invoice_id

required
operation_time datetime | str

Дата и время получения денег по счёту.

None

Returns:

Name Type Description
Invoice Invoice

Актуальный полный объект счёта

Source code in npdtools/modules/invoice.py
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
async def invoice_complete(
    self, invoice_id: int, operation_time: datetime | str = None
) -> Invoice:
    """
    Метод для выдачи чека к счёту. Счёт автоматически становится оплаченным.

    [Примеры использования](https://npd-tools.readthedocs.io/en/dev/guide/example/#_11)

    Args:
        invoice_id: Номер счёта ``Invoice.invoice_id``
        operation_time: Дата и время получения денег по счёту.

    Returns:
        Invoice: Актуальный полный объект счёта
    """
    operation_time = (
        operation_time if operation_time is not None else datetime.now()
    )
    data = {
        "invoiceId": invoice_id,
        "requestTime": datetime.now()
        .replace(microsecond=0)
        .astimezone()
        .isoformat(),
        "operationTime": operation_time
        if isinstance(operation_time, str)
        else operation_time.now().replace(microsecond=0).astimezone().isoformat(),
    }
    response = await self._request(
        "POST",
        url=f"/invoice/{invoice_id}/receipt",
        json=data,
    )

    return Invoice(**response.json())

update_invoice_payment_type(invoice_id, bank) async

Метод для смены способа получения денег по счёту

Примеры использования

Parameters:

Name Type Description Default
invoice_id int

Номер счёта Invoice.invoice_id

required
bank BankPhone | BankAccount

Сведения о способе получения денег. Можно создать руками или получить из NPDTools.get_payment_options()

required

Returns:

Name Type Description
Invoice Invoice

Актуальный полный объект счёта

Source code in npdtools/modules/invoice.py
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
async def update_invoice_payment_type(
    self, invoice_id: int, bank: BankPhone | BankAccount
) -> Invoice:
    """
    Метод для смены способа получения денег по счёту

    [Примеры использования](https://npd-tools.readthedocs.io/en/dev/guide/example/#_11)

    Args:
        invoice_id: Номер счёта ``Invoice.invoice_id``
        bank: Сведения о способе получения денег. Можно создать руками или получить из ``NPDTools.get_payment_options()``

    Returns:
        Invoice: Актуальный полный объект счёта
    """
    data = {"invoiceId": invoice_id}

    if isinstance(bank, BankPhone):
        data["paymentType"] = "PHONE"
        data["bankName"] = bank.name
        data["phone"] = bank.phone
    elif isinstance(bank, BankAccount):
        data["paymentType"] = "ACCOUNT"
        data["bankName"] = bank.name
        data["bankBik"] = bank.bik
        data["corrAccount"] = bank.corr
        data["currentAccount"] = bank.account

    response = await self._request(
        "POST",
        url="/invoice/update-payment-info",
        json=data,
    )

    return Invoice(**response.json())

get_payment_options(by_type=None) async

Метод для получения списка сохранённых способов получения денег по счёту

Примеры использования

Parameters:

Name Type Description Default
by_type Literal['PHONE', 'ACCOUNT'] | None

Отфильтровать по типу способа получения

None

Returns:

Name Type Description
PaymentOptions PaymentOptions

Итерируемый объект со списком способов

Source code in npdtools/modules/invoice.py
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
async def get_payment_options(
    self, by_type: Literal["PHONE", "ACCOUNT"] | None = None
) -> PaymentOptions:
    """
    Метод для получения списка сохранённых способов получения денег по счёту

    [Примеры использования](https://npd-tools.readthedocs.io/en/dev/guide/example/#_11)

    Args:
        by_type: Отфильтровать по типу способа получения

    Returns:
        PaymentOptions: Итерируемый объект со списком способов
    """
    response = await self._request(
        "GET",
        url="/payment-type/table",
        params={"type": by_type} if by_type else None,
    )

    return PaymentOptions(**response.json())