Compare commits
3 Commits
581227d5ea
...
c9701a7396
| Author | SHA1 | Date | |
|---|---|---|---|
| c9701a7396 | |||
| 2d9d8214ef | |||
|
|
cf7d7d8f5a |
@ -45,6 +45,9 @@ module.exports = {
|
||||
invoiceCity: req.body.invoiceCity,
|
||||
invoicePhone: req.body.invoicePhone,
|
||||
invoiceEmail: req.body.invoiceEmail,
|
||||
uidNumber: req.body.uidNumber || req.body.uid_number,
|
||||
atuNumber: req.body.atuNumber || req.body.atu_number,
|
||||
taxMode: req.body.taxMode || req.body.tax_mode,
|
||||
contractNumber: req.body.contractNumber || req.body.contract_number,
|
||||
signingCity: req.body.signingCity || req.body.signing_city || '',
|
||||
signatureDataUrl: req.body.signatureDataUrl || req.body.signature_data_url,
|
||||
|
||||
@ -11,6 +11,10 @@ const CAPSULES_PER_PACK = 10;
|
||||
const MIN_ABO_PACKS = 6;
|
||||
const MAX_ABO_PACKS = 10000;
|
||||
|
||||
function normalizeUid(value) {
|
||||
return String(value || '').trim().toUpperCase().replace(/[^A-Z0-9]/g, '');
|
||||
}
|
||||
|
||||
function getPackCountError(totalPacks) {
|
||||
if (totalPacks < MIN_ABO_PACKS) {
|
||||
return `Order must contain at least ${MIN_ABO_PACKS} packs (${MIN_ABO_PACKS * CAPSULES_PER_PACK} capsules).`;
|
||||
@ -85,6 +89,9 @@ class AbonemmentService {
|
||||
invoiceCity,
|
||||
invoicePhone,
|
||||
invoiceEmail,
|
||||
uidNumber,
|
||||
atuNumber,
|
||||
taxMode,
|
||||
contractNumber,
|
||||
signingCity,
|
||||
signatureDataUrl,
|
||||
@ -155,6 +162,7 @@ class AbonemmentService {
|
||||
|
||||
const now = new Date();
|
||||
const nextBilling = this.addInterval(now, billingInterval || 'month', intervalCount || 1);
|
||||
const normalizedInvoiceUid = normalizeUid(uidNumber || atuNumber || '');
|
||||
|
||||
const effectiveRecipientName = recipientName || `${firstName || ''} ${lastName || ''}`.trim() || null;
|
||||
const effectiveEmail = forSelf ? normalizedEmail : normalizedRecipientEmail;
|
||||
@ -174,6 +182,8 @@ class AbonemmentService {
|
||||
total_packs: totalPacks,
|
||||
is_for_self: forSelf,
|
||||
recipient_name: forSelf ? null : effectiveRecipientName,
|
||||
tax_mode_hint: taxMode || null,
|
||||
invoice_uid_number: normalizedInvoiceUid || null,
|
||||
},
|
||||
pack_breakdown: breakdown,
|
||||
first_name: forSelf ? firstName : (effectiveRecipientName || firstName),
|
||||
@ -270,7 +280,9 @@ class AbonemmentService {
|
||||
snapshot.next_billing_at,
|
||||
{
|
||||
actorUserId: actorUser?.id || null,
|
||||
lang: actorUser?.lang || actorUser?.language || 'en'
|
||||
lang: actorUser?.lang || actorUser?.language || 'en',
|
||||
uidOverride: normalizedInvoiceUid || null,
|
||||
taxModeHint: taxMode || null,
|
||||
}
|
||||
);
|
||||
console.log('[SUBSCRIBE ORDER] Issued invoice:', {
|
||||
|
||||
@ -772,7 +772,7 @@ class InvoiceService {
|
||||
return this._loadInvoiceUserProfile(userId);
|
||||
}
|
||||
|
||||
async resolveTaxDecisionForSubscription({ buyerCountry, invoiceOwnerUserId, invoiceOwnerProfile = null }) {
|
||||
async resolveTaxDecisionForSubscription({ buyerCountry, invoiceOwnerUserId, invoiceOwnerProfile = null, uidOverride = null }) {
|
||||
const uow = new UnitOfWork();
|
||||
await uow.start();
|
||||
|
||||
@ -791,7 +791,7 @@ class InvoiceService {
|
||||
await uow.commit();
|
||||
|
||||
const companyProfile = invoiceOwnerProfile || await this._loadCompanyTaxProfile(invoiceOwnerUserId);
|
||||
const uidCandidate = companyProfile?.atu_number || companyProfile?.registration_number || '';
|
||||
const uidCandidate = uidOverride || companyProfile?.atu_number || companyProfile?.registration_number || '';
|
||||
const normalizedUid = this._normalizeUid(uidCandidate);
|
||||
const hasValidUid = this._isLikelyValidUid(normalizedUid);
|
||||
const countryCode = String(country?.country_code || '').toUpperCase();
|
||||
@ -822,7 +822,7 @@ class InvoiceService {
|
||||
}
|
||||
|
||||
// Issue invoice for a subscription period, with items from pack_breakdown
|
||||
async issueForAbonement(abonement, periodStart, periodEnd, { actorUserId, lang = 'en' } = {}) {
|
||||
async issueForAbonement(abonement, periodStart, periodEnd, { actorUserId, lang = 'en', uidOverride = null, taxModeHint = null } = {}) {
|
||||
console.log('[INVOICE ISSUE] Inputs:', {
|
||||
abonement_id: abonement?.id,
|
||||
abonement_user_id: abonement?.user_id,
|
||||
@ -854,9 +854,20 @@ class InvoiceService {
|
||||
buyerCountry: addr.country,
|
||||
invoiceOwnerUserId: userIdForInvoice,
|
||||
invoiceOwnerProfile: invoiceUserProfile,
|
||||
uidOverride,
|
||||
});
|
||||
const vat_rate = taxDecision?.vatRate ?? null;
|
||||
|
||||
logger.info('InvoiceService.issueForAbonement:tax_decision', {
|
||||
userId: userIdForInvoice,
|
||||
buyerCountry: addr.country || null,
|
||||
profileUserType: invoiceUserProfile?.user_type || null,
|
||||
providedUidOverride: uidOverride || null,
|
||||
taxModeHint: taxModeHint || null,
|
||||
taxMode: taxDecision?.isReverseCharge ? 'reverse_charge' : 'standard',
|
||||
resolvedUid: taxDecision?.uid || null,
|
||||
});
|
||||
|
||||
const items = await this._buildInvoiceItems({ abonement, vatRate: vat_rate, lang });
|
||||
|
||||
const context = {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user