Add Cc (Zusatzempfänger) recipient support for invoice emails
Lets an invoice carry an additional Cc recipient alongside the primary SendToEmail, sent via the ProcessWeb mailer API. Honors the Fuchs:Email:OverrideRecipient dev safety net: when the override is active, Cc is dropped entirely (only the single override inbox is ever reached), never leaked to it. - IComService.SendEmailAsync / ProcessWebComService: new optional `cc` parameter, included in the mailer payload only when non-empty. - FdsInvoiceData.RawInvoiceEmailCc + BuildInvoiceParams: reads `new.invoiceemailcc`, posts @SendToEmailCc. - IntranetController.Requests: reads SendToEmailCc from the loaded invoice row and passes it through on send/resend. - Fuchs_Database: SendToEmailCc column on fds__invoices, threaded through fds__createInvoice/fds__setInvoice/fds__getInvoice and the fds__tt__invoice_base/_core table types. - fis.req_txt_de.js: "Zusatzempfänger (CC)" field label. - Tests: ProcessWebComServiceTests (Cc included/omitted/dropped under override); SystemStatusServiceTests mocks updated for the new IComService.SendEmailAsync parameter. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -322,6 +322,46 @@ public class ProcessWebComServiceTests
|
|||||||
Assert.Equal("realcustomer@example.de", json["communication"]!["to"]!.ToString());
|
Assert.Equal("realcustomer@example.de", json["communication"]!["to"]!.ToString());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ── Cc recipient ("Zusatzempfänger") ─────────────────────────────────────────
|
||||||
|
[Fact]
|
||||||
|
public async Task SendEmailAsync_CcProvided_IsIncludedInPayload()
|
||||||
|
{
|
||||||
|
var handler = new StubHandler(HttpStatusCode.OK);
|
||||||
|
var svc = CreateService(handler);
|
||||||
|
|
||||||
|
await svc.SendEmailAsync("inv_cc1", "Subject", "<p>hi</p>", "kunde@example.de", "Kunde",
|
||||||
|
cc: "zusatz@example.de");
|
||||||
|
|
||||||
|
var json = JObject.Parse(handler.LastRequestBody!);
|
||||||
|
Assert.Equal("zusatz@example.de", json["communication"]!["cc"]!.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task SendEmailAsync_CcOmitted_IsNullInPayload()
|
||||||
|
{
|
||||||
|
var handler = new StubHandler(HttpStatusCode.OK);
|
||||||
|
var svc = CreateService(handler);
|
||||||
|
|
||||||
|
await svc.SendEmailAsync("inv_cc2", "Subject", "<p>hi</p>", "kunde@example.de", "Kunde");
|
||||||
|
|
||||||
|
var json = JObject.Parse(handler.LastRequestBody!);
|
||||||
|
Assert.Equal(JTokenType.Null, json["communication"]!["cc"]!.Type);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task SendEmailAsync_OverrideRecipientSet_DropsCcEntirely()
|
||||||
|
{
|
||||||
|
var handler = new StubHandler(HttpStatusCode.OK);
|
||||||
|
var svc = CreateService(handler, overrideRecipient: "dev-inbox@example.test");
|
||||||
|
|
||||||
|
await svc.SendEmailAsync("inv_cc3", "Subject", "<p>hi</p>", "realcustomer@example.de", "Kunde",
|
||||||
|
cc: "zusatz@example.de");
|
||||||
|
|
||||||
|
var json = JObject.Parse(handler.LastRequestBody!);
|
||||||
|
Assert.Equal("dev-inbox@example.test", json["communication"]!["to"]!.ToString());
|
||||||
|
Assert.Equal(JTokenType.Null, json["communication"]!["cc"]!.Type);
|
||||||
|
}
|
||||||
|
|
||||||
// ── Override enforcement across every real appsettings*.json environment ───
|
// ── Override enforcement across every real appsettings*.json environment ───
|
||||||
// Loads the ACTUAL Fuchs/appsettings*.json files the same way ASP.NET Core
|
// Loads the ACTUAL Fuchs/appsettings*.json files the same way ASP.NET Core
|
||||||
// layers them (base file + optional environment-specific overlay). These files
|
// layers them (base file + optional environment-specific overlay). These files
|
||||||
|
|||||||
@@ -404,7 +404,7 @@ public class SystemStatusServiceTests
|
|||||||
|
|
||||||
Assert.False(r.Sent);
|
Assert.False(r.Sent);
|
||||||
com.Verify(c => c.SendEmailAsync(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>(),
|
com.Verify(c => c.SendEmailAsync(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>(),
|
||||||
It.IsAny<string>(), It.IsAny<string>(), It.IsAny<Dictionary<string, byte[]>>()), Times.Never);
|
It.IsAny<string>(), It.IsAny<string>(), It.IsAny<Dictionary<string, byte[]>>(), It.IsAny<string?>()), Times.Never);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
@@ -413,9 +413,9 @@ public class SystemStatusServiceTests
|
|||||||
string? capturedHtml = null, capturedTo = null, capturedSubject = null;
|
string? capturedHtml = null, capturedTo = null, capturedSubject = null;
|
||||||
var com = new Mock<IComService>();
|
var com = new Mock<IComService>();
|
||||||
com.Setup(c => c.SendEmailAsync(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>(),
|
com.Setup(c => c.SendEmailAsync(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>(),
|
||||||
It.IsAny<string>(), It.IsAny<string>(), It.IsAny<Dictionary<string, byte[]>?>()))
|
It.IsAny<string>(), It.IsAny<string>(), It.IsAny<Dictionary<string, byte[]>?>(), It.IsAny<string?>()))
|
||||||
.Callback<string, string, string, string, string, Dictionary<string, byte[]>?>(
|
.Callback<string, string, string, string, string, Dictionary<string, byte[]>?, string?>(
|
||||||
(_, subj, html, to, _, _) => { capturedSubject = subj; capturedHtml = html; capturedTo = to; })
|
(_, subj, html, to, _, _, _) => { capturedSubject = subj; capturedHtml = html; capturedTo = to; })
|
||||||
.ReturnsAsync(true);
|
.ReturnsAsync(true);
|
||||||
var svc = Build(com: com);
|
var svc = Build(com: com);
|
||||||
|
|
||||||
@@ -436,7 +436,7 @@ public class SystemStatusServiceTests
|
|||||||
{
|
{
|
||||||
var com = new Mock<IComService>();
|
var com = new Mock<IComService>();
|
||||||
com.Setup(c => c.SendEmailAsync(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>(),
|
com.Setup(c => c.SendEmailAsync(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>(),
|
||||||
It.IsAny<string>(), It.IsAny<string>(), It.IsAny<Dictionary<string, byte[]>?>()))
|
It.IsAny<string>(), It.IsAny<string>(), It.IsAny<Dictionary<string, byte[]>?>(), It.IsAny<string?>()))
|
||||||
.ReturnsAsync(true);
|
.ReturnsAsync(true);
|
||||||
var svc = Build(com: com, email: new FuchsEmailSettings { OverrideRecipient = "safety@example.test" });
|
var svc = Build(com: com, email: new FuchsEmailSettings { OverrideRecipient = "safety@example.test" });
|
||||||
|
|
||||||
@@ -453,7 +453,7 @@ public class SystemStatusServiceTests
|
|||||||
{
|
{
|
||||||
var com = new Mock<IComService>();
|
var com = new Mock<IComService>();
|
||||||
com.Setup(c => c.SendEmailAsync(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>(),
|
com.Setup(c => c.SendEmailAsync(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>(),
|
||||||
It.IsAny<string>(), It.IsAny<string>(), It.IsAny<Dictionary<string, byte[]>?>()))
|
It.IsAny<string>(), It.IsAny<string>(), It.IsAny<Dictionary<string, byte[]>?>(), It.IsAny<string?>()))
|
||||||
.ReturnsAsync(false);
|
.ReturnsAsync(false);
|
||||||
var svc = Build(com: com);
|
var svc = Build(com: com);
|
||||||
|
|
||||||
|
|||||||
@@ -324,6 +324,7 @@ public partial class IntranetController
|
|||||||
Security: DbSec, options: SqlOpt(fn, id, code));
|
Security: DbSec, options: SqlOpt(fn, id, code));
|
||||||
frdic = dtset.Table("inv").FirstRow.toObjectDictionary();
|
frdic = dtset.Table("inv").FirstRow.toObjectDictionary();
|
||||||
string email = frdic.nz("SendToEmail", "");
|
string email = frdic.nz("SendToEmail", "");
|
||||||
|
string emailCc = frdic.nz("SendToEmailCc", "");
|
||||||
if (!string.IsNullOrEmpty(email) && filebyte.Length > 0)
|
if (!string.IsNullOrEmpty(email) && filebyte.Length > 0)
|
||||||
{
|
{
|
||||||
var inv = new Dictionary<string, byte[]> { [frdic.nz("DocumentName")] = filebyte };
|
var inv = new Dictionary<string, byte[]> { [frdic.nz("DocumentName")] = filebyte };
|
||||||
@@ -334,7 +335,7 @@ public partial class IntranetController
|
|||||||
invId, email.Trim(), UserAccountID);
|
invId, email.Trim(), UserAccountID);
|
||||||
bool sent = await _comService.SendEmailAsync(
|
bool sent = await _comService.SendEmailAsync(
|
||||||
$"inv_{invId}", $"Sanit\u00e4rFuchs - {frdic.nz("DocumentName")}",
|
$"inv_{invId}", $"Sanit\u00e4rFuchs - {frdic.nz("DocumentName")}",
|
||||||
body, email.Trim(), "", inv);
|
body, email.Trim(), "", inv, string.IsNullOrEmpty(emailCc) ? null : emailCc.Trim());
|
||||||
if (sent)
|
if (sent)
|
||||||
{
|
{
|
||||||
await _events.InvoiceSentToCustomerAsync(fdInv, email.Trim(), UserAccountID);
|
await _events.InvoiceSentToCustomerAsync(fdInv, email.Trim(), UserAccountID);
|
||||||
@@ -425,6 +426,7 @@ public partial class IntranetController
|
|||||||
var fdInv = await _invoices.LoadInvoiceAsync(invId, UserAccountID, DbSec);
|
var fdInv = await _invoices.LoadInvoiceAsync(invId, UserAccountID, DbSec);
|
||||||
byte[] filebyte = await _invoices.RenderInvoicePdfBytesAsync(fdInv, fdInv.IsDraft);
|
byte[] filebyte = await _invoices.RenderInvoicePdfBytesAsync(fdInv, fdInv.IsDraft);
|
||||||
string email = frdic.nz("SendToEmail", "");
|
string email = frdic.nz("SendToEmail", "");
|
||||||
|
string emailCc = frdic.nz("SendToEmailCc", "");
|
||||||
if (!string.IsNullOrEmpty(email) && filebyte.Length > 0)
|
if (!string.IsNullOrEmpty(email) && filebyte.Length > 0)
|
||||||
{
|
{
|
||||||
double bal = Convert.ToDouble(frdic.no("InvoiceBalance", 0));
|
double bal = Convert.ToDouble(frdic.no("InvoiceBalance", 0));
|
||||||
@@ -432,7 +434,8 @@ public partial class IntranetController
|
|||||||
bool sent = await _comService.SendEmailAsync(
|
bool sent = await _comService.SendEmailAsync(
|
||||||
$"inv_{invId}", $"Sanit\u00e4rFuchs - {frdic.nz("DocumentName")}",
|
$"inv_{invId}", $"Sanit\u00e4rFuchs - {frdic.nz("DocumentName")}",
|
||||||
BuildInvoiceBody(bal, terms), email.Trim(), "",
|
BuildInvoiceBody(bal, terms), email.Trim(), "",
|
||||||
new Dictionary<string, byte[]> { [frdic.nz("DocumentName")] = filebyte });
|
new Dictionary<string, byte[]> { [frdic.nz("DocumentName")] = filebyte },
|
||||||
|
string.IsNullOrEmpty(emailCc) ? null : emailCc.Trim());
|
||||||
if (sent)
|
if (sent)
|
||||||
await _events.InvoiceSentToCustomerAsync(fdInv, email.Trim(), UserAccountID, resent: true);
|
await _events.InvoiceSentToCustomerAsync(fdInv, email.Trim(), UserAccountID, resent: true);
|
||||||
else
|
else
|
||||||
|
|||||||
@@ -15,9 +15,10 @@ public interface IComService
|
|||||||
/// <param name="email">Recipient email address.</param>
|
/// <param name="email">Recipient email address.</param>
|
||||||
/// <param name="name">Recipient display name.</param>
|
/// <param name="name">Recipient display name.</param>
|
||||||
/// <param name="attachments">Optional file attachments (filename → content).</param>
|
/// <param name="attachments">Optional file attachments (filename → content).</param>
|
||||||
|
/// <param name="cc">Optional Cc recipient (e.g. a customer's "Zusatzempfänger").</param>
|
||||||
/// <returns><c>true</c> when the email was accepted successfully.</returns>
|
/// <returns><c>true</c> when the email was accepted successfully.</returns>
|
||||||
Task<bool> SendEmailAsync(string reference, string subject, string html,
|
Task<bool> SendEmailAsync(string reference, string subject, string html,
|
||||||
string email, string name, Dictionary<string, byte[]>? attachments = null);
|
string email, string name, Dictionary<string, byte[]>? attachments = null, string? cc = null);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Sends an SMS message.
|
/// Sends an SMS message.
|
||||||
|
|||||||
@@ -135,13 +135,13 @@ public class InvoiceService : IInvoiceService
|
|||||||
var sqlParts = new List<string> { "DECLARE @Id varchar(10);" };
|
var sqlParts = new List<string> { "DECLARE @Id varchar(10);" };
|
||||||
if (!change)
|
if (!change)
|
||||||
{
|
{
|
||||||
sqlParts.Add("EXECUTE [dbo].[fds__createInvoice] @InvoiceType, @InvoiceTitle, @InvoiceBalance, @InvoiceBalance_net, @InvoiceVAT_net1, @InvoiceVAT_1, @PaymentTerm, @CustomerId, @SendToAddress, @SendToEmail, @ProvisionPeriod, @CustomValues, @authuser, @Id OUTPUT, @SendToAddressJson;");
|
sqlParts.Add("EXECUTE [dbo].[fds__createInvoice] @InvoiceType, @InvoiceTitle, @InvoiceBalance, @InvoiceBalance_net, @InvoiceVAT_net1, @InvoiceVAT_1, @PaymentTerm, @CustomerId, @SendToAddress, @SendToEmail, @SendToEmailCc, @ProvisionPeriod, @CustomValues, @authuser, @Id OUTPUT, @SendToAddressJson;");
|
||||||
sqlParts.Add("EXECUTE [dbo].[fds__createInvoice_Details] @Id, @InvoiceService_net, @InvoiceService_VAT, @InvoiceOptions, @authuser;");
|
sqlParts.Add("EXECUTE [dbo].[fds__createInvoice_Details] @Id, @InvoiceService_net, @InvoiceService_VAT, @InvoiceOptions, @authuser;");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
pl.Add(SQL_VarChar("@InvId", invId));
|
pl.Add(SQL_VarChar("@InvId", invId));
|
||||||
sqlParts.Add("EXECUTE [dbo].[fds__setInvoice] @InvId, @InvoiceType, @InvoiceTitle, @InvoiceBalance, @InvoiceBalance_net, @InvoiceVAT_net1, @InvoiceVAT_1, @PaymentTerm, @CustomerId, @SendToAddress, @SendToEmail, @ProvisionPeriod, @CustomValues, @authuser, @Id OUTPUT, @SendToAddressJson;");
|
sqlParts.Add("EXECUTE [dbo].[fds__setInvoice] @InvId, @InvoiceType, @InvoiceTitle, @InvoiceBalance, @InvoiceBalance_net, @InvoiceVAT_net1, @InvoiceVAT_1, @PaymentTerm, @CustomerId, @SendToAddress, @SendToEmail, @SendToEmailCc, @ProvisionPeriod, @CustomValues, @authuser, @Id OUTPUT, @SendToAddressJson;");
|
||||||
sqlParts.Add("EXECUTE [dbo].[fds__createInvoice_Details] @Id, @InvoiceService_net, @InvoiceService_VAT, @InvoiceOptions, @authuser;");
|
sqlParts.Add("EXECUTE [dbo].[fds__createInvoice_Details] @Id, @InvoiceService_net, @InvoiceService_VAT, @InvoiceOptions, @authuser;");
|
||||||
}
|
}
|
||||||
if (invoice.RawProvisionLocation.Length > 0)
|
if (invoice.RawProvisionLocation.Length > 0)
|
||||||
|
|||||||
@@ -46,10 +46,11 @@ public class ProcessWebComService : IComService
|
|||||||
}
|
}
|
||||||
|
|
||||||
public async Task<bool> SendEmailAsync(string reference, string subject, string html,
|
public async Task<bool> SendEmailAsync(string reference, string subject, string html,
|
||||||
string email, string name, Dictionary<string, byte[]>? attachments = null)
|
string email, string name, Dictionary<string, byte[]>? attachments = null, string? cc = null)
|
||||||
{
|
{
|
||||||
using var act = FuchsTelemetry.StartActivity("email.send");
|
using var act = FuchsTelemetry.StartActivity("email.send");
|
||||||
act?.SetTag("fuchs.email.ref", reference);
|
act?.SetTag("fuchs.email.ref", reference);
|
||||||
|
cc = string.IsNullOrWhiteSpace(cc) ? null : cc.Trim();
|
||||||
|
|
||||||
string overrideRecipient = _emailSettings.OverrideRecipient ?? "";
|
string overrideRecipient = _emailSettings.OverrideRecipient ?? "";
|
||||||
if (!string.IsNullOrWhiteSpace(overrideRecipient))
|
if (!string.IsNullOrWhiteSpace(overrideRecipient))
|
||||||
@@ -58,12 +59,13 @@ public class ProcessWebComService : IComService
|
|||||||
// redirect every outbound email to a single controlled inbox, so a locally
|
// redirect every outbound email to a single controlled inbox, so a locally
|
||||||
// enabled mailer can never reach a real tenant-owner or end-customer.
|
// enabled mailer can never reach a real tenant-owner or end-customer.
|
||||||
_logger.LogWarning(
|
_logger.LogWarning(
|
||||||
"SendEmailAsync: recipient override active for ref {Reference} – redirecting from '{OriginalEmail}' to '{OverrideRecipient}'",
|
"SendEmailAsync: recipient override active for ref {Reference} – redirecting from '{OriginalEmail}' (cc='{OriginalCc}') to '{OverrideRecipient}'",
|
||||||
reference, email, overrideRecipient);
|
reference, email, cc ?? "", overrideRecipient);
|
||||||
act?.SetTag("fuchs.email.overridden", true);
|
act?.SetTag("fuchs.email.overridden", true);
|
||||||
act?.SetTag("fuchs.email.original_recipient", email);
|
act?.SetTag("fuchs.email.original_recipient", email);
|
||||||
subject = $"[DEV \u2192 {email}] {subject}";
|
subject = $"[DEV \u2192 {email}] {subject}";
|
||||||
email = overrideRecipient;
|
email = overrideRecipient;
|
||||||
|
cc = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!IsValidEmail(email))
|
if (!IsValidEmail(email))
|
||||||
@@ -111,13 +113,14 @@ public class ProcessWebComService : IComService
|
|||||||
var communication = new
|
var communication = new
|
||||||
{
|
{
|
||||||
to = email,
|
to = email,
|
||||||
|
cc,
|
||||||
subject,
|
subject,
|
||||||
body,
|
body,
|
||||||
attachments = attachmentPayload
|
attachments = attachmentPayload
|
||||||
};
|
};
|
||||||
|
|
||||||
_logger.LogDebug("SendEmailAsync ref={Reference} to={Email} attachments={Count}",
|
_logger.LogDebug("SendEmailAsync ref={Reference} to={Email} cc={Cc} attachments={Count}",
|
||||||
reference, email, attachmentPayload.Length);
|
reference, email, cc ?? "", attachmentPayload.Length);
|
||||||
|
|
||||||
var (ok, status, responseBody) = await PostToApiAsync(reference, "e", communication);
|
var (ok, status, responseBody) = await PostToApiAsync(reference, "e", communication);
|
||||||
if (ok)
|
if (ok)
|
||||||
|
|||||||
@@ -133,6 +133,8 @@ public class FdsInvoiceData
|
|||||||
// -- Raw form properties (used by parameter mapping) -----------------------
|
// -- Raw form properties (used by parameter mapping) -----------------------
|
||||||
internal string RawInvoiceAddress => NewValues?.nz("invoiceaddress") ?? "";
|
internal string RawInvoiceAddress => NewValues?.nz("invoiceaddress") ?? "";
|
||||||
internal string RawInvoiceEmail => NewValues?.nz("invoiceemail").Trim() ?? "";
|
internal string RawInvoiceEmail => NewValues?.nz("invoiceemail").Trim() ?? "";
|
||||||
|
/// <summary>Additional recipient ("Zusatzempfänger") sent as Cc alongside the primary invoice email.</summary>
|
||||||
|
internal string RawInvoiceEmailCc => NewValues?.nz("invoiceemailcc").Trim() ?? "";
|
||||||
internal string RawCustomValues => NewValues?.nz("CustomValues").Trim() ?? "";
|
internal string RawCustomValues => NewValues?.nz("CustomValues").Trim() ?? "";
|
||||||
internal string RawProvisionPeriod => NewValues?.nz("provisionperiod") ?? "";
|
internal string RawProvisionPeriod => NewValues?.nz("provisionperiod") ?? "";
|
||||||
internal string[] RawProvisionLocation =>
|
internal string[] RawProvisionLocation =>
|
||||||
@@ -179,6 +181,7 @@ public class FdsInvoiceData
|
|||||||
SQL_BigInt("@CustomerId", Admin?.nz("customerid") ?? ""),
|
SQL_BigInt("@CustomerId", Admin?.nz("customerid") ?? ""),
|
||||||
SQL_VarChar("@SendToAddress", RawInvoiceAddress),
|
SQL_VarChar("@SendToAddress", RawInvoiceAddress),
|
||||||
SQL_NVarChar("@SendToEmail", RawInvoiceEmail),
|
SQL_NVarChar("@SendToEmail", RawInvoiceEmail),
|
||||||
|
SQL_NVarChar("@SendToEmailCc", RawInvoiceEmailCc, dbNull_IfEmpty: true),
|
||||||
SQL_NVarChar("@ProvisionPeriod", RawProvisionPeriod, dbNull_IfEmpty: true),
|
SQL_NVarChar("@ProvisionPeriod", RawProvisionPeriod, dbNull_IfEmpty: true),
|
||||||
SQL_NVarChar("@CustomValues", RawCustomValues, dbNull_IfEmpty: true),
|
SQL_NVarChar("@CustomValues", RawCustomValues, dbNull_IfEmpty: true),
|
||||||
SQL_NVarChar("@SendToAddressJson", SendToAddressJsonForPersist(), dbNull_IfEmpty: true),
|
SQL_NVarChar("@SendToAddressJson", SendToAddressJsonForPersist(), dbNull_IfEmpty: true),
|
||||||
|
|||||||
@@ -65,6 +65,7 @@
|
|||||||
invoiceaddress: 'Adresse'
|
invoiceaddress: 'Adresse'
|
||||||
, loc: 'Leistungsort / Lieferadresse'
|
, loc: 'Leistungsort / Lieferadresse'
|
||||||
, invoiceemail: 'Email'
|
, invoiceemail: 'Email'
|
||||||
|
, invoiceemailcc: 'Zusatzempfänger (CC)'
|
||||||
|
|
||||||
}
|
}
|
||||||
}, $rcol = {
|
}, $rcol = {
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ CREATE PROCEDURE [dbo].[fds__createInvoice]
|
|||||||
@CustomerId bigint,
|
@CustomerId bigint,
|
||||||
@SendToAddress nvarchar(1000),
|
@SendToAddress nvarchar(1000),
|
||||||
@SendToEmail nvarchar(255),
|
@SendToEmail nvarchar(255),
|
||||||
|
@SendToEmailCc nvarchar(255) = NULL,
|
||||||
@ProvisionPeriod varchar(50),
|
@ProvisionPeriod varchar(50),
|
||||||
@CustomValues nvarchar(max),
|
@CustomValues nvarchar(max),
|
||||||
@authuser varchar(25),
|
@authuser varchar(25),
|
||||||
@@ -56,6 +57,7 @@ BEGIN
|
|||||||
[CustomerId] [bigint] NULL,
|
[CustomerId] [bigint] NULL,
|
||||||
[SendToAddress] [nvarchar](1000) NULL,
|
[SendToAddress] [nvarchar](1000) NULL,
|
||||||
[SendToEmail] [nvarchar](255) NULL,
|
[SendToEmail] [nvarchar](255) NULL,
|
||||||
|
[SendToEmailCc] [nvarchar](255) NULL,
|
||||||
[ProvisionPeriod] [varchar](50) NULL,
|
[ProvisionPeriod] [varchar](50) NULL,
|
||||||
[ProvisionLocation] [nvarchar](1000) NULL,
|
[ProvisionLocation] [nvarchar](1000) NULL,
|
||||||
[PaymentStatus] [char](1) NULL,
|
[PaymentStatus] [char](1) NULL,
|
||||||
@@ -100,6 +102,7 @@ BEGIN
|
|||||||
,[CustomerId]
|
,[CustomerId]
|
||||||
,[SendToAddress]
|
,[SendToAddress]
|
||||||
,[SendToEmail]
|
,[SendToEmail]
|
||||||
|
,[SendToEmailCc]
|
||||||
,[ProvisionPeriod]
|
,[ProvisionPeriod]
|
||||||
,[ProvisionLocation]
|
,[ProvisionLocation]
|
||||||
,[PaymentStatus]
|
,[PaymentStatus]
|
||||||
@@ -140,6 +143,7 @@ BEGIN
|
|||||||
,@CustomerId
|
,@CustomerId
|
||||||
,@SendToAddress
|
,@SendToAddress
|
||||||
,@SendToEmail
|
,@SendToEmail
|
||||||
|
,@SendToEmailCc
|
||||||
,@ProvisionPeriod
|
,@ProvisionPeriod
|
||||||
,NULL --[ProvisionLocation]
|
,NULL --[ProvisionLocation]
|
||||||
,NULL --[PaymentStatus]
|
,NULL --[PaymentStatus]
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ BEGIN
|
|||||||
,[CustomerId]
|
,[CustomerId]
|
||||||
,[SendToAddress]
|
,[SendToAddress]
|
||||||
,[SendToEmail]
|
,[SendToEmail]
|
||||||
|
,[SendToEmailCc]
|
||||||
,[ProvisionPeriod]
|
,[ProvisionPeriod]
|
||||||
,[ProvisionLocation]
|
,[ProvisionLocation]
|
||||||
,[PaymentStatus]
|
,[PaymentStatus]
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ CREATE PROCEDURE [dbo].[fds__setInvoice]
|
|||||||
@CustomerId bigint,
|
@CustomerId bigint,
|
||||||
@SendToAddress nvarchar(1000),
|
@SendToAddress nvarchar(1000),
|
||||||
@SendToEmail nvarchar(255),
|
@SendToEmail nvarchar(255),
|
||||||
|
@SendToEmailCc nvarchar(255) = NULL,
|
||||||
@ProvisionPeriod varchar(50),
|
@ProvisionPeriod varchar(50),
|
||||||
@CustomValues nvarchar(max),
|
@CustomValues nvarchar(max),
|
||||||
@authuser varchar(25),
|
@authuser varchar(25),
|
||||||
@@ -57,6 +58,7 @@ BEGIN
|
|||||||
[CustomerId] [bigint] NULL,
|
[CustomerId] [bigint] NULL,
|
||||||
[SendToAddress] [nvarchar](1000) NULL,
|
[SendToAddress] [nvarchar](1000) NULL,
|
||||||
[SendToEmail] [nvarchar](255) NULL,
|
[SendToEmail] [nvarchar](255) NULL,
|
||||||
|
[SendToEmailCc] [nvarchar](255) NULL,
|
||||||
[ProvisionPeriod] [varchar](50) NULL,
|
[ProvisionPeriod] [varchar](50) NULL,
|
||||||
[ProvisionLocation] [nvarchar](1000) NULL,
|
[ProvisionLocation] [nvarchar](1000) NULL,
|
||||||
[PaymentStatus] [char](1) NULL,
|
[PaymentStatus] [char](1) NULL,
|
||||||
@@ -98,6 +100,7 @@ BEGIN
|
|||||||
,@CustomerId
|
,@CustomerId
|
||||||
,@SendToAddress
|
,@SendToAddress
|
||||||
,@SendToEmail
|
,@SendToEmail
|
||||||
|
,@SendToEmailCc
|
||||||
,@ProvisionPeriod
|
,@ProvisionPeriod
|
||||||
,NULL --[ProvisionLocation]
|
,NULL --[ProvisionLocation]
|
||||||
,NULL --[PaymentStatus]
|
,NULL --[PaymentStatus]
|
||||||
@@ -130,6 +133,7 @@ BEGIN
|
|||||||
,[CustomerId]
|
,[CustomerId]
|
||||||
,[SendToAddress]
|
,[SendToAddress]
|
||||||
,[SendToEmail]
|
,[SendToEmail]
|
||||||
|
,[SendToEmailCc]
|
||||||
,[ProvisionPeriod]
|
,[ProvisionPeriod]
|
||||||
,[ProvisionLocation]
|
,[ProvisionLocation]
|
||||||
,[PaymentStatus]
|
,[PaymentStatus]
|
||||||
@@ -164,6 +168,7 @@ BEGIN
|
|||||||
,[CustomerId] = SOURCE.[CustomerId]
|
,[CustomerId] = SOURCE.[CustomerId]
|
||||||
,[SendToAddress] = SOURCE.[SendToAddress]
|
,[SendToAddress] = SOURCE.[SendToAddress]
|
||||||
,[SendToEmail] = SOURCE.[SendToEmail]
|
,[SendToEmail] = SOURCE.[SendToEmail]
|
||||||
|
,[SendToEmailCc] = SOURCE.[SendToEmailCc]
|
||||||
,[ProvisionPeriod] = SOURCE.[ProvisionPeriod]
|
,[ProvisionPeriod] = SOURCE.[ProvisionPeriod]
|
||||||
,[ProvisionLocation] = SOURCE.[ProvisionLocation]
|
,[ProvisionLocation] = SOURCE.[ProvisionLocation]
|
||||||
,[CustomValues] = SOURCE.[CustomValues]
|
,[CustomValues] = SOURCE.[CustomValues]
|
||||||
|
|||||||
@@ -16,6 +16,7 @@
|
|||||||
[CustomerId] BIGINT NULL,
|
[CustomerId] BIGINT NULL,
|
||||||
[SendToAddress] NVARCHAR (1000) NULL,
|
[SendToAddress] NVARCHAR (1000) NULL,
|
||||||
[SendToEmail] NVARCHAR (255) NULL,
|
[SendToEmail] NVARCHAR (255) NULL,
|
||||||
|
[SendToEmailCc] NVARCHAR (255) NULL,
|
||||||
[ProvisionPeriod] VARCHAR (50) NULL,
|
[ProvisionPeriod] VARCHAR (50) NULL,
|
||||||
[ProvisionLocation] NVARCHAR (1000) NULL,
|
[ProvisionLocation] NVARCHAR (1000) NULL,
|
||||||
[PaymentStatus] CHAR (1) NULL,
|
[PaymentStatus] CHAR (1) NULL,
|
||||||
|
|||||||
@@ -16,6 +16,7 @@
|
|||||||
[CustomerId] BIGINT NULL,
|
[CustomerId] BIGINT NULL,
|
||||||
[SendToAddress] NVARCHAR (1000) NULL,
|
[SendToAddress] NVARCHAR (1000) NULL,
|
||||||
[SendToEmail] NVARCHAR (255) NULL,
|
[SendToEmail] NVARCHAR (255) NULL,
|
||||||
|
[SendToEmailCc] NVARCHAR (255) NULL,
|
||||||
[ProvisionPeriod] VARCHAR (50) NULL,
|
[ProvisionPeriod] VARCHAR (50) NULL,
|
||||||
[ProvisionLocation] NVARCHAR (1000) NULL,
|
[ProvisionLocation] NVARCHAR (1000) NULL,
|
||||||
[PaymentStatus] CHAR (1) NULL,
|
[PaymentStatus] CHAR (1) NULL,
|
||||||
|
|||||||
@@ -16,6 +16,7 @@
|
|||||||
[CustomerId] BIGINT NULL,
|
[CustomerId] BIGINT NULL,
|
||||||
[SendToAddress] NVARCHAR (1000) NULL,
|
[SendToAddress] NVARCHAR (1000) NULL,
|
||||||
[SendToEmail] NVARCHAR (255) NULL,
|
[SendToEmail] NVARCHAR (255) NULL,
|
||||||
|
[SendToEmailCc] NVARCHAR (255) NULL,
|
||||||
[ProvisionPeriod] VARCHAR (50) NULL,
|
[ProvisionPeriod] VARCHAR (50) NULL,
|
||||||
[ProvisionLocation] NVARCHAR (1000) NULL,
|
[ProvisionLocation] NVARCHAR (1000) NULL,
|
||||||
[PaymentStatus] CHAR (1) NULL,
|
[PaymentStatus] CHAR (1) NULL,
|
||||||
|
|||||||
Reference in New Issue
Block a user