@floristcloud/api-lib 1.2.114 → 1.2.116

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -6,6 +6,7 @@ const schemas_1 = require("../../schemas");
6
6
  const CreateCashFlowItemRequestSchema = zod_1.z.object({
7
7
  name: zod_1.z.string().trim().min(1).max(255),
8
8
  sortOrder: zod_1.z.coerce.number().int().optional(),
9
+ excludeFromReports: zod_1.z.boolean().optional(),
9
10
  });
10
11
  const CreateCashFlowItemResponseSchema = zod_1.z.object({
11
12
  message: zod_1.z.string().optional(),
@@ -8,6 +8,7 @@ const UpdateCashFlowItemRequestSchema = zod_1.z.object({
8
8
  name: zod_1.z.string().trim().min(1).max(255).optional(),
9
9
  status: zod_1.z.nativeEnum(cash_flow_item_status_enum_1.CashFlowItemStatusEnum).optional(),
10
10
  sortOrder: zod_1.z.coerce.number().int().optional(),
11
+ excludeFromReports: zod_1.z.boolean().optional(),
11
12
  });
12
13
  const UpdateCashFlowItemResponseSchema = zod_1.z.object({
13
14
  message: zod_1.z.string().optional(),
@@ -32,7 +32,14 @@ const CashFlowItemRowSchema = zod_1.z.object({
32
32
  cashFlowItemName: zod_1.z.string().nullable(),
33
33
  income: money_schema_1.MoneySchema,
34
34
  expense: money_schema_1.MoneySchema,
35
+ // Часть `expense`, которая является расходом бизнеса: без выплат клиентам и возвратов
36
+ // предоплат — они двигают баланс клиента, а не прибыль. Для большинства статей совпадает
37
+ // с `expense`. Флаг статьи здесь НЕ применён: строка со своей суммой видна всегда, а
38
+ // складывать её или нет — решает `excludeFromReports`.
39
+ operatingExpense: money_schema_1.MoneySchema,
35
40
  transactionCount: zod_1.z.number(),
41
+ // Копия флага статьи. У строки "Без статьи" всегда false — такие платежи учитываются.
42
+ excludeFromReports: zod_1.z.boolean(),
36
43
  });
37
44
  const CashFlowMonthRowSchema = CashFlowItemRowSchema.extend({
38
45
  month: zod_1.z.string(),
@@ -48,6 +55,13 @@ const GetCashFlowResponseSchema = zod_1.z.object({
48
55
  // Сальдо (`income - expense`) — знаковая величина, минус здесь легален,
49
56
  // поэтому ограничения на знак нет и быть не должно.
50
57
  total: money_schema_1.MoneySchema,
58
+ // Расход, который вычитается из прибыли на странице отчётов: сумма `operatingExpense`
59
+ // по строкам с `excludeFromReports = false`, включая строку "Без статьи".
60
+ expenseForReports: money_schema_1.MoneySchema,
61
+ // Часть `expenseForReports` без проставленной статьи — величина "из них", а не слагаемое.
62
+ expenseWithoutItem: money_schema_1.MoneySchema,
63
+ // Сколько денег отсекли флагом статьи. Для сноски "мимо отчёта прошло X".
64
+ excludedExpense: money_schema_1.MoneySchema,
51
65
  }),
52
66
  }),
53
67
  });
@@ -0,0 +1,82 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.GetWriteOffSummaryContractQuery = void 0;
4
+ const zod_1 = require("zod");
5
+ const date_helper_1 = require("../../helpers/date.helper");
6
+ const money_schema_1 = require("../../schemas/money.schema");
7
+ const write_off_report_date_basis_enum_1 = require("../../enum/write-off-report-date-basis.enum");
8
+ const report_constant_1 = require("../../constant/report.constant");
9
+ const GetWriteOffSummaryRequestSchema = zod_1.z
10
+ .object({
11
+ startDate: zod_1.z.coerce.date(),
12
+ endDate: zod_1.z.coerce.date(),
13
+ dateBasis: zod_1.z.nativeEnum(write_off_report_date_basis_enum_1.WriteOffReportDateBasisEnum).default(write_off_report_date_basis_enum_1.WriteOffReportDateBasisEnum.WRITE_OFF_DATE),
14
+ // Тот же формат, что в ReportOrderFilterSchema: CSV или повтор параметра. Применяется
15
+ // только к разрезу по клиентам — у складских списаний клиента нет.
16
+ excludeClientUUID: zod_1.z
17
+ .union([zod_1.z.string(), zod_1.z.array(zod_1.z.string())])
18
+ .transform(value => (Array.isArray(value) ? value : value.split(',')).map(item => item.trim()).filter(Boolean))
19
+ .pipe(zod_1.z.array(zod_1.z.string().uuid()).max(report_constant_1.REPORT_EXCLUDE_CLIENT_LIMIT))
20
+ .optional(),
21
+ clientLimit: zod_1.z.coerce
22
+ .number()
23
+ .int()
24
+ .positive()
25
+ .max(report_constant_1.REPORT_WRITE_OFF_CLIENT_LIMIT_MAX)
26
+ .default(report_constant_1.REPORT_WRITE_OFF_CLIENT_LIMIT_DEFAULT),
27
+ })
28
+ .refine(value => (0, date_helper_1.dateRangeCheck)(value.startDate, value.endDate), {
29
+ message: 'validation.dateRange',
30
+ path: ['endDate', 'startDate'],
31
+ })
32
+ .refine(value => (0, date_helper_1.isStatementPeriodWithinLimit)(value.startDate, value.endDate), {
33
+ message: 'validation.reportPeriodMax',
34
+ path: ['endDate', 'startDate'],
35
+ });
36
+ const WriteOffSummaryReasonRowSchema = zod_1.z.object({
37
+ // Свободный текст из справочника причин, схлопнут только по краевым пробелам (TRIM).
38
+ // Регистр не нормализуем: «Брак» и «брак» останутся разными строками.
39
+ reason: zod_1.z.string(),
40
+ units: zod_1.z.number(),
41
+ cost: money_schema_1.MoneySchema,
42
+ });
43
+ const WriteOffSummaryClientRowSchema = zod_1.z.object({
44
+ clientUUID: zod_1.z.string(),
45
+ clientName: zod_1.z.string(),
46
+ orderCount: zod_1.z.number(),
47
+ units: zod_1.z.number(),
48
+ cost: money_schema_1.MoneySchema,
49
+ orderAmount: money_schema_1.MoneySchema,
50
+ });
51
+ const GetWriteOffSummaryResponseSchema = zod_1.z.object({
52
+ message: zod_1.z.string().optional(),
53
+ data: zod_1.z.object({
54
+ // totals = warehouse + byClient, считается по всем строкам — усечение `clientLimit`
55
+ // на итоги не влияет.
56
+ totals: zod_1.z.object({
57
+ units: zod_1.z.number(),
58
+ cost: money_schema_1.MoneySchema,
59
+ }),
60
+ // Списания без заказа: до этого отчёта они не попадали ни в одну сводку.
61
+ warehouse: zod_1.z.object({
62
+ units: zod_1.z.number(),
63
+ cost: money_schema_1.MoneySchema,
64
+ byReason: WriteOffSummaryReasonRowSchema.array(),
65
+ }),
66
+ // Списания по заказу: клиенту они уже вернулись на баланс, то есть это выручка,
67
+ // которой по факту не было.
68
+ byClient: zod_1.z.object({
69
+ units: zod_1.z.number(),
70
+ cost: money_schema_1.MoneySchema,
71
+ orderAmount: money_schema_1.MoneySchema,
72
+ rows: WriteOffSummaryClientRowSchema.array(),
73
+ // Сколько клиентов всего — чтобы отличить усечённый ответ от полного.
74
+ rowsTotal: zod_1.z.number(),
75
+ }),
76
+ }),
77
+ });
78
+ var GetWriteOffSummaryContractQuery;
79
+ (function (GetWriteOffSummaryContractQuery) {
80
+ GetWriteOffSummaryContractQuery.RequestSchema = GetWriteOffSummaryRequestSchema;
81
+ GetWriteOffSummaryContractQuery.ResponseSchema = GetWriteOffSummaryResponseSchema;
82
+ })(GetWriteOffSummaryContractQuery || (exports.GetWriteOffSummaryContractQuery = GetWriteOffSummaryContractQuery = {}));
@@ -28,6 +28,7 @@ __exportStar(require("./export-client-statement.query"), exports);
28
28
  __exportStar(require("./get-report-by-client-weeks.query"), exports);
29
29
  __exportStar(require("./get-daily-orders-summary.query"), exports);
30
30
  __exportStar(require("./get-cash-flow.query"), exports);
31
+ __exportStar(require("./get-write-off-summary.query"), exports);
31
32
  __exportStar(require("./get-inventory-stock.query"), exports);
32
33
  __exportStar(require("./get-inventory-turnover.query"), exports);
33
34
  __exportStar(require("./get-sales-by-client.query"), exports);
@@ -1138,6 +1138,7 @@ exports.ERRORS = {
1138
1138
  REPORT_FETCH_FAILED: { code: 'REP001', message: 'Failed to fetch report', httpCode: 500 },
1139
1139
  REPORT_EXPORT_FAILED: { code: 'REP002', message: 'Failed to export report', httpCode: 500 },
1140
1140
  REPORT_NO_DATA: { code: 'REP003', message: 'No data available for the selected period', httpCode: 404 },
1141
+ WRITE_OFF_SUMMARY_REPORT_FAILED: { code: 'REP004', message: 'Failed to build write-off summary report', httpCode: 500 },
1141
1142
  STATEMENT_PERIOD_TOO_LONG: { code: 'REP004', message: 'Statement period must not exceed 1 year', httpCode: 400 },
1142
1143
  // PAYMENT INVOICE
1143
1144
  PAYMENT_INVOICE_CREATE_FAILED: { code: 'PINV001', message: 'Failed to create payment invoice', httpCode: 500 },
@@ -1,9 +1,16 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.REPORT_EXCLUDE_CLIENT_LIMIT = void 0;
3
+ exports.REPORT_WRITE_OFF_CLIENT_LIMIT_MAX = exports.REPORT_WRITE_OFF_CLIENT_LIMIT_DEFAULT = exports.REPORT_EXCLUDE_CLIENT_LIMIT = void 0;
4
4
  /**
5
5
  * Потолок списка исключаемых из отчёта клиентов. Список едет в query-строке и дальше в SQL
6
6
  * как `= ANY($n::text[])`, поэтому ограничение защищает и от переполнения URL, и от запроса
7
7
  * с массивом в тысячи элементов.
8
8
  */
9
9
  exports.REPORT_EXCLUDE_CLIENT_LIMIT = 500;
10
+ /**
11
+ * Сколько клиентов отдаётся в разрезе списаний по умолчанию и максимум. Итоги считаются по всем
12
+ * строкам независимо от лимита, поэтому усечение влияет только на список; отличить усечённый
13
+ * ответ от полного позволяет `rowsTotal`.
14
+ */
15
+ exports.REPORT_WRITE_OFF_CLIENT_LIMIT_DEFAULT = 50;
16
+ exports.REPORT_WRITE_OFF_CLIENT_LIMIT_MAX = 500;
@@ -116,3 +116,4 @@ __exportStar(require("./payment-invoice-status.enum"), exports);
116
116
  __exportStar(require("./order-by.enum"), exports);
117
117
  __exportStar(require("./report-sort-by.enum"), exports);
118
118
  __exportStar(require("./report-order-date-basis.enum"), exports);
119
+ __exportStar(require("./write-off-report-date-basis.enum"), exports);
@@ -0,0 +1,18 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.WriteOffReportDateBasisEnum = void 0;
4
+ /**
5
+ * По какой дате списание попадает в период отчёта.
6
+ *
7
+ * `WRITE_OFF_DATE` — дата самого списания. На ней живёт блок списаний вкладки «По продажам»:
8
+ * выручка там считается по дате заказа, поэтому списание, оформленное в июле по июньскому
9
+ * заказу, уменьшит операционную прибыль июля. Это осознанное допущение, оно подписано в UI.
10
+ *
11
+ * `CONSIGNMENT_DELIVERY_DATE` — дата поставки партии. На ней построен `/report/profit`, поэтому
12
+ * на этой оси итоги сходятся с его строками «Всего списано» и «Списано по заказам».
13
+ */
14
+ var WriteOffReportDateBasisEnum;
15
+ (function (WriteOffReportDateBasisEnum) {
16
+ WriteOffReportDateBasisEnum["WRITE_OFF_DATE"] = "WRITE_OFF_DATE";
17
+ WriteOffReportDateBasisEnum["CONSIGNMENT_DELIVERY_DATE"] = "CONSIGNMENT_DELIVERY_DATE";
18
+ })(WriteOffReportDateBasisEnum || (exports.WriteOffReportDateBasisEnum = WriteOffReportDateBasisEnum = {}));
@@ -9,6 +9,9 @@ exports.CashFlowItemSchema = zod_1.z.object({
9
9
  name: zod_1.z.string(),
10
10
  status: zod_1.z.nativeEnum(cash_flow_item_status_enum_1.CashFlowItemStatusEnum),
11
11
  sortOrder: zod_1.z.number(),
12
+ // Статья не участвует в расчёте прибыли: перевод между кассами, оплата поставщику (уже сидит
13
+ // в себестоимости), выплата учредителю. На отчёт ДДС не влияет — там остаются все обороты.
14
+ excludeFromReports: zod_1.z.boolean(),
12
15
  createdAt: zod_1.z.date(),
13
16
  updatedAt: zod_1.z.date(),
14
17
  });
@@ -4,6 +4,7 @@ import { CashFlowItemSchema } from '../../schemas';
4
4
  const CreateCashFlowItemRequestSchema = z.object({
5
5
  name: z.string().trim().min(1).max(255),
6
6
  sortOrder: z.coerce.number().int().optional(),
7
+ excludeFromReports: z.boolean().optional(),
7
8
  });
8
9
 
9
10
  const CreateCashFlowItemResponseSchema = z.object({
@@ -6,6 +6,7 @@ const UpdateCashFlowItemRequestSchema = z.object({
6
6
  name: z.string().trim().min(1).max(255).optional(),
7
7
  status: z.nativeEnum(CashFlowItemStatusEnum).optional(),
8
8
  sortOrder: z.coerce.number().int().optional(),
9
+ excludeFromReports: z.boolean().optional(),
9
10
  });
10
11
 
11
12
  const UpdateCashFlowItemResponseSchema = z.object({
@@ -31,7 +31,14 @@ const CashFlowItemRowSchema = z.object({
31
31
  cashFlowItemName: z.string().nullable(),
32
32
  income: MoneySchema,
33
33
  expense: MoneySchema,
34
+ // Часть `expense`, которая является расходом бизнеса: без выплат клиентам и возвратов
35
+ // предоплат — они двигают баланс клиента, а не прибыль. Для большинства статей совпадает
36
+ // с `expense`. Флаг статьи здесь НЕ применён: строка со своей суммой видна всегда, а
37
+ // складывать её или нет — решает `excludeFromReports`.
38
+ operatingExpense: MoneySchema,
34
39
  transactionCount: z.number(),
40
+ // Копия флага статьи. У строки "Без статьи" всегда false — такие платежи учитываются.
41
+ excludeFromReports: z.boolean(),
35
42
  });
36
43
 
37
44
  const CashFlowMonthRowSchema = CashFlowItemRowSchema.extend({
@@ -49,6 +56,13 @@ const GetCashFlowResponseSchema = z.object({
49
56
  // Сальдо (`income - expense`) — знаковая величина, минус здесь легален,
50
57
  // поэтому ограничения на знак нет и быть не должно.
51
58
  total: MoneySchema,
59
+ // Расход, который вычитается из прибыли на странице отчётов: сумма `operatingExpense`
60
+ // по строкам с `excludeFromReports = false`, включая строку "Без статьи".
61
+ expenseForReports: MoneySchema,
62
+ // Часть `expenseForReports` без проставленной статьи — величина "из них", а не слагаемое.
63
+ expenseWithoutItem: MoneySchema,
64
+ // Сколько денег отсекли флагом статьи. Для сноски "мимо отчёта прошло X".
65
+ excludedExpense: MoneySchema,
52
66
  }),
53
67
  }),
54
68
  });
@@ -0,0 +1,90 @@
1
+ import { z } from 'zod';
2
+ import { dateRangeCheck, isStatementPeriodWithinLimit } from '../../helpers/date.helper';
3
+ import { MoneySchema } from '../../schemas/money.schema';
4
+ import { WriteOffReportDateBasisEnum } from '../../enum/write-off-report-date-basis.enum';
5
+ import {
6
+ REPORT_EXCLUDE_CLIENT_LIMIT,
7
+ REPORT_WRITE_OFF_CLIENT_LIMIT_DEFAULT,
8
+ REPORT_WRITE_OFF_CLIENT_LIMIT_MAX,
9
+ } from '../../constant/report.constant';
10
+
11
+ const GetWriteOffSummaryRequestSchema = z
12
+ .object({
13
+ startDate: z.coerce.date(),
14
+ endDate: z.coerce.date(),
15
+ dateBasis: z.nativeEnum(WriteOffReportDateBasisEnum).default(WriteOffReportDateBasisEnum.WRITE_OFF_DATE),
16
+ // Тот же формат, что в ReportOrderFilterSchema: CSV или повтор параметра. Применяется
17
+ // только к разрезу по клиентам — у складских списаний клиента нет.
18
+ excludeClientUUID: z
19
+ .union([z.string(), z.array(z.string())])
20
+ .transform(value => (Array.isArray(value) ? value : value.split(',')).map(item => item.trim()).filter(Boolean))
21
+ .pipe(z.array(z.string().uuid()).max(REPORT_EXCLUDE_CLIENT_LIMIT))
22
+ .optional(),
23
+ clientLimit: z.coerce
24
+ .number()
25
+ .int()
26
+ .positive()
27
+ .max(REPORT_WRITE_OFF_CLIENT_LIMIT_MAX)
28
+ .default(REPORT_WRITE_OFF_CLIENT_LIMIT_DEFAULT),
29
+ })
30
+ .refine(value => dateRangeCheck(value.startDate, value.endDate), {
31
+ message: 'validation.dateRange',
32
+ path: ['endDate', 'startDate'],
33
+ })
34
+ .refine(value => isStatementPeriodWithinLimit(value.startDate, value.endDate), {
35
+ message: 'validation.reportPeriodMax',
36
+ path: ['endDate', 'startDate'],
37
+ });
38
+
39
+ const WriteOffSummaryReasonRowSchema = z.object({
40
+ // Свободный текст из справочника причин, схлопнут только по краевым пробелам (TRIM).
41
+ // Регистр не нормализуем: «Брак» и «брак» останутся разными строками.
42
+ reason: z.string(),
43
+ units: z.number(),
44
+ cost: MoneySchema,
45
+ });
46
+
47
+ const WriteOffSummaryClientRowSchema = z.object({
48
+ clientUUID: z.string(),
49
+ clientName: z.string(),
50
+ orderCount: z.number(),
51
+ units: z.number(),
52
+ cost: MoneySchema,
53
+ orderAmount: MoneySchema,
54
+ });
55
+
56
+ const GetWriteOffSummaryResponseSchema = z.object({
57
+ message: z.string().optional(),
58
+ data: z.object({
59
+ // totals = warehouse + byClient, считается по всем строкам — усечение `clientLimit`
60
+ // на итоги не влияет.
61
+ totals: z.object({
62
+ units: z.number(),
63
+ cost: MoneySchema,
64
+ }),
65
+ // Списания без заказа: до этого отчёта они не попадали ни в одну сводку.
66
+ warehouse: z.object({
67
+ units: z.number(),
68
+ cost: MoneySchema,
69
+ byReason: WriteOffSummaryReasonRowSchema.array(),
70
+ }),
71
+ // Списания по заказу: клиенту они уже вернулись на баланс, то есть это выручка,
72
+ // которой по факту не было.
73
+ byClient: z.object({
74
+ units: z.number(),
75
+ cost: MoneySchema,
76
+ orderAmount: MoneySchema,
77
+ rows: WriteOffSummaryClientRowSchema.array(),
78
+ // Сколько клиентов всего — чтобы отличить усечённый ответ от полного.
79
+ rowsTotal: z.number(),
80
+ }),
81
+ }),
82
+ });
83
+
84
+ export namespace GetWriteOffSummaryContractQuery {
85
+ export const RequestSchema = GetWriteOffSummaryRequestSchema;
86
+ export type Request = z.infer<typeof RequestSchema>;
87
+
88
+ export const ResponseSchema = GetWriteOffSummaryResponseSchema;
89
+ export type Response = z.infer<typeof ResponseSchema>;
90
+ }
@@ -12,6 +12,7 @@ export * from './export-client-statement.query';
12
12
  export * from './get-report-by-client-weeks.query';
13
13
  export * from './get-daily-orders-summary.query';
14
14
  export * from './get-cash-flow.query';
15
+ export * from './get-write-off-summary.query';
15
16
  export * from './get-inventory-stock.query';
16
17
  export * from './get-inventory-turnover.query';
17
18
  export * from './get-sales-by-client.query';
package/constant/error.ts CHANGED
@@ -1185,6 +1185,7 @@ export const ERRORS = {
1185
1185
  REPORT_FETCH_FAILED: { code: 'REP001', message: 'Failed to fetch report', httpCode: 500 },
1186
1186
  REPORT_EXPORT_FAILED: { code: 'REP002', message: 'Failed to export report', httpCode: 500 },
1187
1187
  REPORT_NO_DATA: { code: 'REP003', message: 'No data available for the selected period', httpCode: 404 },
1188
+ WRITE_OFF_SUMMARY_REPORT_FAILED: { code: 'REP004', message: 'Failed to build write-off summary report', httpCode: 500 },
1188
1189
  STATEMENT_PERIOD_TOO_LONG: { code: 'REP004', message: 'Statement period must not exceed 1 year', httpCode: 400 },
1189
1190
 
1190
1191
  // PAYMENT INVOICE
@@ -4,3 +4,12 @@
4
4
  * с массивом в тысячи элементов.
5
5
  */
6
6
  export const REPORT_EXCLUDE_CLIENT_LIMIT = 500;
7
+
8
+ /**
9
+ * Сколько клиентов отдаётся в разрезе списаний по умолчанию и максимум. Итоги считаются по всем
10
+ * строкам независимо от лимита, поэтому усечение влияет только на список; отличить усечённый
11
+ * ответ от полного позволяет `rowsTotal`.
12
+ */
13
+ export const REPORT_WRITE_OFF_CLIENT_LIMIT_DEFAULT = 50;
14
+
15
+ export const REPORT_WRITE_OFF_CLIENT_LIMIT_MAX = 500;
package/enum/index.ts CHANGED
@@ -100,3 +100,4 @@ export * from './payment-invoice-status.enum';
100
100
  export * from './order-by.enum';
101
101
  export * from './report-sort-by.enum';
102
102
  export * from './report-order-date-basis.enum';
103
+ export * from './write-off-report-date-basis.enum';
@@ -0,0 +1,14 @@
1
+ /**
2
+ * По какой дате списание попадает в период отчёта.
3
+ *
4
+ * `WRITE_OFF_DATE` — дата самого списания. На ней живёт блок списаний вкладки «По продажам»:
5
+ * выручка там считается по дате заказа, поэтому списание, оформленное в июле по июньскому
6
+ * заказу, уменьшит операционную прибыль июля. Это осознанное допущение, оно подписано в UI.
7
+ *
8
+ * `CONSIGNMENT_DELIVERY_DATE` — дата поставки партии. На ней построен `/report/profit`, поэтому
9
+ * на этой оси итоги сходятся с его строками «Всего списано» и «Списано по заказам».
10
+ */
11
+ export enum WriteOffReportDateBasisEnum {
12
+ WRITE_OFF_DATE = 'WRITE_OFF_DATE',
13
+ CONSIGNMENT_DELIVERY_DATE = 'CONSIGNMENT_DELIVERY_DATE',
14
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@floristcloud/api-lib",
3
- "version": "1.2.114",
3
+ "version": "1.2.116",
4
4
  "description": "",
5
5
  "main": "./build/index.js",
6
6
  "scripts": {
@@ -7,6 +7,9 @@ export const CashFlowItemSchema = z.object({
7
7
  name: z.string(),
8
8
  status: z.nativeEnum(CashFlowItemStatusEnum),
9
9
  sortOrder: z.number(),
10
+ // Статья не участвует в расчёте прибыли: перевод между кассами, оплата поставщику (уже сидит
11
+ // в себестоимости), выплата учредителю. На отчёт ДДС не влияет — там остаются все обороты.
12
+ excludeFromReports: z.boolean(),
10
13
  createdAt: z.date(),
11
14
  updatedAt: z.date(),
12
15
  });