arcli 1.7.1 → 2.0.0
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.
- package/CHANGELOG.md +78 -1
- package/README.md +11 -18
- package/dist/cli/commands/billing.command.options.js +17 -15
- package/dist/cli/commands/billing.command.options.js.map +1 -1
- package/dist/cli/commands/billing.command.parser.js +57 -28
- package/dist/cli/commands/billing.command.parser.js.map +1 -1
- package/dist/cli/commands/billing.command.pdf.d.ts +1 -1
- package/dist/cli/commands/billing.command.pdf.js +17 -2
- package/dist/cli/commands/billing.command.pdf.js.map +1 -1
- package/dist/cli/commands/config.command.js +4 -2
- package/dist/cli/commands/config.command.js.map +1 -1
- package/dist/cli/commands/vouchers.command.js +7 -6
- package/dist/cli/commands/vouchers.command.js.map +1 -1
- package/dist/cli/error-output.d.ts +7 -0
- package/dist/cli/error-output.js +26 -0
- package/dist/cli/error-output.js.map +1 -0
- package/dist/cli/help-argv.d.ts +5 -0
- package/dist/cli/help-argv.js +21 -0
- package/dist/cli/help-argv.js.map +1 -0
- package/dist/cli/help.js +4 -3
- package/dist/cli/help.js.map +1 -1
- package/dist/cli/index.js +14 -20
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/interactive/advanced-options.js +2 -2
- package/dist/cli/interactive/advanced-options.js.map +1 -1
- package/dist/cli/interactive/config.flow.d.ts +1 -1
- package/dist/cli/interactive/config.flow.js +53 -18
- package/dist/cli/interactive/config.flow.js.map +1 -1
- package/dist/cli/interactive/history.flow.d.ts +4 -0
- package/dist/cli/interactive/history.flow.js +22 -8
- package/dist/cli/interactive/history.flow.js.map +1 -1
- package/dist/cli/interactive/interactive-mode.js +99 -17
- package/dist/cli/interactive/interactive-mode.js.map +1 -1
- package/dist/cli/interactive/invoice-picker.d.ts +25 -0
- package/dist/cli/interactive/invoice-picker.js +153 -0
- package/dist/cli/interactive/invoice-picker.js.map +1 -0
- package/dist/cli/interactive/note.flow.d.ts +8 -2
- package/dist/cli/interactive/note.flow.js +39 -37
- package/dist/cli/interactive/note.flow.js.map +1 -1
- package/dist/cli/interactive/pdf.flow.js +33 -22
- package/dist/cli/interactive/pdf.flow.js.map +1 -1
- package/dist/cli/interactive/prompts.d.ts +36 -5
- package/dist/cli/interactive/prompts.js +185 -19
- package/dist/cli/interactive/prompts.js.map +1 -1
- package/dist/cli/interactive/repeat.flow.js +26 -17
- package/dist/cli/interactive/repeat.flow.js.map +1 -1
- package/dist/cli/interactive/status.flow.d.ts +3 -0
- package/dist/cli/interactive/status.flow.js +29 -0
- package/dist/cli/interactive/status.flow.js.map +1 -0
- package/dist/cli/interactive/update.flow.d.ts +6 -0
- package/dist/cli/interactive/update.flow.js +26 -0
- package/dist/cli/interactive/update.flow.js.map +1 -0
- package/dist/cli/interactive/validators.js +8 -4
- package/dist/cli/interactive/validators.js.map +1 -1
- package/dist/cli/option-parsers.d.ts +6 -0
- package/dist/cli/option-parsers.js +34 -0
- package/dist/cli/option-parsers.js.map +1 -0
- package/dist/cli/version.d.ts +1 -1
- package/dist/cli/version.js +1 -1
- package/dist/lib/dates/arca-date.d.ts +13 -0
- package/dist/lib/dates/arca-date.js +28 -11
- package/dist/lib/dates/arca-date.js.map +1 -1
- package/dist/lib/errors/app-error.d.ts +3 -0
- package/dist/lib/errors/app-error.js +3 -0
- package/dist/lib/errors/app-error.js.map +1 -1
- package/dist/lib/files/restrict-to-owner.d.ts +7 -0
- package/dist/lib/files/restrict-to-owner.js +19 -0
- package/dist/lib/files/restrict-to-owner.js.map +1 -0
- package/dist/lib/identity/format-cuit.d.ts +2 -0
- package/dist/lib/identity/format-cuit.js +6 -0
- package/dist/lib/identity/format-cuit.js.map +1 -0
- package/dist/lib/numbers/argentine-amount.d.ts +23 -0
- package/dist/lib/numbers/argentine-amount.js +37 -0
- package/dist/lib/numbers/argentine-amount.js.map +1 -0
- package/dist/lib/numbers/strict-integer.d.ts +4 -0
- package/dist/lib/numbers/strict-integer.js +10 -0
- package/dist/lib/numbers/strict-integer.js.map +1 -0
- package/dist/lib/security/pem.js +5 -1
- package/dist/lib/security/pem.js.map +1 -1
- package/dist/modules/billing/billing-response.js +3 -2
- package/dist/modules/billing/billing-response.js.map +1 -1
- package/dist/modules/billing/billing.amounts.d.ts +2 -0
- package/dist/modules/billing/billing.amounts.js +6 -3
- package/dist/modules/billing/billing.amounts.js.map +1 -1
- package/dist/modules/billing/billing.associated-vouchers.js +14 -3
- package/dist/modules/billing/billing.associated-vouchers.js.map +1 -1
- package/dist/modules/billing/billing.batch.js +6 -0
- package/dist/modules/billing/billing.batch.js.map +1 -1
- package/dist/modules/billing/billing.date-range.js +14 -9
- package/dist/modules/billing/billing.date-range.js.map +1 -1
- package/dist/modules/billing/billing.display.js +4 -4
- package/dist/modules/billing/billing.display.js.map +1 -1
- package/dist/modules/billing/billing.errors.d.ts +12 -0
- package/dist/modules/billing/billing.errors.js +18 -0
- package/dist/modules/billing/billing.errors.js.map +1 -0
- package/dist/modules/billing/billing.schemas.js +13 -5
- package/dist/modules/billing/billing.schemas.js.map +1 -1
- package/dist/modules/billing/billing.service.js +10 -3
- package/dist/modules/billing/billing.service.js.map +1 -1
- package/dist/modules/billing/billing.validation.js +4 -0
- package/dist/modules/billing/billing.validation.js.map +1 -1
- package/dist/modules/config/config-value-parser.d.ts +1 -1
- package/dist/modules/config/config-value-parser.js +21 -9
- package/dist/modules/config/config-value-parser.js.map +1 -1
- package/dist/modules/config/config.presenter.d.ts +4 -0
- package/dist/modules/config/config.presenter.js +57 -37
- package/dist/modules/config/config.presenter.js.map +1 -1
- package/dist/modules/config/config.schemas.d.ts +4 -2
- package/dist/modules/config/config.schemas.js +4 -0
- package/dist/modules/config/config.schemas.js.map +1 -1
- package/dist/modules/config/config.sections.d.ts +14 -0
- package/dist/modules/config/config.sections.js +61 -0
- package/dist/modules/config/config.sections.js.map +1 -0
- package/dist/modules/config/config.service.d.ts +5 -0
- package/dist/modules/config/config.service.js +30 -6
- package/dist/modules/config/config.service.js.map +1 -1
- package/dist/modules/examples/examples.js +5 -1
- package/dist/modules/examples/examples.js.map +1 -1
- package/dist/modules/interactive/amount-input.d.ts +3 -5
- package/dist/modules/interactive/amount-input.js +9 -26
- package/dist/modules/interactive/amount-input.js.map +1 -1
- package/dist/modules/interactive/config-fields.d.ts +1 -3
- package/dist/modules/interactive/config-fields.js +37 -42
- package/dist/modules/interactive/config-fields.js.map +1 -1
- package/dist/modules/interactive/equivalent-command.js +6 -8
- package/dist/modules/interactive/equivalent-command.js.map +1 -1
- package/dist/modules/interactive/invoice-copy.d.ts +19 -0
- package/dist/modules/interactive/invoice-copy.js +26 -0
- package/dist/modules/interactive/invoice-copy.js.map +1 -0
- package/dist/modules/interactive/periods.d.ts +2 -2
- package/dist/modules/interactive/periods.js +8 -4
- package/dist/modules/interactive/periods.js.map +1 -1
- package/dist/modules/parameters/health.d.ts +17 -0
- package/dist/modules/parameters/health.js +29 -0
- package/dist/modules/parameters/health.js.map +1 -0
- package/dist/modules/pdf/pdf.errors.d.ts +0 -1
- package/dist/modules/pdf/pdf.errors.js +1 -3
- package/dist/modules/pdf/pdf.errors.js.map +1 -1
- package/dist/modules/storybook/showcase.js +4 -1
- package/dist/modules/storybook/showcase.js.map +1 -1
- package/dist/modules/update-check/changelog.d.ts +23 -0
- package/dist/modules/update-check/changelog.js +99 -0
- package/dist/modules/update-check/changelog.js.map +1 -0
- package/dist/modules/update-check/update-check.presenter.d.ts +4 -0
- package/dist/modules/update-check/update-check.presenter.js +80 -2
- package/dist/modules/update-check/update-check.presenter.js.map +1 -1
- package/dist/modules/update-check/update-check.service.d.ts +3 -0
- package/dist/modules/update-check/update-check.service.js +2 -2
- package/dist/modules/update-check/update-check.service.js.map +1 -1
- package/dist/modules/vouchers/voucher-history.d.ts +9 -4
- package/dist/modules/vouchers/voucher-history.js +8 -3
- package/dist/modules/vouchers/voucher-history.js.map +1 -1
- package/dist/modules/vouchers/voucher-history.presenter.d.ts +9 -2
- package/dist/modules/vouchers/voucher-history.presenter.js +53 -15
- package/dist/modules/vouchers/voucher-history.presenter.js.map +1 -1
- package/dist/services/arca/arca-context.resolver.js +5 -0
- package/dist/services/arca/arca-context.resolver.js.map +1 -1
- package/dist/services/clipboard/clipboard.d.ts +2 -0
- package/dist/services/clipboard/clipboard.js +17 -0
- package/dist/services/clipboard/clipboard.js.map +1 -0
- package/dist/services/pdf/escape-html.d.ts +6 -0
- package/dist/services/pdf/escape-html.js +25 -0
- package/dist/services/pdf/escape-html.js.map +1 -0
- package/dist/services/pdf/pdf-exporter.js +2 -1
- package/dist/services/pdf/pdf-exporter.js.map +1 -1
- package/dist/ui/components/statusBar.d.ts +15 -2
- package/dist/ui/components/statusBar.js +18 -9
- package/dist/ui/components/statusBar.js.map +1 -1
- package/dist/ui/presenters/errors.presenter.js +5 -4
- package/dist/ui/presenters/errors.presenter.js.map +1 -1
- package/dist/ui/primitives/renderLogo.d.ts +2 -1
- package/dist/ui/primitives/renderLogo.js +21 -4
- package/dist/ui/primitives/renderLogo.js.map +1 -1
- package/dist/ui/primitives/renderPanel.d.ts +2 -0
- package/dist/ui/primitives/renderPanel.js +15 -5
- package/dist/ui/primitives/renderPanel.js.map +1 -1
- package/dist/ui/stream/terminal-stream.d.ts +6 -0
- package/dist/ui/stream/terminal-stream.js +15 -1
- package/dist/ui/stream/terminal-stream.js.map +1 -1
- package/dist/ui/theme/theme.d.ts +3 -3
- package/dist/ui/theme/theme.js +14 -3
- package/dist/ui/theme/theme.js.map +1 -1
- package/llms.txt +12 -10
- package/package.json +1 -1
- package/dist/cli/interactive/lookup.flow.d.ts +0 -5
- package/dist/cli/interactive/lookup.flow.js +0 -72
- package/dist/cli/interactive/lookup.flow.js.map +0 -1
|
@@ -1,14 +1,22 @@
|
|
|
1
|
+
import { Separator } from '@inquirer/select';
|
|
2
|
+
import { formatCuit } from '../../lib/identity/format-cuit.js';
|
|
1
3
|
import { ConfigService } from '../../modules/config/config.service.js';
|
|
2
4
|
import { listMissingSetupKeys } from '../../modules/interactive/config-fields.js';
|
|
5
|
+
import { checkArcaHealth } from '../../modules/parameters/health.js';
|
|
6
|
+
import { checkForUpdate } from '../../modules/update-check/update-check.service.js';
|
|
7
|
+
import { ArcaParametersGateway } from '../../services/arca/arca-parameters.gateway.js';
|
|
3
8
|
import { colorize, formatCliError, noticePanel, renderLogo, statusBar, writeTerminalError, writeTerminalOutput, } from '../../ui/index.js';
|
|
9
|
+
import { startSpinner } from '../spinner.js';
|
|
10
|
+
import { CLI_VERSION } from '../version.js';
|
|
4
11
|
import { runConfigMenu, runGuidedSetup } from './config.flow.js';
|
|
5
12
|
import { runHistoryFlow } from './history.flow.js';
|
|
6
13
|
import { runInvoiceFlow } from './invoice.flow.js';
|
|
7
|
-
import { runLookupFlow, runStatusFlow } from './lookup.flow.js';
|
|
8
14
|
import { runNoteFlow } from './note.flow.js';
|
|
9
15
|
import { chooseOne, confirm, isPromptCancellation } from './prompts.js';
|
|
10
16
|
import { runRepeatFlow } from './repeat.flow.js';
|
|
11
17
|
import { createInteractiveSession } from './session.js';
|
|
18
|
+
import { runStatusFlow } from './status.flow.js';
|
|
19
|
+
import { runUpdateFlow } from './update.flow.js';
|
|
12
20
|
function listMissingSetup() {
|
|
13
21
|
const service = new ConfigService();
|
|
14
22
|
try {
|
|
@@ -42,34 +50,87 @@ async function runOption(option, options) {
|
|
|
42
50
|
await runInvoiceFlow(session);
|
|
43
51
|
if (option === 'repetir')
|
|
44
52
|
await runRepeatFlow(session);
|
|
45
|
-
if (option === 'nota')
|
|
46
|
-
await runNoteFlow(session);
|
|
53
|
+
if (option === 'nota-credito')
|
|
54
|
+
await runNoteFlow(session, 'credito');
|
|
55
|
+
if (option === 'nota-debito')
|
|
56
|
+
await runNoteFlow(session, 'debito');
|
|
47
57
|
if (option === 'historial')
|
|
48
58
|
await runHistoryFlow(session);
|
|
49
|
-
if (option === 'consultar')
|
|
50
|
-
await runLookupFlow(session);
|
|
51
59
|
if (option === 'estado')
|
|
52
60
|
await runStatusFlow(session);
|
|
53
61
|
}
|
|
54
|
-
|
|
62
|
+
const HEALTH_LABELS = {
|
|
63
|
+
'con-demoras': ['ARCA con demoras', 'warning'],
|
|
64
|
+
'con-problemas': ['ARCA con problemas', 'danger'],
|
|
65
|
+
funcionando: ['ARCA funcionando', 'success'],
|
|
66
|
+
'sin-respuesta': ['ARCA sin respuesta', 'danger'],
|
|
67
|
+
};
|
|
68
|
+
function tryResolveSession(options) {
|
|
55
69
|
try {
|
|
56
|
-
|
|
57
|
-
return statusBar('Modo interactivo', `${environment} · PV ${pointOfSale ?? 'sin configurar'}`, environment === 'produccion' ? 'danger' : 'warning');
|
|
70
|
+
return createInteractiveSession(options);
|
|
58
71
|
}
|
|
59
72
|
catch {
|
|
60
|
-
return
|
|
73
|
+
return undefined;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
/** La razon social, si es tan larga que no entra en la barra, se corta. */
|
|
77
|
+
const MAX_ISSUER_NAME_LENGTH = 32;
|
|
78
|
+
/**
|
|
79
|
+
* Barra de estado: a la izquierda, quien emite (razon social, o el CUIT si no esta configurada) y el punto de
|
|
80
|
+
* venta; a la derecha, como esta ARCA y el entorno, cada uno en su color.
|
|
81
|
+
*/
|
|
82
|
+
async function buildHeader(options) {
|
|
83
|
+
const session = tryResolveSession(options);
|
|
84
|
+
if (!session) {
|
|
85
|
+
return statusBar([{ text: 'falta completar la configuracion' }], [{ color: 'muted', text: 'ARCA SIN VERIFICAR' }]);
|
|
86
|
+
}
|
|
87
|
+
const spinner = startSpinner('Consultando el estado de ARCA...');
|
|
88
|
+
const health = await checkArcaHealth({ gateway: new ArcaParametersGateway(session.arca) });
|
|
89
|
+
spinner?.stop();
|
|
90
|
+
const [label, color] = HEALTH_LABELS[health];
|
|
91
|
+
const { config, context, environment, pointOfSale } = session.runtime;
|
|
92
|
+
return statusBar([
|
|
93
|
+
{ text: formatIssuer(config.emisor?.razonSocial, context.cuit) },
|
|
94
|
+
{ text: `PV ${pointOfSale ?? 'sin configurar'}` },
|
|
95
|
+
], [
|
|
96
|
+
{ color, text: label.toUpperCase() },
|
|
97
|
+
environment === 'produccion'
|
|
98
|
+
? { color: 'production', text: 'PRODUCCION' }
|
|
99
|
+
: { color: 'testing', text: 'TESTING' },
|
|
100
|
+
], { rightSeparator: 'rule' });
|
|
101
|
+
}
|
|
102
|
+
function formatIssuer(businessName, cuit) {
|
|
103
|
+
if (!businessName) {
|
|
104
|
+
return formatCuit(cuit);
|
|
61
105
|
}
|
|
106
|
+
return businessName.length > MAX_ISSUER_NAME_LENGTH
|
|
107
|
+
? `${businessName.slice(0, MAX_ISSUER_NAME_LENGTH - 1).trimEnd()}…`
|
|
108
|
+
: businessName;
|
|
109
|
+
}
|
|
110
|
+
function updateChoice(update) {
|
|
111
|
+
const name = `Actualizar a la version ${update.latestVersion}`;
|
|
112
|
+
return { name: colorize(name, 'highlight'), short: name, value: 'actualizar' };
|
|
62
113
|
}
|
|
63
114
|
/** Asistente paso a paso encima del CLI. Ctrl+C cancela el flujo actual; en el menu, sale. */
|
|
64
115
|
export async function runInteractiveMode(options = {}) {
|
|
65
|
-
//
|
|
66
|
-
|
|
116
|
+
// En el modo interactivo se consulta npm siempre (no una vez por dia): la consulta va en paralelo con ARCA.
|
|
117
|
+
const updatePromise = checkForUpdate(CLI_VERSION, { maxAgeMs: 0 }).catch(() => null);
|
|
118
|
+
// Dos lineas en blanco entre el logo y la barra. La barra se escribe aparte porque, mientras se consulta ARCA,
|
|
119
|
+
// en su lugar va el spinner. Debajo, una linea en blanco fija: al responder el menu, @inquirer saca las lineas
|
|
120
|
+
// de su prefijo y sin esta la respuesta quedaria pegada a la barra (ver `compactTop` en el primer menu).
|
|
121
|
+
process.stdout.write(`${renderLogo(CLI_VERSION).trimEnd()}\n\n\n`);
|
|
122
|
+
process.stdout.write(`${await buildHeader(options)}\n\n`);
|
|
123
|
+
const update = await updatePromise;
|
|
124
|
+
// El menu va justo debajo de la barra solo la primera vez; despues, debajo de lo que mostro cada flujo.
|
|
125
|
+
let menuUnderHeader = true;
|
|
67
126
|
// Primera vez: sin CUIT, certificado o punto de venta no se puede hacer nada, asi que se ofrece la guia.
|
|
68
127
|
if (listMissingSetup().length > 0) {
|
|
128
|
+
menuUnderHeader = false;
|
|
69
129
|
try {
|
|
70
130
|
if (await confirm('Falta completar la configuracion. ¿La hacemos ahora, paso a paso?', 'Si, configurar', 'Despues')) {
|
|
71
131
|
await runGuidedSetup();
|
|
72
|
-
writeTerminalOutput(
|
|
132
|
+
writeTerminalOutput(await buildHeader(options));
|
|
133
|
+
menuUnderHeader = true;
|
|
73
134
|
}
|
|
74
135
|
}
|
|
75
136
|
catch (error) {
|
|
@@ -82,19 +143,34 @@ export async function runInteractiveMode(options = {}) {
|
|
|
82
143
|
let option;
|
|
83
144
|
try {
|
|
84
145
|
option = await chooseOne('¿Que queres hacer?', [
|
|
146
|
+
...(update ? [updateChoice(update), new Separator(' ')] : []),
|
|
85
147
|
{ name: 'Emitir factura', value: 'factura' },
|
|
86
148
|
{
|
|
87
149
|
description: 'Copia una de las ultimas, con fechas nuevas',
|
|
88
150
|
name: 'Repetir una factura anterior',
|
|
89
151
|
value: 'repetir',
|
|
90
152
|
},
|
|
91
|
-
{
|
|
92
|
-
|
|
93
|
-
|
|
153
|
+
{
|
|
154
|
+
description: 'Descuento, devolucion o anulacion de una factura',
|
|
155
|
+
name: 'Emitir nota de credito',
|
|
156
|
+
value: 'nota-credito',
|
|
157
|
+
},
|
|
158
|
+
{ description: 'Cargo adicional sobre una factura', name: 'Emitir nota de debito', value: 'nota-debito' },
|
|
159
|
+
{
|
|
160
|
+
description: 'Los ultimos de cada tipo, o buscar uno por numero',
|
|
161
|
+
name: 'Consultar comprobantes',
|
|
162
|
+
value: 'historial',
|
|
163
|
+
},
|
|
94
164
|
{ description: 'Servidores, punto de venta y cotizacion del dolar', name: 'Estado de ARCA', value: 'estado' },
|
|
95
|
-
{
|
|
165
|
+
{
|
|
166
|
+
description: 'Revisar, configuracion guiada, cambiar un dato y PDF',
|
|
167
|
+
name: 'Configuracion',
|
|
168
|
+
value: 'config',
|
|
169
|
+
},
|
|
170
|
+
new Separator(' '),
|
|
96
171
|
{ name: 'Salir', value: 'salir' },
|
|
97
|
-
]);
|
|
172
|
+
], undefined, { compactTop: menuUnderHeader, escapeLabel: 'salir', escapeValue: 'salir' });
|
|
173
|
+
menuUnderHeader = false;
|
|
98
174
|
}
|
|
99
175
|
catch (error) {
|
|
100
176
|
if (isPromptCancellation(error)) {
|
|
@@ -106,6 +182,12 @@ export async function runInteractiveMode(options = {}) {
|
|
|
106
182
|
break;
|
|
107
183
|
}
|
|
108
184
|
try {
|
|
185
|
+
if (option === 'actualizar') {
|
|
186
|
+
if (update && (await runUpdateFlow(update))) {
|
|
187
|
+
return;
|
|
188
|
+
}
|
|
189
|
+
continue;
|
|
190
|
+
}
|
|
109
191
|
await runOption(option, options);
|
|
110
192
|
}
|
|
111
193
|
catch (error) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"interactive-mode.js","sourceRoot":"","sources":["../../../src/cli/interactive/interactive-mode.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,qCAAqC,CAAC;AACpE,OAAO,EAAE,oBAAoB,EAAE,MAAM,yCAAyC,CAAC;AAC/E,OAAO,EACL,QAAQ,EACR,cAAc,EACd,WAAW,EACX,UAAU,EACV,SAAS,
|
|
1
|
+
{"version":3,"file":"interactive-mode.js","sourceRoot":"","sources":["../../../src/cli/interactive/interactive-mode.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { VoucherKindDefinition } from '../../modules/billing/billing.types';
|
|
2
|
+
import { type Back } from '../../modules/interactive/wizard';
|
|
3
|
+
import { type IssuedVoucher } from '../../modules/vouchers/voucher-history';
|
|
4
|
+
import type { InteractiveSession } from './session';
|
|
5
|
+
/** Comprobante elegido y el punto de venta donde se emitio (a mano puede ser otro que el configurado). */
|
|
6
|
+
export interface PickedInvoice {
|
|
7
|
+
readonly invoice: IssuedVoucher;
|
|
8
|
+
readonly pointOfSale: number;
|
|
9
|
+
}
|
|
10
|
+
interface PickInvoiceOptions {
|
|
11
|
+
readonly message: string;
|
|
12
|
+
/**
|
|
13
|
+
* Modo explorar: en vez de devolver el elegido, lo pasa aca y vuelve a mostrar la lista sin perder lo cargado.
|
|
14
|
+
* Solo se sale con "Volver".
|
|
15
|
+
*/
|
|
16
|
+
readonly onPick?: (picked: PickedInvoice) => Promise<void> | void;
|
|
17
|
+
readonly pointOfSale: number;
|
|
18
|
+
readonly voucherKind: VoucherKindDefinition;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Elegir un comprobante emitido: los ultimos del punto de venta configurado, con opciones para cargar mas
|
|
22
|
+
* o ingresar el numero a mano (por ejemplo, uno viejo o de otro punto de venta).
|
|
23
|
+
*/
|
|
24
|
+
export declare function pickInvoice(session: InteractiveSession, options: PickInvoiceOptions): Promise<Back | PickedInvoice>;
|
|
25
|
+
export {};
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
import { Separator } from '@inquirer/select';
|
|
2
|
+
import { BACK } from '../../modules/interactive/wizard.js';
|
|
3
|
+
import { listVouchersFrom, RECENT_VOUCHERS_LIMIT } from '../../modules/vouchers/voucher-history.js';
|
|
4
|
+
import { formatVoucherNumber, formatVoucherPickerRows } from '../../modules/vouchers/voucher-history.presenter.js';
|
|
5
|
+
import { colorize, noticePanel, statusBarWidth, writeTerminalOutput } from '../../ui/index.js';
|
|
6
|
+
import { startSpinner } from '../spinner.js';
|
|
7
|
+
import { askTextStep, chooseStep, chooseStepWhileLoading, eraseLastAnswer, fitPageSize } from './prompts.js';
|
|
8
|
+
const LOAD_MORE = 'cargar-mas';
|
|
9
|
+
const BY_NUMBER = 'a-mano';
|
|
10
|
+
/** Separa las columnas de cada fila del listado. */
|
|
11
|
+
const COLUMN_SEPARATOR = ' · ';
|
|
12
|
+
/**
|
|
13
|
+
* Linea punteada tenue que enmarca el listado, del mismo ancho que la barra de estado de ARCA.
|
|
14
|
+
* @inquirer deja un espacio antes de cada separador; por eso se resta uno al ancho.
|
|
15
|
+
*/
|
|
16
|
+
function listRule() {
|
|
17
|
+
return new Separator(colorize('┈'.repeat(statusBarWidth() - 1), 'muted'));
|
|
18
|
+
}
|
|
19
|
+
async function withSpinner(text, run) {
|
|
20
|
+
const spinner = startSpinner(text);
|
|
21
|
+
try {
|
|
22
|
+
return await run();
|
|
23
|
+
}
|
|
24
|
+
finally {
|
|
25
|
+
spinner?.stop();
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
function validatePositiveInteger(label) {
|
|
29
|
+
return (value) => {
|
|
30
|
+
const number = Number(value.trim());
|
|
31
|
+
return Number.isInteger(number) && number > 0 ? true : `${label} tiene que ser un numero entero mayor a 0.`;
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
/** Pide punto de venta y numero, y lo busca en ARCA. Volver o un comprobante inexistente vuelven a la lista. */
|
|
35
|
+
async function askVoucherByNumber(session, voucherKind, defaultPointOfSale) {
|
|
36
|
+
const pointOfSaleAnswer = await askTextStep('Punto de venta:', {
|
|
37
|
+
defaultValue: String(defaultPointOfSale),
|
|
38
|
+
validate: validatePositiveInteger('El punto de venta'),
|
|
39
|
+
});
|
|
40
|
+
if (pointOfSaleAnswer === BACK) {
|
|
41
|
+
return BACK;
|
|
42
|
+
}
|
|
43
|
+
const numberAnswer = await askTextStep('Numero:', { validate: validatePositiveInteger('El numero') });
|
|
44
|
+
if (numberAnswer === BACK) {
|
|
45
|
+
return BACK;
|
|
46
|
+
}
|
|
47
|
+
const pointOfSale = Number(pointOfSaleAnswer.trim());
|
|
48
|
+
const number = Number(numberAnswer.trim());
|
|
49
|
+
const invoice = await withSpinner('Buscando en ARCA...', () => session.historyGateway.getVoucher(number, pointOfSale, voucherKind.arcaType));
|
|
50
|
+
if (!invoice) {
|
|
51
|
+
writeTerminalOutput(noticePanel(`No existe la ${voucherKind.displayName} N° ${formatVoucherNumber(pointOfSale, number)}.`, 'warning'));
|
|
52
|
+
return BACK;
|
|
53
|
+
}
|
|
54
|
+
return { invoice, pointOfSale };
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Elegir un comprobante emitido: los ultimos del punto de venta configurado, con opciones para cargar mas
|
|
58
|
+
* o ingresar el numero a mano (por ejemplo, uno viejo o de otro punto de venta).
|
|
59
|
+
*/
|
|
60
|
+
export async function pickInvoice(session, options) {
|
|
61
|
+
const { message, onPick, pointOfSale, voucherKind } = options;
|
|
62
|
+
const { historyGateway } = session;
|
|
63
|
+
// Comprobantes por tanda: los primeros y cada "cargar mas".
|
|
64
|
+
const pageSize = session.runtime.config.comprobantesPorLista ?? RECENT_VOUCHERS_LIMIT;
|
|
65
|
+
const { invoices, lastNumber } = await withSpinner('Buscando en ARCA...', async () => {
|
|
66
|
+
const last = await historyGateway.getLastNumber(pointOfSale, voucherKind.arcaType);
|
|
67
|
+
return {
|
|
68
|
+
invoices: await listVouchersFrom(historyGateway, pointOfSale, voucherKind.arcaType, last, { limit: pageSize }),
|
|
69
|
+
lastNumber: last,
|
|
70
|
+
};
|
|
71
|
+
});
|
|
72
|
+
// Proximo numero a consultar al cargar mas.
|
|
73
|
+
let nextNumber = lastNumber - pageSize;
|
|
74
|
+
let defaultChoice;
|
|
75
|
+
if (invoices.length === 0) {
|
|
76
|
+
writeTerminalOutput(noticePanel(`No hay ${voucherKind.displayName} emitidas en el punto de venta ${pointOfSale}.`, 'warning'));
|
|
77
|
+
}
|
|
78
|
+
// Tanda pedida a ARCA con "cargar mas" mientras la lista sigue en pantalla.
|
|
79
|
+
let loading;
|
|
80
|
+
for (;;) {
|
|
81
|
+
const choices = [];
|
|
82
|
+
// El listado y "cargar mas" van entre lineas punteadas; buscar a mano queda afuera.
|
|
83
|
+
if (invoices.length > 0) {
|
|
84
|
+
// Las filas llegan hasta el final de la linea punteada; el cursor "❯ " ocupa dos columnas.
|
|
85
|
+
const rows = formatVoucherPickerRows(pointOfSale, invoices, COLUMN_SEPARATOR, statusBarWidth() - 2);
|
|
86
|
+
choices.push(listRule(), ...invoices.map((item, index) => ({
|
|
87
|
+
name: rows[index] ?? '',
|
|
88
|
+
// Al elegirla queda solo el numero, no la fila entera.
|
|
89
|
+
short: formatVoucherNumber(pointOfSale, item.number),
|
|
90
|
+
value: item,
|
|
91
|
+
})));
|
|
92
|
+
if (loading) {
|
|
93
|
+
choices.push(new Separator(' '), new Separator(colorize(' Cargando…', 'muted')));
|
|
94
|
+
}
|
|
95
|
+
else if (nextNumber > 0) {
|
|
96
|
+
choices.push(new Separator(' '), { name: '+ Cargar mas…', value: LOAD_MORE });
|
|
97
|
+
}
|
|
98
|
+
choices.push(listRule(), new Separator(' '));
|
|
99
|
+
}
|
|
100
|
+
choices.push({
|
|
101
|
+
description: 'Uno mas viejo o de otro punto de venta',
|
|
102
|
+
name: '# Ingresar el numero a mano…',
|
|
103
|
+
value: BY_NUMBER,
|
|
104
|
+
});
|
|
105
|
+
// +2: el separador y "Volver" que agrega chooseStep.
|
|
106
|
+
const pageSizeOnScreen = fitPageSize(choices.length + 2);
|
|
107
|
+
let answer;
|
|
108
|
+
if (loading) {
|
|
109
|
+
const result = await chooseStepWhileLoading(message, choices, defaultChoice, pageSizeOnScreen, loading);
|
|
110
|
+
loading = undefined;
|
|
111
|
+
if ('loaded' in result) {
|
|
112
|
+
nextNumber -= pageSize;
|
|
113
|
+
// El cursor queda en el primero nuevo; si no vino ninguno, en "cargar mas" o "a mano".
|
|
114
|
+
defaultChoice = result.loaded[0] ?? (nextNumber > 0 ? LOAD_MORE : BY_NUMBER);
|
|
115
|
+
invoices.push(...result.loaded);
|
|
116
|
+
continue;
|
|
117
|
+
}
|
|
118
|
+
// Se eligio otra opcion antes de que terminara la carga: lo que llegue se descarta.
|
|
119
|
+
answer = result.answer;
|
|
120
|
+
}
|
|
121
|
+
else {
|
|
122
|
+
answer = await chooseStep(message, choices, defaultChoice, pageSizeOnScreen);
|
|
123
|
+
}
|
|
124
|
+
if (answer === BACK) {
|
|
125
|
+
return BACK;
|
|
126
|
+
}
|
|
127
|
+
if (answer === LOAD_MORE) {
|
|
128
|
+
// La misma lista se vuelve a dibujar en su lugar, con "Cargando…" en vez del boton.
|
|
129
|
+
eraseLastAnswer();
|
|
130
|
+
loading = listVouchersFrom(historyGateway, pointOfSale, voucherKind.arcaType, nextNumber, { limit: pageSize });
|
|
131
|
+
defaultChoice = invoices.at(-1);
|
|
132
|
+
continue;
|
|
133
|
+
}
|
|
134
|
+
let picked;
|
|
135
|
+
if (answer === BY_NUMBER) {
|
|
136
|
+
const byNumber = await askVoucherByNumber(session, voucherKind, pointOfSale);
|
|
137
|
+
if (byNumber === BACK) {
|
|
138
|
+
defaultChoice = BY_NUMBER;
|
|
139
|
+
continue;
|
|
140
|
+
}
|
|
141
|
+
picked = byNumber;
|
|
142
|
+
}
|
|
143
|
+
else {
|
|
144
|
+
picked = { invoice: answer, pointOfSale };
|
|
145
|
+
}
|
|
146
|
+
if (!onPick) {
|
|
147
|
+
return picked;
|
|
148
|
+
}
|
|
149
|
+
await onPick(picked);
|
|
150
|
+
defaultChoice = answer;
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
//# sourceMappingURL=invoice-picker.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"invoice-picker.js","sourceRoot":"","sources":["../../../src/cli/interactive/invoice-picker.ts"],"names":[],"mappings":"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"}
|
|
@@ -3,16 +3,22 @@ import type { VoucherKindDefinition } from '../../modules/billing/billing.types'
|
|
|
3
3
|
import { type WizardStep } from '../../modules/interactive/wizard';
|
|
4
4
|
import { type IssuedVoucher } from '../../modules/vouchers/voucher-history';
|
|
5
5
|
import { type InteractiveSession } from './session';
|
|
6
|
+
export type NoteKind = 'credito' | 'debito';
|
|
6
7
|
export interface NoteState {
|
|
7
8
|
readonly cancellation?: boolean;
|
|
8
9
|
readonly concept?: BillingConcept;
|
|
9
10
|
readonly documentNumber?: number;
|
|
10
11
|
readonly documentType?: BillingCommandInput['documentType'];
|
|
12
|
+
/** Anula la factura entera: la nota copia exento y no gravado. */
|
|
13
|
+
readonly annulsTotal?: boolean;
|
|
11
14
|
readonly invoice?: IssuedVoucher;
|
|
12
15
|
readonly invoiceKind?: VoucherKindDefinition;
|
|
16
|
+
/** Punto de venta de la factura asociada; ingresada a mano puede no ser el configurado. */
|
|
17
|
+
readonly invoicePointOfSale?: number;
|
|
13
18
|
readonly ivaCondition?: BillingCommandInput['ivaCondition'];
|
|
14
19
|
readonly ivaRate?: BillingCommandInput['ivaRate'];
|
|
15
|
-
|
|
20
|
+
/** Credito o debito: viene del menu principal. */
|
|
21
|
+
readonly kind?: NoteKind;
|
|
16
22
|
readonly periodFrom?: string;
|
|
17
23
|
readonly periodTo?: string;
|
|
18
24
|
/** Sobre una factura de la lista o sobre un periodo (solo notas comunes). */
|
|
@@ -23,4 +29,4 @@ export interface NoteState {
|
|
|
23
29
|
export declare function noteSteps(session: InteractiveSession, pointOfSale: number): Array<WizardStep<NoteState>>;
|
|
24
30
|
/** Arma la entrada del CLI con lo que respondio el usuario. */
|
|
25
31
|
export declare function buildNoteInput(state: NoteState, session: InteractiveSession, pointOfSale: number): BillingCommandInput;
|
|
26
|
-
export declare function runNoteFlow(session: InteractiveSession): Promise<void>;
|
|
32
|
+
export declare function runNoteFlow(session: InteractiveSession, kind: NoteKind): Promise<void>;
|
|
@@ -3,11 +3,11 @@ import { formatMoneyLabel } from '../../modules/billing/billing.labels.js';
|
|
|
3
3
|
import { billingCommandSchema, } from '../../modules/billing/billing.schemas.js';
|
|
4
4
|
import { parseAmountInput } from '../../modules/interactive/amount-input.js';
|
|
5
5
|
import { conceptChoices, invoiceKindChoices, ivaConditionChoices, ivaRateChoices, noteKindChoices, receiverChoices, } from '../../modules/interactive/choices.js';
|
|
6
|
+
import { copyInvoiceAmounts } from '../../modules/interactive/invoice-copy.js';
|
|
6
7
|
import { BACK, runWizard } from '../../modules/interactive/wizard.js';
|
|
7
|
-
import {
|
|
8
|
-
import { formatVoucherSummary } from '../../modules/vouchers/voucher-history.presenter.js';
|
|
8
|
+
import { resolveDocumentType } from '../../modules/vouchers/voucher-history.js';
|
|
9
9
|
import { noticePanel, writeTerminalOutput } from '../../ui/index.js';
|
|
10
|
-
import {
|
|
10
|
+
import { pickInvoice } from './invoice-picker.js';
|
|
11
11
|
import { askTextStep, chooseStep } from './prompts.js';
|
|
12
12
|
import { previewAndEmit, requirePointOfSale } from './session.js';
|
|
13
13
|
import { normalizeDocumentNumber, validateAmount, validateCuit, validateDate, validateDni } from './validators.js';
|
|
@@ -20,13 +20,15 @@ const isPeriod = (state) => state.target === 'periodo';
|
|
|
20
20
|
async function askNoteAmount(state) {
|
|
21
21
|
const invoice = state.invoice;
|
|
22
22
|
const label = state.kind === 'debito' ? 'Monto de la nota de debito:' : 'Monto de la nota de credito:';
|
|
23
|
-
|
|
23
|
+
// Con varias alicuotas o tributos no se puede armar una nota igual a la factura: solo parcial.
|
|
24
|
+
const canAnnulTotal = Boolean(invoice && !copyInvoiceAmounts(invoice, state.invoiceKind?.letter ?? 'c').limitation);
|
|
25
|
+
if (state.kind === 'credito' && invoice && canAnnulTotal) {
|
|
24
26
|
const scope = await chooseStep('¿Total o parcial?', [
|
|
25
27
|
{ name: `Anular el total (${formatMoneyLabel(invoice.total)})`, value: 'total' },
|
|
26
28
|
{ name: 'Parcial (ingresar monto)', value: 'parcial' },
|
|
27
29
|
]);
|
|
28
30
|
if (scope === BACK || scope === 'total') {
|
|
29
|
-
return scope === BACK ? BACK : invoice.total;
|
|
31
|
+
return scope === BACK ? BACK : { annulsTotal: true, totalAmount: invoice.total };
|
|
30
32
|
}
|
|
31
33
|
}
|
|
32
34
|
const answer = await askTextStep(label, {
|
|
@@ -40,21 +42,11 @@ async function askNoteAmount(state) {
|
|
|
40
42
|
: `No puede superar el total de la factura (${formatMoneyLabel(invoice.total)}).`;
|
|
41
43
|
},
|
|
42
44
|
});
|
|
43
|
-
return answer === BACK ? BACK : parseAmountInput(answer);
|
|
45
|
+
return answer === BACK ? BACK : { annulsTotal: false, totalAmount: parseAmountInput(answer) };
|
|
44
46
|
}
|
|
45
47
|
/** Pasos del flujo de notas; cada uno se puede deshacer con "Volver". */
|
|
46
48
|
export function noteSteps(session, pointOfSale) {
|
|
47
49
|
return [
|
|
48
|
-
{
|
|
49
|
-
name: 'nota',
|
|
50
|
-
run: async () => {
|
|
51
|
-
const kind = await chooseStep('¿Que nota queres emitir?', [
|
|
52
|
-
{ name: 'Nota de credito (descuento, devolucion o anulacion)', value: 'credito' },
|
|
53
|
-
{ name: 'Nota de debito (cargo adicional)', value: 'debito' },
|
|
54
|
-
]);
|
|
55
|
-
return kind === BACK ? BACK : { kind };
|
|
56
|
-
},
|
|
57
|
-
},
|
|
58
50
|
{
|
|
59
51
|
name: 'tipo-factura',
|
|
60
52
|
run: async () => {
|
|
@@ -66,7 +58,11 @@ export function noteSteps(session, pointOfSale) {
|
|
|
66
58
|
name: 'asociacion',
|
|
67
59
|
run: async () => {
|
|
68
60
|
const target = await chooseStep('¿A que la asociamos?', [
|
|
69
|
-
{
|
|
61
|
+
{
|
|
62
|
+
description: 'Elegis una de las ultimas emitidas o la ingresas a mano',
|
|
63
|
+
name: 'A una factura',
|
|
64
|
+
value: 'factura',
|
|
65
|
+
},
|
|
70
66
|
{
|
|
71
67
|
description: 'Por ejemplo, un descuento sobre todo el mes',
|
|
72
68
|
name: 'A un periodo',
|
|
@@ -82,33 +78,33 @@ export function noteSteps(session, pointOfSale) {
|
|
|
82
78
|
name: 'factura',
|
|
83
79
|
run: async (state) => {
|
|
84
80
|
const invoiceKind = state.invoiceKind;
|
|
85
|
-
const
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
const invoice = await chooseStep(`¿Sobre que ${invoiceKind.displayName}?`, invoices.map((item) => ({
|
|
92
|
-
description: item.cae ? `CAE ${item.cae}` : undefined,
|
|
93
|
-
name: formatVoucherSummary(pointOfSale, item),
|
|
94
|
-
value: item,
|
|
95
|
-
})));
|
|
96
|
-
if (invoice === BACK) {
|
|
81
|
+
const picked = await pickInvoice(session, {
|
|
82
|
+
message: `¿Sobre que ${invoiceKind.displayName}?`,
|
|
83
|
+
pointOfSale,
|
|
84
|
+
voucherKind: invoiceKind,
|
|
85
|
+
});
|
|
86
|
+
if (picked === BACK) {
|
|
97
87
|
return BACK;
|
|
98
88
|
}
|
|
89
|
+
const { invoice } = picked;
|
|
99
90
|
const documentType = resolveDocumentType(invoice.documentTypeCode);
|
|
100
91
|
if (!documentType) {
|
|
101
92
|
writeTerminalOutput(noticePanel('La factura tiene un tipo de documento que el asistente no soporta. Usa los flags del CLI.', 'warning'));
|
|
102
93
|
return BACK;
|
|
103
94
|
}
|
|
104
|
-
|
|
95
|
+
const copy = copyInvoiceAmounts(invoice, invoiceKind.letter);
|
|
96
|
+
if (copy.limitation) {
|
|
97
|
+
writeTerminalOutput(noticePanel(`${copy.limitation} La nota solo puede ser parcial; revisa la alicuota.`, 'warning'));
|
|
98
|
+
}
|
|
99
|
+
// La nota hereda de la factura el receptor, el concepto, la moneda y la alicuota (si se puede deducir).
|
|
105
100
|
return {
|
|
106
101
|
concept: CONCEPTS_BY_CODE[invoice.concept ?? 2] ?? 'servicios',
|
|
107
102
|
documentNumber: documentType === 'consumidor-final' ? undefined : invoice.documentNumber,
|
|
108
103
|
documentType,
|
|
109
104
|
invoice,
|
|
105
|
+
invoicePointOfSale: picked.pointOfSale,
|
|
110
106
|
ivaCondition: documentType === 'consumidor-final' ? 'consumidor-final' : undefined,
|
|
111
|
-
ivaRate:
|
|
107
|
+
ivaRate: copy.ivaRate,
|
|
112
108
|
};
|
|
113
109
|
},
|
|
114
110
|
skip: isPeriod,
|
|
@@ -121,7 +117,7 @@ export function noteSteps(session, pointOfSale) {
|
|
|
121
117
|
return BACK;
|
|
122
118
|
}
|
|
123
119
|
const periodTo = await askTextStep('Periodo hasta:', { validate: validateDate });
|
|
124
|
-
return periodTo === BACK ? BACK : { invoice: undefined, periodFrom, periodTo };
|
|
120
|
+
return periodTo === BACK ? BACK : { invoice: undefined, invoicePointOfSale: undefined, periodFrom, periodTo };
|
|
125
121
|
},
|
|
126
122
|
skip: (state) => !isPeriod(state),
|
|
127
123
|
},
|
|
@@ -161,8 +157,8 @@ export function noteSteps(session, pointOfSale) {
|
|
|
161
157
|
{
|
|
162
158
|
name: 'monto',
|
|
163
159
|
run: async (state) => {
|
|
164
|
-
const
|
|
165
|
-
return
|
|
160
|
+
const amount = await askNoteAmount(state);
|
|
161
|
+
return amount === BACK ? BACK : amount;
|
|
166
162
|
},
|
|
167
163
|
},
|
|
168
164
|
{
|
|
@@ -201,6 +197,8 @@ export function buildNoteInput(state, session, pointOfSale) {
|
|
|
201
197
|
const invoiceKind = state.invoiceKind;
|
|
202
198
|
const noteKind = noteKindChoices(state.kind ?? 'credito', invoiceKind);
|
|
203
199
|
const invoice = state.invoice;
|
|
200
|
+
// Una nota va en la moneda de su factura; si la anula entera, tambien copia exento y no gravado.
|
|
201
|
+
const copy = !isPeriod(state) && invoice ? copyInvoiceAmounts(invoice, invoiceKind.letter) : undefined;
|
|
204
202
|
return billingCommandSchema.parse({
|
|
205
203
|
associatedPeriod: isPeriod(state) ? { desde: state.periodFrom, hasta: state.periodTo } : undefined,
|
|
206
204
|
associatedVoucher: !isPeriod(state) && invoice
|
|
@@ -208,26 +206,30 @@ export function buildNoteInput(state, session, pointOfSale) {
|
|
|
208
206
|
cuit: String(session.runtime.context.cuit),
|
|
209
207
|
fecha: formatArcaDateAsArgentineDate(invoice.date),
|
|
210
208
|
numero: invoice.number,
|
|
211
|
-
puntoVenta: pointOfSale,
|
|
209
|
+
puntoVenta: state.invoicePointOfSale ?? pointOfSale,
|
|
212
210
|
shortcut: invoiceKind.shortcut,
|
|
213
211
|
}
|
|
214
212
|
: undefined,
|
|
215
213
|
cancellation: state.cancellation ?? false,
|
|
216
214
|
concept: state.concept,
|
|
215
|
+
currencyCode: copy?.currencyCode,
|
|
217
216
|
documentNumber: state.documentType === 'consumidor-final' ? undefined : state.documentNumber,
|
|
218
217
|
documentType: state.documentType,
|
|
218
|
+
exchangeRate: copy?.exchangeRate,
|
|
219
|
+
exemptAmount: state.annulsTotal ? copy?.exemptAmount : undefined,
|
|
219
220
|
ivaCondition: state.ivaCondition,
|
|
220
221
|
ivaRate: state.ivaRate === '21' && !session.runtime.config.alicuotaPorDefecto ? undefined : state.ivaRate,
|
|
221
222
|
shortcut: noteKind.shortcut,
|
|
222
223
|
totalAmount: state.totalAmount,
|
|
224
|
+
untaxedAmount: state.annulsTotal ? copy?.untaxedAmount : undefined,
|
|
223
225
|
});
|
|
224
226
|
}
|
|
225
|
-
export async function runNoteFlow(session) {
|
|
227
|
+
export async function runNoteFlow(session, kind) {
|
|
226
228
|
const pointOfSale = requirePointOfSale(session);
|
|
227
229
|
if (!pointOfSale) {
|
|
228
230
|
return;
|
|
229
231
|
}
|
|
230
|
-
const state = await runWizard(noteSteps(session, pointOfSale), {});
|
|
232
|
+
const state = await runWizard(noteSteps(session, pointOfSale), { kind });
|
|
231
233
|
if (!state) {
|
|
232
234
|
return;
|
|
233
235
|
}
|