@placeshakr/config 10.29.4 → 10.31.0-alpha.2
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/dist/auth/policy.js +6 -0
- package/dist/auth/policy.js.map +1 -1
- package/dist/billing/index.js +9 -0
- package/dist/billing/index.js.map +1 -0
- package/dist/billing/pennylane.js +400 -0
- package/dist/billing/pennylane.js.map +1 -0
- package/dist/billing/permissions.js +27 -0
- package/dist/billing/permissions.js.map +1 -0
- package/dist/billing/prefill.js +208 -0
- package/dist/billing/prefill.js.map +1 -0
- package/dist/billing/types.js +3 -0
- package/dist/billing/types.js.map +1 -0
- package/dist/billing/validate.js +189 -0
- package/dist/billing/validate.js.map +1 -0
- package/dist/environment/base.js +28 -0
- package/dist/environment/base.js.map +1 -1
- package/dist/environment/decorators.js +2 -0
- package/dist/environment/decorators.js.map +1 -1
- package/dist/helpers/index.js +1 -0
- package/dist/helpers/index.js.map +1 -1
- package/dist/index.js +3 -1
- package/dist/index.js.map +1 -1
- package/dist/types/auth/policy.d.ts +2 -1
- package/dist/types/auth/policy.d.ts.map +1 -1
- package/dist/types/billing/index.d.ts +6 -0
- package/dist/types/billing/index.d.ts.map +1 -0
- package/dist/types/billing/pennylane.d.ts +191 -0
- package/dist/types/billing/pennylane.d.ts.map +1 -0
- package/dist/types/billing/permissions.d.ts +23 -0
- package/dist/types/billing/permissions.d.ts.map +1 -0
- package/dist/types/billing/prefill.d.ts +42 -0
- package/dist/types/billing/prefill.d.ts.map +1 -0
- package/dist/types/billing/types.d.ts +30 -0
- package/dist/types/billing/types.d.ts.map +1 -0
- package/dist/types/billing/validate.d.ts +48 -0
- package/dist/types/billing/validate.d.ts.map +1 -0
- package/dist/types/environment/base.d.ts.map +1 -1
- package/dist/types/environment/decorators.d.ts.map +1 -1
- package/dist/types/environment/types.d.ts +5 -0
- package/dist/types/environment/types.d.ts.map +1 -1
- package/dist/types/helpers/index.d.ts +1 -0
- package/dist/types/helpers/index.d.ts.map +1 -1
- package/dist/types/index.d.ts +2 -1
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/types.d.ts +491 -0
- package/dist/types/types.d.ts.map +1 -1
- package/dist/types.js +70 -1
- package/dist/types.js.map +1 -1
- package/package.json +2 -2
- package/src/auth/policy.ts +21 -1
- package/src/billing/index.ts +5 -0
- package/src/billing/pennylane.ts +530 -0
- package/src/billing/permissions.ts +25 -0
- package/src/billing/prefill.ts +309 -0
- package/src/billing/types.ts +32 -0
- package/src/billing/validate.ts +198 -0
- package/src/environment/base.ts +30 -0
- package/src/environment/decorators.ts +2 -0
- package/src/environment/types.ts +5 -0
- package/src/helpers/index.ts +2 -0
- package/src/index.ts +2 -0
- package/src/types.ts +524 -0
package/src/types.ts
CHANGED
|
@@ -527,6 +527,8 @@ export interface Enterprise extends Resource {
|
|
|
527
527
|
whatsapp?: boolean;
|
|
528
528
|
marketplace?: boolean;
|
|
529
529
|
multiProfessionals?: boolean;
|
|
530
|
+
/** PennyLane integration: enables the Bills listing and the sync. */
|
|
531
|
+
pennylane?: boolean;
|
|
530
532
|
};
|
|
531
533
|
|
|
532
534
|
/**
|
|
@@ -690,6 +692,13 @@ export interface User extends Resource {
|
|
|
690
692
|
type Permissions = Record<string, boolean>;
|
|
691
693
|
|
|
692
694
|
export interface Profile extends Resource {
|
|
695
|
+
/**
|
|
696
|
+
* The third party's billing data. It lives on Profile — and not on Client,
|
|
697
|
+
* Pro and Seller separately — because all three inherit from it and the SDK
|
|
698
|
+
* writes against this type. See [[BillingIdentity]] and `config/src/billing`.
|
|
699
|
+
*/
|
|
700
|
+
billing?: BillingIdentity;
|
|
701
|
+
|
|
693
702
|
/**
|
|
694
703
|
*
|
|
695
704
|
*/
|
|
@@ -1105,6 +1114,12 @@ export interface Commissions {
|
|
|
1105
1114
|
* Represents an provider
|
|
1106
1115
|
*/
|
|
1107
1116
|
export interface Provider extends Resource {
|
|
1117
|
+
/**
|
|
1118
|
+
* Datos de facturacion. Se completa de forma incremental al facturar.
|
|
1119
|
+
* Ver [[BillingIdentity]] y `config/src/billing`.
|
|
1120
|
+
*/
|
|
1121
|
+
billing?: BillingIdentity;
|
|
1122
|
+
|
|
1108
1123
|
/**
|
|
1109
1124
|
* The provider name
|
|
1110
1125
|
*/
|
|
@@ -2493,9 +2508,33 @@ export type Bill = Resource & {
|
|
|
2493
2508
|
// used to save information related with any possible external system
|
|
2494
2509
|
metadata?: {
|
|
2495
2510
|
sentToIpaidthat?: boolean;
|
|
2511
|
+
/** @deprecated use metadata.pennylane. Kept until email delivery is retired. */
|
|
2496
2512
|
sentToPennyLane?: boolean;
|
|
2513
|
+
/** @deprecated usar metadata.pennylane.lastSyncAt */
|
|
2497
2514
|
sentToPennyLaneDate?: number;
|
|
2515
|
+
/**
|
|
2516
|
+
* PennyLane sync state. Replaces the two booleans above: it holds the
|
|
2517
|
+
* accounting id, the hash of the last payload sent (idempotency) and the
|
|
2518
|
+
* error, so a retry never duplicates.
|
|
2519
|
+
*/
|
|
2520
|
+
pennylane?: PennylaneBillSync;
|
|
2498
2521
|
};
|
|
2522
|
+
|
|
2523
|
+
/**
|
|
2524
|
+
* Where the document came from when it was not created in Articho. Bills
|
|
2525
|
+
* whose source is not undefined are neither edited nor deleted from the app:
|
|
2526
|
+
* the authority on that is firestore.rules.
|
|
2527
|
+
*/
|
|
2528
|
+
source?: 'pennylane';
|
|
2529
|
+
imported?: boolean;
|
|
2530
|
+
|
|
2531
|
+
/**
|
|
2532
|
+
* Billing data of the recipient when they have no record of their own
|
|
2533
|
+
* (fournisseur de matériaux, de services and personnalisé). For CLIENT, PRO
|
|
2534
|
+
* and PROVIDER it lives on the third party's record. See
|
|
2535
|
+
* `config/src/billing`.
|
|
2536
|
+
*/
|
|
2537
|
+
billing?: BillingIdentity;
|
|
2499
2538
|
};
|
|
2500
2539
|
|
|
2501
2540
|
export type BillReceived = Bill & {
|
|
@@ -2656,6 +2695,12 @@ export type Price = {
|
|
|
2656
2695
|
* Represents a materials provider
|
|
2657
2696
|
*/
|
|
2658
2697
|
export interface MaterialsProvider extends Resource {
|
|
2698
|
+
/**
|
|
2699
|
+
* Datos de facturacion. Se completa de forma incremental al facturar.
|
|
2700
|
+
* Ver [[BillingIdentity]] y `config/src/billing`.
|
|
2701
|
+
*/
|
|
2702
|
+
billing?: BillingIdentity;
|
|
2703
|
+
|
|
2659
2704
|
/**
|
|
2660
2705
|
* The material provider name
|
|
2661
2706
|
*/
|
|
@@ -4563,3 +4608,482 @@ export enum EmailEventsEnum {
|
|
|
4563
4608
|
RESET_USER_PASSWORD = 'RESET_USER_PASSWORD',
|
|
4564
4609
|
DOCUMENTS_ISSUES = 'DOCUMENTS_ISSUES',
|
|
4565
4610
|
}
|
|
4611
|
+
|
|
4612
|
+
/* -------------------------------------------------------------------------- */
|
|
4613
|
+
/* PennyLane */
|
|
4614
|
+
/* -------------------------------------------------------------------------- */
|
|
4615
|
+
|
|
4616
|
+
/** Sync state of one specific bill against PennyLane. */
|
|
4617
|
+
export type PennylaneBillSync = {
|
|
4618
|
+
status: 'PENDING' | 'SYNCED' | 'FAILED' | 'SKIPPED';
|
|
4619
|
+
/** Invoice id in PennyLane. */
|
|
4620
|
+
invoiceId?: string;
|
|
4621
|
+
/** Id of the credited invoice in PennyLane (for credit notes). */
|
|
4622
|
+
creditedInvoiceId?: string;
|
|
4623
|
+
/** Id of the PennyLane credit note that cancels this invoice. */
|
|
4624
|
+
creditNoteId?: string;
|
|
4625
|
+
creditNoteNumber?: string;
|
|
4626
|
+
creditNoteStatus?: 'PENDING' | 'SYNCED' | 'FAILED' | 'SKIPPED';
|
|
4627
|
+
creditNoteError?: string;
|
|
4628
|
+
/** Mirror document under enterprises/{id}/importedBills. */
|
|
4629
|
+
importedBillId?: string;
|
|
4630
|
+
fileAttachmentId?: string;
|
|
4631
|
+
/**
|
|
4632
|
+
* Hash of the payload sent. PennyLane offers no Idempotency-Key, so
|
|
4633
|
+
* deduplication is ours: same hash as the last SYNCED, nothing is resent.
|
|
4634
|
+
*/
|
|
4635
|
+
payloadHash?: string;
|
|
4636
|
+
attempts?: number;
|
|
4637
|
+
lastAttemptAt?: number;
|
|
4638
|
+
lastSyncAt?: number;
|
|
4639
|
+
syncedAt?: number;
|
|
4640
|
+
error?: { code: string; message: string; status?: number };
|
|
4641
|
+
};
|
|
4642
|
+
|
|
4643
|
+
/** Which field of the PennyLane invoice each reference is read from. */
|
|
4644
|
+
export type PennylaneReferenceConfig = {
|
|
4645
|
+
/** Field where the supplier writes the chantier reference. */
|
|
4646
|
+
projectField: 'label' | 'invoice_number' | 'lines';
|
|
4647
|
+
/** Field where the supplier writes the devis reference. */
|
|
4648
|
+
devisField: 'label' | 'invoice_number' | 'lines';
|
|
4649
|
+
/** Regular expression with a single capture group. */
|
|
4650
|
+
projectPattern?: string;
|
|
4651
|
+
devisPattern?: string;
|
|
4652
|
+
};
|
|
4653
|
+
|
|
4654
|
+
export type PennylaneIgnoredSupplier = {
|
|
4655
|
+
name: string;
|
|
4656
|
+
regNo?: string | null;
|
|
4657
|
+
pennylaneId?: string | null;
|
|
4658
|
+
ignoredAt: number;
|
|
4659
|
+
ignoredBy?: string | null;
|
|
4660
|
+
};
|
|
4661
|
+
|
|
4662
|
+
/** Per-enterprise PennyLane configuration: enterprises/{id}/configurations/pennylane */
|
|
4663
|
+
export type PennylaneConfiguration = {
|
|
4664
|
+
enabled: boolean;
|
|
4665
|
+
/** Numeric id of the company in PennyLane (e.g. '156553'). */
|
|
4666
|
+
companyId?: string;
|
|
4667
|
+
push: { issued: boolean; received: boolean };
|
|
4668
|
+
pull: { supplierInvoices: boolean };
|
|
4669
|
+
/** false = send aggregate amounts + PDF only. */
|
|
4670
|
+
sendLineItems: boolean;
|
|
4671
|
+
/** true while the accounting mapping is not settled with the accountant. */
|
|
4672
|
+
importAsIncomplete: boolean;
|
|
4673
|
+
references: PennylaneReferenceConfig;
|
|
4674
|
+
/** PennyLane states that are not pulled (drafts and initial noise). */
|
|
4675
|
+
excludedStates?: string[];
|
|
4676
|
+
/** Days to look back on the initial load or a full resync. */
|
|
4677
|
+
lookbackDays?: number;
|
|
4678
|
+
defaultLedgerAccountId?: string;
|
|
4679
|
+
ledgerAccountByCategory?: Record<string, string>;
|
|
4680
|
+
/** Analytical breakdown per chantier. See [[PennylaneCategoryConfig]]. */
|
|
4681
|
+
categories?: PennylaneCategoryConfig;
|
|
4682
|
+
/** Suppliers whose invoices are ignored automatically on sync. */
|
|
4683
|
+
ignoredSuppliers?: PennylaneIgnoredSupplier[];
|
|
4684
|
+
/** Sync state. Written by the Cloud Functions only. */
|
|
4685
|
+
sync?: {
|
|
4686
|
+
supplierInvoices?: PennylaneSyncState;
|
|
4687
|
+
customerInvoices?: PennylaneSyncState;
|
|
4688
|
+
};
|
|
4689
|
+
};
|
|
4690
|
+
|
|
4691
|
+
/**
|
|
4692
|
+
* Analytical breakdown per chantier: one PennyLane category per Articho
|
|
4693
|
+
* project, the same one for that project's issued and received invoices.
|
|
4694
|
+
*
|
|
4695
|
+
* The category GROUP cannot be created through the API: a person creates it in
|
|
4696
|
+
* PennyLane and its id is pasted here. And categories, once created, can NOT
|
|
4697
|
+
* be deleted through the API — only renamed — so they are created lazily: the
|
|
4698
|
+
* first time a project receives or issues an invoice, never when the project
|
|
4699
|
+
* is created. A project that never invoices does not pollute the chart.
|
|
4700
|
+
*/
|
|
4701
|
+
export type PennylaneCategoryConfig = {
|
|
4702
|
+
/** Master switch. Without it the sync never touches categories. */
|
|
4703
|
+
enabled: boolean;
|
|
4704
|
+
/**
|
|
4705
|
+
* Id of the group created by hand in PennyLane (e.g. "Chantiers Articho").
|
|
4706
|
+
* It differs per enterprise: they are separate PennyLane workspaces.
|
|
4707
|
+
*/
|
|
4708
|
+
groupId: number;
|
|
4709
|
+
/** Also categorise the invoices Articho issues. */
|
|
4710
|
+
includeCustomerInvoices?: boolean;
|
|
4711
|
+
};
|
|
4712
|
+
|
|
4713
|
+
export type PennylaneSyncState = {
|
|
4714
|
+
/**
|
|
4715
|
+
* Timestamp of the last change processed. PennyLane's changelog only retains
|
|
4716
|
+
* 4 weeks: if this falls behind, data is lost.
|
|
4717
|
+
*/
|
|
4718
|
+
checkpoint: number;
|
|
4719
|
+
lastRunAt: number;
|
|
4720
|
+
lastError?: string | null;
|
|
4721
|
+
/**
|
|
4722
|
+
* Invoices that failed and must be retried on the next run.
|
|
4723
|
+
*
|
|
4724
|
+
* It exists so the checkpoint can advance even when an invoice fails. The
|
|
4725
|
+
* alternative — holding the checkpoint back whenever there are errors —
|
|
4726
|
+
* looks safer and is not: a single invoice that always fails (a corrupt PDF,
|
|
4727
|
+
* a supplier that never resolves) would freeze the whole enterprise's sync,
|
|
4728
|
+
* reprocessing an ever-growing window until the function times out.
|
|
4729
|
+
*/
|
|
4730
|
+
pending?: PennylanePendingInvoice[];
|
|
4731
|
+
};
|
|
4732
|
+
|
|
4733
|
+
/** An invoice awaiting retry, with its attempt count. */
|
|
4734
|
+
export type PennylanePendingInvoice = {
|
|
4735
|
+
/** Invoice id in PennyLane. */
|
|
4736
|
+
id: string;
|
|
4737
|
+
/** Attempts used. On reaching [[PENNYLANE_MAX_RETRIES]] it is abandoned. */
|
|
4738
|
+
attempts: number;
|
|
4739
|
+
/** Last error, so the reason is visible without opening the logs. */
|
|
4740
|
+
lastError: string;
|
|
4741
|
+
/** When it last failed. */
|
|
4742
|
+
lastAttemptAt: number;
|
|
4743
|
+
};
|
|
4744
|
+
|
|
4745
|
+
export enum ImportedBillStatus {
|
|
4746
|
+
/** Arrived from PennyLane; project or devis could not be resolved. */
|
|
4747
|
+
PENDING_ASSIGNMENT = 'PENDING_ASSIGNMENT',
|
|
4748
|
+
/** Project and devis resolved: waiting for an administrator to confirm. */
|
|
4749
|
+
READY_TO_ASSIGN = 'READY_TO_ASSIGN',
|
|
4750
|
+
/** Already has a bill created inside a project. */
|
|
4751
|
+
ASSIGNED = 'ASSIGNED',
|
|
4752
|
+
/** Discarded by hand. */
|
|
4753
|
+
IGNORED = 'IGNORED',
|
|
4754
|
+
/** Duplicate of another imported invoice. */
|
|
4755
|
+
DUPLICATE = 'DUPLICATE',
|
|
4756
|
+
}
|
|
4757
|
+
|
|
4758
|
+
export enum PennylaneSyncEventType {
|
|
4759
|
+
IMPORTED = 'IMPORTED',
|
|
4760
|
+
EXTERNAL_STATUS_CHANGE = 'EXTERNAL_STATUS_CHANGE',
|
|
4761
|
+
BILL_STATUS_UPDATED = 'BILL_STATUS_UPDATED',
|
|
4762
|
+
ASSIGNED = 'ASSIGNED',
|
|
4763
|
+
IGNORED = 'IGNORED',
|
|
4764
|
+
ERROR = 'ERROR',
|
|
4765
|
+
}
|
|
4766
|
+
|
|
4767
|
+
/**
|
|
4768
|
+
* One event per thing that happens to an imported invoice. Without this, an
|
|
4769
|
+
* invoice that changes status on its own is indistinguishable from a bug.
|
|
4770
|
+
*/
|
|
4771
|
+
export type PennylaneSyncEvent = {
|
|
4772
|
+
id: string;
|
|
4773
|
+
date: number;
|
|
4774
|
+
type: PennylaneSyncEventType;
|
|
4775
|
+
message: string;
|
|
4776
|
+
before?: Record<string, unknown>;
|
|
4777
|
+
after?: Record<string, unknown>;
|
|
4778
|
+
payload?: Record<string, unknown>;
|
|
4779
|
+
};
|
|
4780
|
+
|
|
4781
|
+
/**
|
|
4782
|
+
* Mirror of a PennyLane invoice inside Articho.
|
|
4783
|
+
*
|
|
4784
|
+
* It deliberately lives at enterprise level and not inside a project: an
|
|
4785
|
+
* invoice arriving electronically does not know which project it belongs to.
|
|
4786
|
+
* It is also the source of the "Bills" listing in the administrator menu.
|
|
4787
|
+
*/
|
|
4788
|
+
export type ImportedBill = {
|
|
4789
|
+
id: string;
|
|
4790
|
+
source: 'pennylane';
|
|
4791
|
+
direction: 'supplier' | 'customer';
|
|
4792
|
+
/** Id in PennyLane. The deduplication key. */
|
|
4793
|
+
externalId: string;
|
|
4794
|
+
enterpriseId: string;
|
|
4795
|
+
status: ImportedBillStatus;
|
|
4796
|
+
|
|
4797
|
+
invoice: {
|
|
4798
|
+
reference: string;
|
|
4799
|
+
label?: string;
|
|
4800
|
+
date: number;
|
|
4801
|
+
dueDate?: number | null;
|
|
4802
|
+
currency: string;
|
|
4803
|
+
amountHT: number;
|
|
4804
|
+
amountTVA: number;
|
|
4805
|
+
amountTTC: number;
|
|
4806
|
+
isPaid: boolean;
|
|
4807
|
+
paidAt?: number | null;
|
|
4808
|
+
externalStatus?: string | null;
|
|
4809
|
+
/** How it got into PennyLane: Email, API, PA/PDP… */
|
|
4810
|
+
externalSource?: string | null;
|
|
4811
|
+
fileUrl?: string | null;
|
|
4812
|
+
};
|
|
4813
|
+
|
|
4814
|
+
counterparty: {
|
|
4815
|
+
name: string;
|
|
4816
|
+
regNo?: string | null;
|
|
4817
|
+
pennylaneId?: string | null;
|
|
4818
|
+
};
|
|
4819
|
+
|
|
4820
|
+
/** References exactly as they came on the invoice, and which field they came from. */
|
|
4821
|
+
references: {
|
|
4822
|
+
projectRef?: string | null;
|
|
4823
|
+
devisRef?: string | null;
|
|
4824
|
+
sources?: { project?: string; devis?: string };
|
|
4825
|
+
};
|
|
4826
|
+
|
|
4827
|
+
/** Automatic resolution. It never creates the bill on its own. */
|
|
4828
|
+
suggestion?: {
|
|
4829
|
+
projectId?: string | null;
|
|
4830
|
+
devisId?: string | null;
|
|
4831
|
+
reasons: string[];
|
|
4832
|
+
};
|
|
4833
|
+
|
|
4834
|
+
/** Association confirmed by an administrator. */
|
|
4835
|
+
assignment?: {
|
|
4836
|
+
projectId: string;
|
|
4837
|
+
devisId: string;
|
|
4838
|
+
billId: string;
|
|
4839
|
+
projectName?: string | null;
|
|
4840
|
+
projectReference?: string | null;
|
|
4841
|
+
devisName?: string | null;
|
|
4842
|
+
assignedBy: string;
|
|
4843
|
+
assignedAt: number;
|
|
4844
|
+
} | null;
|
|
4845
|
+
|
|
4846
|
+
lastSyncAt: number;
|
|
4847
|
+
createdAt: number;
|
|
4848
|
+
};
|
|
4849
|
+
|
|
4850
|
+
/* -------------------------------------------------------------------------- */
|
|
4851
|
+
/* Billing identity */
|
|
4852
|
+
/* -------------------------------------------------------------------------- */
|
|
4853
|
+
|
|
4854
|
+
/**
|
|
4855
|
+
* Postal address, broken down.
|
|
4856
|
+
*
|
|
4857
|
+
* The loose `address` field several entities already carry is not usable for
|
|
4858
|
+
* invoicing: PennyLane — and e-invoicing in general — requires street, postal
|
|
4859
|
+
* code, city and country as separate fields. And `GeoLocation` only stores
|
|
4860
|
+
* lat/lng, so there is nothing to derive them from.
|
|
4861
|
+
*/
|
|
4862
|
+
export type PostalAddress = {
|
|
4863
|
+
address: string;
|
|
4864
|
+
postalCode: string;
|
|
4865
|
+
city: string;
|
|
4866
|
+
/** Two-letter ISO code: FR, ES, BE… */
|
|
4867
|
+
countryAlpha2: string;
|
|
4868
|
+
};
|
|
4869
|
+
|
|
4870
|
+
export enum BillingPaymentConditions {
|
|
4871
|
+
UPON_RECEIPT = 'upon_receipt',
|
|
4872
|
+
DAYS_7 = '7_days',
|
|
4873
|
+
DAYS_15 = '15_days',
|
|
4874
|
+
DAYS_30 = '30_days',
|
|
4875
|
+
DAYS_30_EOM = '30_days_end_of_month',
|
|
4876
|
+
DAYS_45 = '45_days',
|
|
4877
|
+
DAYS_45_EOM = '45_days_end_of_month',
|
|
4878
|
+
DAYS_60 = '60_days',
|
|
4879
|
+
}
|
|
4880
|
+
|
|
4881
|
+
export enum BillingLanguage {
|
|
4882
|
+
FR = 'fr_FR',
|
|
4883
|
+
EN = 'en_GB',
|
|
4884
|
+
DE = 'de_DE',
|
|
4885
|
+
ES = 'es_ES',
|
|
4886
|
+
}
|
|
4887
|
+
|
|
4888
|
+
/**
|
|
4889
|
+
* Everything needed to issue an invoice to this entity.
|
|
4890
|
+
*
|
|
4891
|
+
* It is deliberately the same object for the five billable entities (Client,
|
|
4892
|
+
* Pro, Seller, Provider, MaterialsProvider): one type, one validator and one
|
|
4893
|
+
* form, instead of five variants that drift apart.
|
|
4894
|
+
*
|
|
4895
|
+
* It is filled in incrementally: the PennyLane sending modal asks for whatever
|
|
4896
|
+
* is missing right before invoicing and saves it here, so it only ever gets
|
|
4897
|
+
* completed for the entities that actually get invoiced.
|
|
4898
|
+
*/
|
|
4899
|
+
/**
|
|
4900
|
+
* Legal person or natural person.
|
|
4901
|
+
*
|
|
4902
|
+
* Not a cosmetic detail: it decides what the law requires and which PennyLane
|
|
4903
|
+
* endpoint is used. An invoice to a company falls under e-invoicing — SIREN
|
|
4904
|
+
* mandatory, transmitted over the network; one to a private individual is out
|
|
4905
|
+
* of scope and only produces e-reporting, with no client identity.
|
|
4906
|
+
*
|
|
4907
|
+
* `undefined` means "we do not know yet", which is different from the other
|
|
4908
|
+
* two: the form has to ask, not assume.
|
|
4909
|
+
*/
|
|
4910
|
+
export type BillingLegalType = 'company' | 'individual';
|
|
4911
|
+
|
|
4912
|
+
export type BillingIdentity = {
|
|
4913
|
+
/** Company or private individual. See [[BillingLegalType]]. */
|
|
4914
|
+
legalType?: BillingLegalType;
|
|
4915
|
+
|
|
4916
|
+
/**
|
|
4917
|
+
* Legal name. Mandatory for companies.
|
|
4918
|
+
*
|
|
4919
|
+
* It is not asked of an individual: it is composed from first and last name
|
|
4920
|
+
* by [[billingDisplayName]], so the same fact does not live in two places
|
|
4921
|
+
* and end up saying different things.
|
|
4922
|
+
*/
|
|
4923
|
+
legalName: string;
|
|
4924
|
+
|
|
4925
|
+
/** First name. Mandatory for individuals; PennyLane wants it separate. */
|
|
4926
|
+
firstName?: string;
|
|
4927
|
+
/** Last name. Mandatory for individuals. */
|
|
4928
|
+
lastName?: string;
|
|
4929
|
+
/** Billing address. Mandatory. */
|
|
4930
|
+
address: PostalAddress;
|
|
4931
|
+
/** Delivery address, when it differs from the billing one. */
|
|
4932
|
+
deliveryAddress?: PostalAddress;
|
|
4933
|
+
/** SIREN (9 digits) or SIRET (14). */
|
|
4934
|
+
registrationNumber?: string;
|
|
4935
|
+
/** Intra-community VAT number. Not to be confused with the VAT rate. */
|
|
4936
|
+
vatNumber?: string;
|
|
4937
|
+
/** Addresses the invoice is sent to. */
|
|
4938
|
+
emails?: string[];
|
|
4939
|
+
phone?: string;
|
|
4940
|
+
/** Recipient person or department inside the company. */
|
|
4941
|
+
recipient?: string;
|
|
4942
|
+
paymentConditions?: BillingPaymentConditions;
|
|
4943
|
+
language?: BillingLanguage;
|
|
4944
|
+
/** Notes attached to the third party's record. */
|
|
4945
|
+
notes?: string;
|
|
4946
|
+
/**
|
|
4947
|
+
* The third party's id in PennyLane, cached after the first invoice. It
|
|
4948
|
+
* avoids looking it up again and, above all, avoids duplicating the record.
|
|
4949
|
+
*/
|
|
4950
|
+
pennylaneCustomerId?: string;
|
|
4951
|
+
|
|
4952
|
+
/**
|
|
4953
|
+
* What the public register says about the company, exactly as it was last
|
|
4954
|
+
* read. It is not printed on the invoice: it is the provenance of what is
|
|
4955
|
+
* above. See [[BillingInseeData]].
|
|
4956
|
+
*/
|
|
4957
|
+
insee?: BillingInseeData;
|
|
4958
|
+
|
|
4959
|
+
/**
|
|
4960
|
+
* What went wrong the last time this record was completed from the public
|
|
4961
|
+
* registers. Meant to be rendered as a tooltip. See [[BillingEnrichment]].
|
|
4962
|
+
*/
|
|
4963
|
+
enrichment?: BillingEnrichment;
|
|
4964
|
+
|
|
4965
|
+
updatedAt?: number;
|
|
4966
|
+
updatedBy?: string;
|
|
4967
|
+
};
|
|
4968
|
+
|
|
4969
|
+
/**
|
|
4970
|
+
* What the public register says about a third party's company.
|
|
4971
|
+
*
|
|
4972
|
+
* Written by `scripts/enrich-billing-from-insee.js`. It hangs off
|
|
4973
|
+
* [[BillingIdentity]] alongside the rest of what invoicing needs, but in its
|
|
4974
|
+
* own block: the fields above are what gets printed on the invoice and a human
|
|
4975
|
+
* may correct them; this is what the register says and it is rewritten on
|
|
4976
|
+
* every pass.
|
|
4977
|
+
*/
|
|
4978
|
+
export interface BillingInseeData {
|
|
4979
|
+
/** SIREN, 9 digits. */
|
|
4980
|
+
siren?: string;
|
|
4981
|
+
/** SIRET of the establishment queried, 14 digits. */
|
|
4982
|
+
siret?: string;
|
|
4983
|
+
/** Whether the establishment queried is the registered office. */
|
|
4984
|
+
siege?: boolean;
|
|
4985
|
+
/** Legal form (`categorieJuridiqueUniteLegale`). */
|
|
4986
|
+
legalForm?: string | null;
|
|
4987
|
+
/** APE/NAF code (`activitePrincipaleUniteLegale`). */
|
|
4988
|
+
nafCode?: string | null;
|
|
4989
|
+
/** Legal unit state: `A` active, `C` ceased. */
|
|
4990
|
+
state?: string | null;
|
|
4991
|
+
/** Establishment state: `A` open, `F` closed. */
|
|
4992
|
+
establishmentState?: string | null;
|
|
4993
|
+
/** Trade name, when it differs from the legal name. */
|
|
4994
|
+
tradeName?: string | null;
|
|
4995
|
+
/** How it was resolved: `siret`, `siege` or `siege-fallback`. */
|
|
4996
|
+
matchedBy?: string;
|
|
4997
|
+
/**
|
|
4998
|
+
* Set only when the SIREN was absent from the record and was deduced by
|
|
4999
|
+
* searching on the legal name. It keeps a supplied fact distinguishable from
|
|
5000
|
+
* an inferred one.
|
|
5001
|
+
*/
|
|
5002
|
+
sirenFoundBy?: string;
|
|
5003
|
+
/** Result of checking the VAT number against VIES. */
|
|
5004
|
+
vatCheck?: BillingVatCheck;
|
|
5005
|
+
/** When the register was last queried. */
|
|
5006
|
+
checkedAt?: number;
|
|
5007
|
+
}
|
|
5008
|
+
|
|
5009
|
+
/**
|
|
5010
|
+
* Validation of the intra-community VAT number against the VIES register.
|
|
5011
|
+
*
|
|
5012
|
+
* INSEE does not publish the number: it is computed from the SIREN, and the
|
|
5013
|
+
* formula always returns something well-formed, including for someone under
|
|
5014
|
+
* franchise en base who has no real number. `valid: false` means the number
|
|
5015
|
+
* does not exist, not that it is malformed.
|
|
5016
|
+
*/
|
|
5017
|
+
export interface BillingVatCheck {
|
|
5018
|
+
/** The number that was checked. */
|
|
5019
|
+
number: string;
|
|
5020
|
+
status: 'VALID' | 'INVALID' | 'UNAVAILABLE';
|
|
5021
|
+
/** `null` when VIES did not answer: unknown, which is not the same as no. */
|
|
5022
|
+
valid: boolean | null;
|
|
5023
|
+
reason?: string | null;
|
|
5024
|
+
source: string;
|
|
5025
|
+
checkedAt: number;
|
|
5026
|
+
}
|
|
5027
|
+
|
|
5028
|
+
/**
|
|
5029
|
+
* Severity of an enrichment issue.
|
|
5030
|
+
*
|
|
5031
|
+
* - `ok` the record was completed with nothing worth flagging.
|
|
5032
|
+
* - `warning` it was completed, but something is worth a look.
|
|
5033
|
+
* - `error` it could not be completed: the identifier is missing, it is not
|
|
5034
|
+
* in the register, or the lookup failed.
|
|
5035
|
+
*/
|
|
5036
|
+
export type BillingEnrichmentLevel = 'ok' | 'warning' | 'error';
|
|
5037
|
+
|
|
5038
|
+
/**
|
|
5039
|
+
* Code for each issue. It exists so they can be filtered and counted without
|
|
5040
|
+
* parsing the text, which is written to be read and may be reworded.
|
|
5041
|
+
*/
|
|
5042
|
+
export enum BillingEnrichmentCode {
|
|
5043
|
+
/** The record carries neither SIREN nor SIRET. */
|
|
5044
|
+
NO_IDENTIFIER = 'NO_IDENTIFIER',
|
|
5045
|
+
/** Several companies share that legal name: a human must choose. */
|
|
5046
|
+
SIREN_AMBIGUOUS = 'SIREN_AMBIGUOUS',
|
|
5047
|
+
/** The identifier does not appear in the register. */
|
|
5048
|
+
NOT_FOUND = 'NOT_FOUND',
|
|
5049
|
+
/** The legal unit is recorded as ceased. */
|
|
5050
|
+
COMPANY_CLOSED = 'COMPANY_CLOSED',
|
|
5051
|
+
/** The establishment is closed; the company may still be alive. */
|
|
5052
|
+
ESTABLISHMENT_CLOSED = 'ESTABLISHMENT_CLOSED',
|
|
5053
|
+
/** The VAT number is unknown to VIES. Likely franchise en base. */
|
|
5054
|
+
VAT_NOT_REGISTERED = 'VAT_NOT_REGISTERED',
|
|
5055
|
+
/** VIES did not answer: the number was stored unverified. */
|
|
5056
|
+
VAT_UNVERIFIED = 'VAT_UNVERIFIED',
|
|
5057
|
+
/** VIES returns a legal name different from INSEE's. */
|
|
5058
|
+
VAT_NAME_MISMATCH = 'VAT_NAME_MISMATCH',
|
|
5059
|
+
/** Establishment outside France: the country must be filled in by hand. */
|
|
5060
|
+
FOREIGN_ADDRESS = 'FOREIGN_ADDRESS',
|
|
5061
|
+
MISSING_POSTAL_CODE = 'MISSING_POSTAL_CODE',
|
|
5062
|
+
MISSING_STREET = 'MISSING_STREET',
|
|
5063
|
+
/** The register lookup failed (network, quota, credentials). */
|
|
5064
|
+
LOOKUP_ERROR = 'LOOKUP_ERROR',
|
|
5065
|
+
}
|
|
5066
|
+
|
|
5067
|
+
/**
|
|
5068
|
+
* What happened the last time this record's billing data was completed from
|
|
5069
|
+
* the public registers.
|
|
5070
|
+
*
|
|
5071
|
+
* `text` is the field meant to be displayed: plain text, one message per line,
|
|
5072
|
+
* ready for a `title` or a tooltip. `messages` and `codes` are there for
|
|
5073
|
+
* whoever prefers to render them separately or filter by issue type.
|
|
5074
|
+
*
|
|
5075
|
+
* The whole block is rewritten on every pass. Its absence means the record was
|
|
5076
|
+
* never reviewed; `level` being `ok` means it was reviewed and there was
|
|
5077
|
+
* nothing to flag.
|
|
5078
|
+
*/
|
|
5079
|
+
export interface BillingEnrichment {
|
|
5080
|
+
/** One message per line, separated by `\n`. Empty when `level` is `ok`. */
|
|
5081
|
+
text: string;
|
|
5082
|
+
/** The same messages, unjoined. */
|
|
5083
|
+
messages: string[];
|
|
5084
|
+
codes: BillingEnrichmentCode[];
|
|
5085
|
+
level: BillingEnrichmentLevel;
|
|
5086
|
+
/** Who wrote it, e.g. `insee-script`. */
|
|
5087
|
+
source: string;
|
|
5088
|
+
checkedAt: number;
|
|
5089
|
+
}
|