QuellCode/CentronERP war nur als Gitlink (Submodul-Referenz auf 79c1142) getrackt, ohne .gitmodules und ohne erreichbares Remote. Der Untersuchungsgegenstand der Versuchsreihe war damit nicht reproduzierbar gesichert: Ein Klon haette ein leeres Verzeichnis erhalten, und die Belege der 3.287 Anforderungen waeren nicht ueberpruefbar gewesen. Umstellung: - Historie nach c:\DEV\CentronERP_git_snapshot_79c1142 ausgelagert (vollstaendig lesbar, enthaelt 79c1142 und Vorgaenger 89ccfd6) - Gitlink aus dem Index entfernt - Dateiinhalt aufgenommen: 24.557 Dateien, rund 333 MB Die verschachtelte .gitignore der Codebasis gilt weiter, Build-Artefakte bleiben ausgeschlossen. Details in Versuche/Versuch_01/_Codebasis-Nachweis.md
247 lines
10 KiB
C#
247 lines
10 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using Centron.BusinessLogic;
|
|
using Centron.BusinessLogic.Sales.Receipts.DataAndResults;
|
|
using Centron.BusinessLogic.WebServices.Sales.Receipts;
|
|
using Centron.Core.Extensions;
|
|
using Centron.Data.WebServices.Sales.Receipts.Invoices;
|
|
using Centron.Interfaces;
|
|
using Centron.Interfaces.Administration.Environment;
|
|
using Centron.Interfaces.BL;
|
|
using Centron.Interfaces.Sales.Receipts;
|
|
using Centron.Tests.EndToEnd.Infrastructure;
|
|
using CentronSoftware.Centron.WebServices.Entities.Sales.Receipts;
|
|
using Xunit.Abstractions;
|
|
|
|
namespace Centron.Tests.EndToEnd.Tests.ReceiptProvisionTiers;
|
|
|
|
public class ReceiptProvisionEmployeeLevelTests : EndToEndTest
|
|
{
|
|
public ReceiptProvisionEmployeeLevelTests(ITestOutputHelper testOutputHelper)
|
|
: base(testOutputHelper)
|
|
{
|
|
}
|
|
|
|
private const int EmployeeI3D = 10;
|
|
private const int Invoice1I3D = 4408;
|
|
private const int Invoice2I3D = 5414;
|
|
|
|
public override void Execute()
|
|
{
|
|
this.PrepareDatabase();
|
|
|
|
this.SaveLevels(step: 1);
|
|
this.LoadLevels(step: 2);
|
|
|
|
this.SingleInvoice(step: 3);
|
|
this.MultiInvoice(step: 4);
|
|
this.MoveProvisionToOtherEmployee(step: 5);
|
|
this.ChangeInvoiceDate(step: 6);
|
|
|
|
// Ticket 163976: tiers without FromPrice=0 used to yield [null] in GetLevels and NRE in PrepareLevelsOverwriteLowerLevels
|
|
this.LevelsWithoutZeroTier_BelowFirstTier(step: 7);
|
|
|
|
// Ticket 163972: bonus of just-reached tier was dropped when invoice sum exactly equaled tier FromPrice
|
|
this.InvoiceExactlyOnTierBoundary(step: 8);
|
|
}
|
|
|
|
private void PrepareDatabase()
|
|
{
|
|
// Fix broken tables
|
|
this.Sql("ALTER TABLE RechKopf DROP COLUMN LcmStatus");
|
|
this.Sql("ALTER TABLE GutKopf DROP COLUMN LcmStatus");
|
|
|
|
// Create a dummy provision-schema to enable provision-schemas instead of old ones
|
|
this.WithSession(s => s.GetBL<ReceiptProvisionSchemaWebServiceBL>().SaveProvisionSchema(new ReceiptProvisionSchemaDTO
|
|
{
|
|
Name = "Dummy",
|
|
}, this.GetLoggedInUser()));
|
|
|
|
// Prepare some invoices for later
|
|
this.Sql($"DELETE FROM RechPos WHERE RechKopfI3D = {Invoice1I3D} AND ISNULL(ArtikelI3D, 0) <> 117");
|
|
}
|
|
|
|
private void SaveLevels(int step)
|
|
{
|
|
using var session = new BLSession();
|
|
|
|
var tiers = new List<ReceiptProvisionEmployeeLevelDTO>
|
|
{
|
|
new() { FromPrice = 0, ProvisionPercentage = 2, OverwriteLowerLevels = false, Bonus = null },
|
|
new() { FromPrice = 500, ProvisionPercentage = 3, OverwriteLowerLevels = true, Bonus = 100 },
|
|
new() { FromPrice = 1000, ProvisionPercentage = 4, OverwriteLowerLevels = false, Bonus = 200 },
|
|
new() { FromPrice = 2000, ProvisionPercentage = 5, OverwriteLowerLevels = false, Bonus = 300 },
|
|
};
|
|
|
|
session.GetBL<ReceiptProvisionEmployeeLevelWebServiceBL>().SaveEmployeeLevels(EmployeeI3D, tiers);
|
|
this.Verifier.VerifyTable($"{step}_Levels_Table", "ReceiptProvisionEmployeeLevels");
|
|
}
|
|
|
|
private void LoadLevels(int step)
|
|
{
|
|
using var session = new BLSession();
|
|
|
|
var tiers = session.GetBL<ReceiptProvisionEmployeeLevelWebServiceBL>().GetLevels(new() { EmployeeI3Ds = new List<int> { EmployeeI3D } });
|
|
this.Verifier.Verify($"{step}_Levels", tiers);
|
|
}
|
|
|
|
private void SingleInvoice(int step)
|
|
{
|
|
this.UpdateInvoice(Invoice1I3D, 400);
|
|
this.Verifier.VerifyTable($"{step}_Price_400", "ReceiptProvisionItems");
|
|
|
|
this.UpdateInvoice(Invoice1I3D, 800);
|
|
this.Verifier.VerifyTable($"{step}_Price_800", "ReceiptProvisionItems");
|
|
|
|
this.UpdateInvoice(Invoice1I3D, 3000);
|
|
this.Verifier.VerifyTable($"{step}_Price_3000", "ReceiptProvisionItems");
|
|
}
|
|
|
|
private void MultiInvoice(int step)
|
|
{
|
|
// With the of Invoice-2 200 € we reach the 500 € level
|
|
// That level overwrites the lower tiers, so we should should also get 3 % for the 400 € invoice
|
|
this.UpdateInvoice(Invoice1I3D, 400);
|
|
this.UpdateInvoice(Invoice2I3D, 200);
|
|
this.Verifier.VerifyTable($"{step}.1_Price_600", "ReceiptProvisionItems");
|
|
|
|
// Now reduce it back down to 450 €, should go back to 2 % and no bonus
|
|
this.UpdateInvoice(Invoice2I3D, 50);
|
|
this.Verifier.VerifyTable($"{step}.2_Price_450", "ReceiptProvisionItems");
|
|
}
|
|
|
|
private void MoveProvisionToOtherEmployee(int step)
|
|
{
|
|
// Cleanup first
|
|
this.RemoveProvision(Invoice1I3D);
|
|
this.RemoveProvision(Invoice2I3D);
|
|
this.Verifier.VerifyTable($"{step}.1_Before", "ReceiptProvisionItems");
|
|
|
|
// Lets start with 1000 € for the first employee
|
|
this.UpdateInvoice(Invoice1I3D, 1000);
|
|
this.Verifier.VerifyTable($"{step}.2_OldEmployee", "ReceiptProvisionItems");
|
|
|
|
// Now we move the provision to another employee
|
|
this.UpdateInvoiceAndChangeEmployee(Invoice1I3D, 1000, alternativeEmployeeI3D: 20);
|
|
this.Verifier.VerifyTable($"{step}.3_NewEmployee", "ReceiptProvisionItems");
|
|
}
|
|
|
|
private void ChangeInvoiceDate(int step)
|
|
{
|
|
// Prepare a test case, both invoices together in one month go over 500 €
|
|
this.UpdateInvoice(Invoice1I3D, 400);
|
|
this.UpdateInvoice(Invoice2I3D, 200);
|
|
|
|
// Now we change the date of the first invoice to a new month
|
|
this.UpdateInvoiceAndChangeDate(Invoice1I3D, new DateTime(2022, 1, 1));
|
|
|
|
// The provision should be recalculated for both invoices
|
|
this.Verifier.VerifyTable($"{step}.1_NewMonth", "ReceiptProvisionItems");
|
|
}
|
|
|
|
private void LevelsWithoutZeroTier_BelowFirstTier(int step)
|
|
{
|
|
using var session = new BLSession();
|
|
|
|
var tiers = new List<ReceiptProvisionEmployeeLevelDTO>
|
|
{
|
|
new() { FromPrice = 500, ProvisionPercentage = 3, OverwriteLowerLevels = false, Bonus = null },
|
|
new() { FromPrice = 1000, ProvisionPercentage = 4, OverwriteLowerLevels = false, Bonus = null },
|
|
};
|
|
|
|
session.GetBL<ReceiptProvisionEmployeeLevelWebServiceBL>().SaveEmployeeLevels(EmployeeI3D, tiers);
|
|
this.Verifier.VerifyTable($"{step}_Levels_Table_NoZero", "ReceiptProvisionEmployeeLevels", $"EmployeeI3D = {EmployeeI3D}");
|
|
|
|
this.UpdateInvoice(Invoice1I3D, 400);
|
|
this.Verifier.VerifyTable($"{step}_Price_400_BelowFirstTier", "ReceiptProvisionItems", $"ReceiptI3D = {Invoice1I3D}");
|
|
}
|
|
|
|
private void InvoiceExactlyOnTierBoundary(int step)
|
|
{
|
|
// Stefan's repro from ticket 163972 (TestDB centronwes, RE 42321): tiers 1000/5000/10000 € with bonuses 100/500/1000 €.
|
|
// Invoice exactly on a tier threshold (sum == FromPrice) used to drop that tier's bonus because of strict < check.
|
|
using var session = new BLSession();
|
|
|
|
var tiers = new List<ReceiptProvisionEmployeeLevelDTO>
|
|
{
|
|
new() { FromPrice = 1000, ProvisionPercentage = 5, OverwriteLowerLevels = false, Bonus = 100 },
|
|
new() { FromPrice = 5000, ProvisionPercentage = 7, OverwriteLowerLevels = false, Bonus = 500 },
|
|
new() { FromPrice = 10000, ProvisionPercentage = 2, OverwriteLowerLevels = false, Bonus = 1000 },
|
|
};
|
|
|
|
session.GetBL<ReceiptProvisionEmployeeLevelWebServiceBL>().SaveEmployeeLevels(EmployeeI3D, tiers);
|
|
this.Verifier.VerifyTable($"{step}_Levels_Stefan", "ReceiptProvisionEmployeeLevels", $"EmployeeI3D = {EmployeeI3D}");
|
|
|
|
// Invoice exactly on tier 2 boundary (5000): expected = 5%*1000 + 100 + 7%*4000 + 500 = 930
|
|
this.UpdateInvoice(Invoice1I3D, 5000);
|
|
this.Verifier.VerifyTable($"{step}.1_Price_5000_OnTier2", "ReceiptProvisionItems", $"ReceiptI3D = {Invoice1I3D}");
|
|
|
|
// Invoice exactly on tier 1 boundary (1000): expected = 5%*1000 + 100 = 150 (count==1 short-circuit case)
|
|
this.UpdateInvoice(Invoice1I3D, 1000);
|
|
this.Verifier.VerifyTable($"{step}.2_Price_1000_OnTier1", "ReceiptProvisionItems", $"ReceiptI3D = {Invoice1I3D}");
|
|
}
|
|
|
|
private void RemoveProvision(int invoiceI3D)
|
|
{
|
|
this.UpdateInvoice(invoiceI3D, 0, invoice =>
|
|
{
|
|
invoice.Provision = [];
|
|
});
|
|
}
|
|
private void UpdateInvoiceAndChangeDate(int invoiceI3D, DateTime date)
|
|
{
|
|
this.UpdateInvoice(invoiceI3D, 0, invoice =>
|
|
{
|
|
invoice.Date = date;
|
|
});
|
|
}
|
|
private void UpdateInvoiceAndChangeEmployee(int invoiceI3D, decimal price, int alternativeEmployeeI3D)
|
|
{
|
|
this.UpdateInvoice(invoiceI3D, price, invoice =>
|
|
{
|
|
invoice.Provision[0].EmployeeI3D = alternativeEmployeeI3D;
|
|
});
|
|
}
|
|
private void UpdateInvoice(int invoiceI3D, decimal price, Action<ReceiptInvoiceDTO> changeInvoice = null)
|
|
{
|
|
var invoice = (ReceiptInvoiceDTO)this.WithSession(s => s.GetBL<ReceiptWebServiceBL>().CreateNewVersion(
|
|
CentronObjectKindNumeric.InvoiceClass,
|
|
invoiceI3D,
|
|
version: null,
|
|
newContactPersonI3D: null,
|
|
this.GetLoggedInUser().User,
|
|
new CreateNewVersionData
|
|
{
|
|
IgnoreCallbacks = true,
|
|
})).ThrowIfError().Receipt;
|
|
|
|
invoice.Provision =
|
|
[
|
|
new ReceiptProvision
|
|
{
|
|
Receiver = ReceiptProvisionReceiver.FixedEmployee,
|
|
EmployeeI3D = EmployeeI3D,
|
|
ProvisionPercentage = null,
|
|
SharePercentage = 100,
|
|
Source = ReceiptProvisionSource.All,
|
|
Value = ReceiptProvisionValue.Sales,
|
|
}
|
|
];
|
|
|
|
invoice.Items[0].BasePrice = price;
|
|
invoice.Items[0].QuantityComplete = 1;
|
|
|
|
changeInvoice?.Invoke(invoice);
|
|
|
|
var savedInvoice = (ReceiptInvoiceDTO)this.WithSession(s => s.GetBL<ReceiptWebServiceBL>().SaveReceipt(
|
|
invoice,
|
|
this.GetLoggedInUser().User,
|
|
new SaveReceiptData
|
|
{
|
|
IgnoreCallbacks = true,
|
|
},
|
|
autoLockIfNewReceipt: false,
|
|
CreatedThroughApplication.WebServices,
|
|
receiptTemplateFolderI3D: null)).ThrowIfError().Receipt;
|
|
}
|
|
} |