diff --git a/internal/processor/order_processor.go b/internal/processor/order_processor.go index bea796c..60ad0f4 100644 --- a/internal/processor/order_processor.go +++ b/internal/processor/order_processor.go @@ -316,6 +316,18 @@ func resolveLineQuantity(product *entities.Product, quantity int, weight *float6 } func (p *OrderProcessorImpl) CreateOrder(ctx context.Context, req *models.CreateOrderRequest, organizationID uuid.UUID) (*models.OrderResponse, error) { + // The order's customer earns EnakPoint and EnakCoin once it is paid, so it must be + // one of the organization's own; orders.customer_id has no foreign key to catch it. + customerID := req.CustomerID + if customerID != nil && *customerID == uuid.Nil { + customerID = nil + } + if customerID != nil { + if _, err := p.customerRepo.GetByIDAndOrganization(ctx, *customerID, organizationID); err != nil { + return nil, fmt.Errorf("customer not found or does not belong to the organization: %w", err) + } + } + orderNumber, err := p.orderRepo.GetNextOrderNumber(ctx, organizationID, req.OutletID) if err != nil { return nil, fmt.Errorf("failed to generate order number: %w", err) @@ -401,7 +413,7 @@ func (p *OrderProcessorImpl) CreateOrder(ctx context.Context, req *models.Create OrganizationID: organizationID, OutletID: req.OutletID, UserID: req.UserID, - CustomerID: req.CustomerID, + CustomerID: customerID, OrderNumber: orderNumber, TableNumber: req.TableNumber, OrderType: entities.OrderType(req.OrderType), diff --git a/internal/transformer/order_transformer.go b/internal/transformer/order_transformer.go index 5bd19ba..2ed1194 100644 --- a/internal/transformer/order_transformer.go +++ b/internal/transformer/order_transformer.go @@ -27,6 +27,7 @@ func CreateOrderContractToModel(req *contract.CreateOrderRequest) *models.Create return &models.CreateOrderRequest{ OutletID: req.OutletID, UserID: req.UserID, + CustomerID: req.CustomerID, TableID: req.TableID, TableNumber: req.TableNumber, OrderType: constants.OrderType(req.OrderType), diff --git a/internal/transformer/order_transformer_test.go b/internal/transformer/order_transformer_test.go index 5c55afd..4c6fcde 100644 --- a/internal/transformer/order_transformer_test.go +++ b/internal/transformer/order_transformer_test.go @@ -32,6 +32,20 @@ func TestCreateOrderContractToModelCarriesWeight(t *testing.T) { require.Equal(t, weight, *result.OrderItems[0].Weight) } +func TestCreateOrderContractToModelCarriesCustomer(t *testing.T) { + customerID := uuid.New() + + result := CreateOrderContractToModel(&contract.CreateOrderRequest{ + OutletID: uuid.New(), + UserID: uuid.New(), + CustomerID: &customerID, + OrderItems: []contract.CreateOrderItemRequest{{ProductID: uuid.New(), Quantity: 1}}, + }) + + require.NotNil(t, result.CustomerID, "the order's customer is who earns EnakPoint and EnakCoin") + require.Equal(t, customerID, *result.CustomerID) +} + func TestAddToOrderContractToModelCarriesWeight(t *testing.T) { weight := 0.8 diff --git a/migrations/000094_add_point_payment_method.down.sql b/migrations/000094_add_point_payment_method.down.sql index dd86218..4bffcee 100644 --- a/migrations/000094_add_point_payment_method.down.sql +++ b/migrations/000094_add_point_payment_method.down.sql @@ -13,4 +13,4 @@ DROP INDEX IF EXISTS uq_payment_methods_point_per_organization; ALTER TABLE payment_methods DROP CONSTRAINT IF EXISTS payment_methods_type_check; ALTER TABLE payment_methods ADD CONSTRAINT payment_methods_type_check - CHECK (type IN ('cash', 'card', 'digital_wallet')); + CHECK (type IN ('cash', 'card', 'digital_wallet', 'qr', 'edc', 'delivery')); diff --git a/migrations/000094_add_point_payment_method.up.sql b/migrations/000094_add_point_payment_method.up.sql index e39899e..eab3509 100644 --- a/migrations/000094_add_point_payment_method.up.sql +++ b/migrations/000094_add_point_payment_method.up.sql @@ -1,10 +1,11 @@ -- Paying with EnakPoint (docs/prd-point-coin.md F9, §8, §10.5). --- A new payment method type. Every organization has exactly one method of it, made by +-- A new payment method type, next to the existing ones (edc and delivery were added to +-- the constraint outside the migrations). Every organization has exactly one method of it, made by -- the system, which cannot be deleted or change type. ALTER TABLE payment_methods DROP CONSTRAINT IF EXISTS payment_methods_type_check; ALTER TABLE payment_methods ADD CONSTRAINT payment_methods_type_check - CHECK (type IN ('cash', 'card', 'digital_wallet', 'point')); + CHECK (type IN ('cash', 'card', 'digital_wallet', 'qr', 'edc', 'delivery', 'point')); CREATE UNIQUE INDEX uq_payment_methods_point_per_organization ON payment_methods(organization_id) WHERE type = 'point'; diff --git a/migrations/000098_allow_edc_delivery_payment_methods.down.sql b/migrations/000098_allow_edc_delivery_payment_methods.down.sql new file mode 100644 index 0000000..d3eedb5 --- /dev/null +++ b/migrations/000098_allow_edc_delivery_payment_methods.down.sql @@ -0,0 +1,2 @@ +-- Nothing to undo: 000094 now allows the same types. +SELECT 1; diff --git a/migrations/000098_allow_edc_delivery_payment_methods.up.sql b/migrations/000098_allow_edc_delivery_payment_methods.up.sql new file mode 100644 index 0000000..c831678 --- /dev/null +++ b/migrations/000098_allow_edc_delivery_payment_methods.up.sql @@ -0,0 +1,7 @@ +-- Production also has edc and delivery payment methods, allowed by a constraint changed +-- outside the migrations, and the code also accepts qr, which no constraint allowed. +-- 000094 first rewrote the constraint without them, which +-- failed on production and, where it ran, dropped them. Keep every type in use. +ALTER TABLE payment_methods DROP CONSTRAINT IF EXISTS payment_methods_type_check; +ALTER TABLE payment_methods ADD CONSTRAINT payment_methods_type_check + CHECK (type IN ('cash', 'card', 'digital_wallet', 'qr', 'edc', 'delivery', 'point'));