delphimvcframework/samples/master_details/BusinessObjects.pas
2024-01-02 17:04:27 +01:00

336 lines
8.2 KiB
ObjectPascal

unit BusinessObjects;
// *************************************************************************** }
//
// Delphi MVC Framework
//
// Copyright (c) 2010-2024 Daniele Teti and the DMVCFramework Team
//
// https://github.com/danieleteti/delphimvcframework
//
// ***************************************************************************
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// ***************************************************************************
interface
uses
MVCFramework.Serializer.Commons,
MVCFramework.ActiveRecord,
MVCFramework.Nullables,
MVCFramework.Rtti.Utils,
System.Generics.Collections,
System.Classes;
type
[MVCNameCase(ncCamelCase)]
[MVCTable('articles')]
TArticles = class(TMVCActiveRecord)
private
[MVCTableField('id', [foPrimaryKey, foAutoGenerated])]
fID: Int64;
[MVCTableField('description')]
fDescription: String;
[MVCTableField('price')]
fPrice: Integer;
public
constructor Create; override;
destructor Destroy; override;
property ID: Int64 read fID write fID;
property Description: String read fDescription write fDescription;
property Price: Integer read fPrice write fPrice;
end;
[MVCNameCase(ncCamelCase)]
[MVCTable('order_details')]
TOrderDetail = class(TMVCActiveRecord)
private
[MVCTableField('id', [foPrimaryKey, foAutoGenerated])]
fID: NullableInt64;
[MVCTableField('id_order')]
fIDOrder: Int64;
[MVCTableField('id_article')]
fIDArticle: Int64;
[MVCTableField('unit_price')]
fUnitPrice: Currency;
[MVCTableField('discount')]
fDiscount: Integer;
[MVCTableField('quantity')]
fQuantity: Integer;
[MVCTableField('description')]
fDescription: String;
[MVCTableField('total')]
fTotal: Currency;
procedure SetDescription(const Value: String);
procedure SetDiscount(const Value: Integer);
procedure SetQuantity(const Value: Integer);
procedure SetUnitPrice(const Value: Currency);
protected
procedure OnBeforeInsertOrUpdate; override;
public
constructor Create; override;
destructor Destroy; override;
procedure RecalcTotal;
function Clone: TOrderDetail;
procedure Assign(Value: TMVCActiveRecord); override;
property ID: NullableInt64 read fID write fID;
[MVCDoNotSerialize]
property IDOrder: Int64 read fIDOrder write fIDOrder;
property IDArticle: Int64 read fIDArticle write fIDArticle;
property UnitPrice: Currency read fUnitPrice write SetUnitPrice;
property Discount: Integer read fDiscount write SetDiscount;
property Quantity: Integer read fQuantity write SetQuantity;
property Description: String read fDescription write SetDescription;
property Total: Currency read fTotal;
end;
[MVCNameCase(ncCamelCase)]
[MVCTable('orders')]
TOrder = class(TMVCActiveRecord)
private
[MVCTableField('id', [foPrimaryKey, foAutoGenerated])]
fID: NullableUInt64;
[MVCTableField('id_customer')]
fIDCustomer: Integer;
[MVCTableField('order_date')]
fOrderDate: TDate;
[MVCTableField('total')]
fTotal: Currency;
[MVCOwned]
fDetails: TObjectList<TOrderDetail>;
protected
procedure OnAfterLoad; override;
procedure OnAfterInsertOrUpdate; override;
procedure OnBeforeInsertOrUpdate; override;
procedure RecalcTotals;
public
constructor Create; override;
destructor Destroy; override;
procedure AddOrderItem(const OrderItem: TOrderDetail);
procedure UpdateOrderItemByID(const OrderItemID: Integer; const OrderItem: TOrderDetail);
function GetOrderDetailByID(const Value: Int64): TOrderDetail;
property ID: NullableUInt64 read fID write fID;
[MVCNameAs('idCustomer')]
property IDCustomer: Integer read fIDCustomer write fIDCustomer;
property OrderDate: TDate read fOrderDate write fOrderDate;
property Total: Currency read fTotal write fTotal;
property OrderItems: TObjectList<TOrderDetail> read fDetails;
end;
[MVCNameCase(ncCamelCase)]
TOrderIn = class
private
fID: NullableUInt64;
fIDCustomer: NullableUInt64;
fOrderDate: NullableTDate;
fTotal: NullableCurrency;
[MVCOwned(TOrderDetail)]
fDetails: TObjectList<TOrderDetail>;
public
constructor Create;
destructor Destroy; override;
property ID: NullableUInt64 read fID write fID;
[MVCNameAs('idCustomer')]
property IDCustomer: NullableUInt64 read fIDCustomer write fIDCustomer;
property OrderDate: NullableTDate read fOrderDate write fOrderDate;
property Total: NullableCurrency read fTotal write fTotal;
property OrderItems: TObjectList<TOrderDetail> read fDetails;
end;
implementation
uses
System.SysUtils;
constructor TArticles.Create;
begin
inherited Create;
end;
destructor TArticles.Destroy;
begin
inherited;
end;
procedure TOrderDetail.Assign(Value: TMVCActiveRecord);
var
lObj: TOrderDetail;
begin
if Value is TOrderDetail then
begin
lObj := TOrderDetail(Value);
self.ID := lObj.ID;
self.IDOrder := lObj.IDOrder;
self.IDArticle := lObj.IDArticle;
self.UnitPrice := lObj.UnitPrice;
self.Discount := lObj.Discount;
self.Quantity := lObj.Quantity;
self.Description := lObj.Description;
end
else
begin
inherited;
end;
end;
function TOrderDetail.Clone: TOrderDetail;
begin
Result := TOrderDetail.Create;
Result.Assign(Self);
end;
constructor TOrderDetail.Create;
begin
inherited Create;
end;
destructor TOrderDetail.Destroy;
begin
inherited;
end;
procedure TOrderDetail.OnBeforeInsertOrUpdate;
begin
inherited;
RecalcTotal;
end;
procedure TOrderDetail.RecalcTotal;
begin
fTotal := fUnitPrice * fQuantity * (1 - fDiscount / 100);
end;
procedure TOrderDetail.SetDescription(const Value: String);
begin
fDescription := Value;
end;
procedure TOrderDetail.SetDiscount(const Value: Integer);
begin
fDiscount := Value;
RecalcTotal;
end;
procedure TOrderDetail.SetQuantity(const Value: Integer);
begin
fQuantity := Value;
RecalcTotal;
end;
procedure TOrderDetail.SetUnitPrice(const Value: Currency);
begin
fUnitPrice := Value;
RecalcTotal;
end;
procedure TOrder.AddOrderItem(const OrderItem: TOrderDetail);
begin
OrderItem.IDOrder := ID;
OrderItems.Add(OrderItem);
end;
constructor TOrder.Create;
begin
inherited Create;
fDetails := TObjectList<TOrderDetail>.Create(true);
end;
destructor TOrder.Destroy;
begin
fDetails.Free;
inherited;
end;
function TOrder.GetOrderDetailByID(const Value: Int64): TOrderDetail;
var
lOrderDetail: TOrderDetail;
begin
inherited;
for lOrderDetail in fDetails do
begin
if lOrderDetail.ID.Value = Value then
begin
Exit(lOrderDetail);
end;
end;
raise EMVCActiveRecord.Create('Item not found');
end;
procedure TOrder.OnAfterInsertOrUpdate;
begin
inherited;
for var lOrderItem in OrderItems do
begin
lOrderItem.IDOrder := ID;
lOrderItem.Store;
end;
end;
procedure TOrder.OnBeforeInsertOrUpdate;
begin
inherited;
RecalcTotals;
end;
procedure TOrder.RecalcTotals;
begin
fTotal := 0;
for var lOrderItem in fDetails do
begin
fTotal := fTotal + lOrderItem.Total;
end;
end;
procedure TOrder.UpdateOrderItemByID(const OrderItemID: Integer;
const OrderItem: TOrderDetail);
begin
var lObj := GetOrderDetailByID(OrderItemID);
lObj.Assign(OrderItem);
lObj.IDOrder := ID;
end;
procedure TOrder.OnAfterLoad;
var
lList: TObjectList<TOrderDetail>;
begin
inherited;
lList := TMVCActiveRecord.SelectRQL<TOrderDetail>(Format('eq(idOrder,%d)',[ID.Value]), 1000);
try
fDetails.Clear;
fDetails.AddRange(lList);
lList.OwnsObjects := False;
finally
lList.Free;
end;
end;
{ TOrderIn }
constructor TOrderIn.Create;
begin
inherited;
fDetails := TObjectList<TOrderDetail>.Create(true);
end;
destructor TOrderIn.Destroy;
begin
fDetails.Free;
inherited;
end;
end.