Skip to content
This repository was archived by the owner on Mar 18, 2025. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 38 additions & 0 deletions EasyQuotes/EasyQuotes.Contracts/Clients/Client.cs.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using EasyQuotes.Contracts.Suppliers;

namespace EasyQuotes.Contracts.Clients
{
public class Client(ClientId id, string nameOfClient, Contact contact, ClientType clientType = ClientType.Business)
{
public ClientId Id {get; init;} = id;

public string Name {get; init;} = nameOfClient;

public Contact Contact {get; init;} = contact;

public ClientType Type {get; init;} = clientType;

}

public sealed class ClientId(long id)
{
public long Value {get; init;} = id;

private static readonly long MinIdValue = 202411001;

public static readonly ClientId None = new(MinIdValue);
}

public class ClientIdException():ArgumentException(message:"Client id is not valid format.");

public enum ClientType:ushort
{
Business = 0,

Individual =1
}
}
56 changes: 56 additions & 0 deletions EasyQuotes/EasyQuotes.Contracts/Clients/ClientBuilder.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using EasyQuotes.Contracts.Suppliers;

namespace EasyQuotes.Contracts.Clients
{
public class ClientBuilder(ClientId id, string name, Contact telNumber)
{
private ClientId clientId = id;

private string nameOfClient = name;

private Contact telephoneNumber = telNumber;

private ClientType clientType = ClientType.Business;

private decimal clientRating = 0;

private string optionalNotes = string.Empty;

private string emailAddress = string.Empty;

public ClientBuilder WithClientType(ClientType type)
{
clientType = type;
return this;
}

public ClientBuilder WithRating(decimal rating)
{
clientRating = rating;
return this;
}

public ClientBuilder WithNotes(string notes)
{
optionalNotes = notes;
return this;
}

public Client TryBuild()
{
if (string.IsNullOrWhiteSpace(nameOfClient))
{
throw new ArgumentException("Client name cannot be empty.");
}
if (telephoneNumber == Contact.None)
{
throw new ArgumentException("Client must have a valid contact number");
}
return new Client(clientId, nameOfClient, telephoneNumber, clientType);
}
}
}
13 changes: 13 additions & 0 deletions EasyQuotes/EasyQuotes.Contracts/Clients/IClientRepository.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using EasyQuotes.Contracts.Shared;

namespace EasyQuotes.Contracts.Clients
{
public interface IClientRepository : IRepository<Client, ClientId>
{

}
}
145 changes: 145 additions & 0 deletions EasyQuotes/EasyQuotes.Contracts/Commerce/Money.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
namespace EasyQuotes.Contracts.Commerce
{
public class Money(int cents, Currency currency = Currency.ZAR)
{
public int InCents { get; init; } = cents;

public Currency Currency { get; init; } = currency;

public static readonly Money MinValue = new(0);

public static readonly Money Zero = MinValue;

public static Money FromParts(int wholePart, int centPart, Currency currency = Currency.ZAR)
{
int cents = wholePart * 100 + centPart;
return new(cents, currency);
}

public static Money FromParts(MoneyParts parts, Currency currency = Currency.ZAR)
{
return FromParts(parts.WholePart, parts.Cents, currency);
}

public decimal ToDecimal()
{
return Math.Round(InCents / 100m, 2);
}

public bool IsDeficit()
{
return InCents < 0;
}

public Money IncrementByPercent(double percent)
{
var increment = (int)Math.Round(InCents * percent / 100);
return new(InCents + increment, Currency);
}

public Money ReduceByPercent(double percent)
{
var decrement = (int)Math.Round(InCents * percent / 100);
return new(InCents - decrement, Currency);
}

public override string ToString()
{
return $"{Currency} {ToDecimal()}";
}

public override bool Equals(object? obj)
{
if (obj is null) return false;
if (obj is not Money) return false;
if (obj is Money money1)
{
if (money1.Currency != Currency) return false;

return money1.InCents == InCents;
}
return false;
}

public override int GetHashCode()
{
return InCents.GetHashCode();
}

public static bool operator ==(Money left, Money right)
{
return left.Equals(right);
}

public static bool operator !=(Money left, Money right)
{
return !left.Equals(right);
}

public static bool operator <(Money left, Money right)
{
ThrowIfDifferentCurrencies(left, right);
return left.InCents < right.InCents;
}

public static bool operator >(Money left, Money right)
{
ThrowIfDifferentCurrencies(left, right);
return left.InCents > right.InCents;
}

public static bool operator >=(Money left, Money right)
{
ThrowIfDifferentCurrencies(left, right);
return left.InCents >= right.InCents;
}

public static bool operator <=(Money left, Money right)
{
ThrowIfDifferentCurrencies(left, right);
return left.InCents <= right.InCents;

}

public static Money operator +(Money left, Money right)
{
ThrowIfDifferentCurrencies(left, right);
return new(left.InCents + right.InCents);
}

public static Money operator -(Money left, Money right)
{
ThrowIfDifferentCurrencies(left, right);
return new(left.InCents - right.InCents);
}

public static Money operator *(Money money, int multiplier)
{
if (money is null) return Money.MinValue;
return new(money.InCents * Math.Abs(multiplier));
}


private static void ThrowIfDifferentCurrencies(Money money1, Money money2, string message = "Cannot perform requested operation on monies of different currencies. Convert to same currency first.")
{
if (money1.Currency != money2.Currency)
{
throw new InvalidOperationException(message);
}
}
}

public enum Currency
{
ZAR,
USD,
EUR
}

public readonly struct MoneyParts(int whole, int cents)
{
public int WholePart { get; } = whole;

public int Cents { get; } = cents;
}
}
9 changes: 9 additions & 0 deletions EasyQuotes/EasyQuotes.Contracts/EasyQuotes.Contracts.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>

</Project>
59 changes: 59 additions & 0 deletions EasyQuotes/EasyQuotes.Contracts/Orders/Order.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
using EasyQuotes.Contracts.Products;
using EasyQuotes.Contracts.Clients;
using EasyQuotes.Contracts.Commerce;

namespace EasyQuotes.Contracts.Orders
{
public class Order(OrderId orderId,
Client forClient,
ICollection<OrderItem> orderItems,
DateTime dateOfOrder,
OrderStatus orderStatus = OrderStatus.Pending)
{
public OrderId Id {get; init;} = orderId;

public IReadOnlyCollection<OrderItem> OrderItems {get; init;} = orderItems.AsEnumerable().ToArray();

public DateTime DateOfOrder {get; init;} = dateOfOrder;

public Client Client {get; init;} = forClient;

public OrderStatus OrderStatus {get; init;} = orderStatus;

public Money CalculateTaxTotal()
{
Money taxTotal = Money.Zero;
foreach (var orderItem in OrderItems)
{
taxTotal += orderItem.CalculateTaxDue();
}
return taxTotal;
}

public Money CalculateOrderTotalExcludingTax()
{
Money total = Money.Zero;
foreach (var orderItem in OrderItems)
{
total += orderItem.CalculateTotalExcludingTax();
}
return total;
}

public Money CalculateOrderTotalIncludingTax()
{
return CalculateOrderTotalExcludingTax() + CalculateTaxTotal();
}

}

public enum OrderStatus:ushort
{
Pending = 0,
Fulfilled = 1,
Canceled = 2
}

public class InvalidQuantityException(string message="Specified quantity is not valid."):Exception(message)
{}
}
47 changes: 47 additions & 0 deletions EasyQuotes/EasyQuotes.Contracts/Orders/OrderId.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
namespace EasyQuotes.Contracts.Orders
{
public sealed class OrderId(long id)
{
private static bool IsValidId(long idValue)
{
return idValue >= 0L;
}

//public static readonly OrderId Null = new(0L);

public static readonly OrderId Default = new(1L);

public long Value {get; init;} = IsValidId(id) ? id : throw new InvalidIDException();

public override bool Equals(object? obj)
{
if (obj is null) return false;
if (obj is int || obj is long) return (long)obj == Value;
if (obj is OrderId id1)
{
return id1.Value == Value;
}
return base.Equals(obj);
}

public static bool operator ==(OrderId left, OrderId right)
{
return left.Equals(right);
}

public static bool operator !=(OrderId left, OrderId right)
{
return !left.Equals(right);
}

public override int GetHashCode()
{
return Value.GetHashCode();
}
}

public class InvalidIDException(string message="Given value is not valid for this id."): Exception(message)
{

}
}
Loading