-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathCustomers.cs
224 lines (201 loc) · 10.2 KB
/
Customers.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
using DotNetSampleApp.Models;
using Fauna;
using Fauna.Types;
using Microsoft.AspNetCore.Mvc;
namespace DotNetSampleApp.Controllers;
/// <summary>
/// Customers controller
/// </summary>
/// <param name="client">Fauna Client</param>
[ApiController,
Route("/[controller]")]
public class Customers(Client client) : ControllerBase
{
/// <summary>
/// Get Customer by ID
/// </summary>
/// <param name="customerId">Customer ID</param>
/// <returns>Customer</returns>
[ProducesResponseType(typeof(Customer), StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
[ProducesResponseType(StatusCodes.Status500InternalServerError)]
[HttpGet("{customerId}")]
public async Task<IActionResult> GetCustomer([FromRoute] string customerId)
{
// Get the Customer document by `id`, using the ! operator to assert that the document exists.
// If the document does not exist, Fauna will throw a document_not_found error.
//
// Use projection to only return the fields you need.
var query = Query.FQL($"""
let customer: Any = Customer.byId({customerId})!
{QuerySnippets.CustomerResponse()}
""");
// Connect to fauna using the client. The query method accepts an FQL query
// as a parameter and a generic type parameter representing the return type.
var res = await client.QueryAsync<Customer>(query);
return Ok(res.Data);
}
/// <summary>
/// Creates a new Customer
/// </summary>
/// <returns>Customer Details</returns>
[ProducesResponseType(typeof(Customer), StatusCodes.Status201Created)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
[ProducesResponseType(StatusCodes.Status500InternalServerError)]
[HttpPost]
public async Task<IActionResult> CreateCustomer(CustomerRequest customer)
{
// Create a new Customer document with the provided fields.
var query = Query.FQL($"""
let customer: Any = Customer.create({customer})
{QuerySnippets.CustomerResponse()}
""");
// Connect to fauna using the client. The query method accepts an FQL query
// as a parameter and a generic type parameter representing the return type.
var res = await client.QueryAsync<Customer>(query);
return CreatedAtAction(nameof(GetCustomer), new { customerId = res.Data.Id }, res.Data);
}
/// <summary>
/// Update Customer Details
/// </summary>
/// <returns>Customer Details</returns>
[ProducesResponseType(typeof(Customer), StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
[ProducesResponseType(StatusCodes.Status500InternalServerError)]
[HttpPost("{customerId}")]
public async Task<IActionResult> UpdateCustomer(
[FromRoute] string customerId,
CustomerRequest customer)
{
// Get the Customer document by `customerId`, using the ! operator to assert that the document exists.
// If the document does not exist, Fauna will throw a document_not_found error.
//
// All unannotated fields and fields annotated with @FaunaField will be serialized, including
// those with `null` values. When an update is made to a field with a null value, that value of
// that field is unset on the document. Partial updates must be made with a dedicated class,
// anonymous class, or Map.
//
// Use projection to only return the fields you need.
var query = Query.FQL($"""
let customer: Any = Customer.byId({customerId})!.update({customer})
{QuerySnippets.CustomerResponse()}
""");
// Connect to fauna using the client. The query method accepts an FQL query
// as a parameter and a generic type parameter representing the return type.
var res = await client.QueryAsync<Customer>(query);
return Ok(res.Data);
}
/// <summary>
/// Return all orders for a specific customer.
/// </summary>
/// <param name="customerId">Customer ID</param>
/// <param name="afterToken">The after token for pagination.</param>
/// <param name="pageSize">A page size. Ignored if after token is provided.</param>
/// <returns>List of Orders.</returns>
[ProducesResponseType(typeof(Page<Order>), StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
[ProducesResponseType(StatusCodes.Status500InternalServerError)]
[HttpGet("{customerId}/orders")]
public async Task<IActionResult> GetOrdersByCustomer(
[FromRoute] string customerId,
[FromQuery] string? afterToken,
[FromQuery] int pageSize = 10)
{
// The `afterToken` parameter contains a Fauna `after` cursor.
// `after` cursors may contain special characters, such as `.` or `+`).
// Make sure to URL encode the `afterToken` value to preserve these
// characters in URLs.
var query = !string.IsNullOrEmpty(afterToken)
// Paginate with the after token if it's present.
? Query.FQL($"Set.paginate({afterToken})")
// Define an FQL query to retrieve a page of orders for a given customer.
// Get the Customer document by id, using the ! operator to assert that the document exists.
// If the document does not exist, Fauna will throw a document_not_found error. We then
// use the Order.byCustomer index to retrieve all orders for that customer and map over
// the results to return only the fields we care about.
: Query.FQL($$"""
let customer: Any = Customer.byId({{customerId}})!
Order.byCustomer(customer).pageSize({{pageSize}}).map((order) => {
let order: Any = order
// Return the order.
{{QuerySnippets.OrderResponse()}}
})
""");
// Connect to fauna using the client. The query method accepts an FQL query
// as a parameter and a generic type parameter representing the return type.
var result = await client.QueryAsync<Page<Order>>(query);
return Ok(result.Data);
}
/// <summary>
/// Creates a new cart for a specific customer.
/// </summary>
/// <param name="customerId">Customer ID for new Cart</param>
/// <returns>Cart details</returns>
[ProducesResponseType(typeof(Order), StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
[ProducesResponseType(StatusCodes.Status500InternalServerError)]
[HttpPost("{customerId}/cart")]
public async Task<IActionResult> CreateCart([FromRoute] string customerId)
{
// Call our getOrCreateCart UDF to get the customer's cart. The function
// definition can be found 'server/schema/functions.fsl'.
var query = Query.FQL($"""
let order: Any = getOrCreateCart({customerId})
// Return the cart.
{QuerySnippets.OrderResponse()}
""");
// Connect to fauna using the client. The query method accepts an FQL query
// as a parameter and a generic type parameter representing the return type.
var res = await client.QueryAsync<Order>(query);
return CreatedAtAction(nameof(GetCart), new { customerId }, res.Data);
}
/// <summary>
/// Adds an item to the customer's cart.
/// </summary>
/// <param name="customerId">Customer ID</param>
/// <param name="item">Item details</param>
/// <returns>Cart Details</returns>
[ProducesResponseType(typeof(Order), StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
[ProducesResponseType(StatusCodes.Status500InternalServerError)]
[HttpPost("{customerId}/cart/item")]
public async Task<IActionResult> AddItemToCart([FromRoute] string customerId, AddItemToCartRequest item)
{
// Call our createOrUpdateCartItem UDF to add an item to the customer's cart. The function
// definition can be found 'server/schema/functions.fsl'.
var query = Query.FQL($"""
let req = {item}
let order: Any = createOrUpdateCartItem({customerId}, req.productName, req.quantity)
// Return the cart as an OrderResponse object.
{QuerySnippets.OrderResponse()}
""");
// Connect to fauna using the client. The query method accepts an FQL query
// as a parameter and a generic type parameter representing the return type.
var res = await client.QueryAsync<Order>(query);
return Ok(res.Data);
}
/// <summary>
/// Returns the contents of the customer's cart.
/// </summary>
/// <param name="customerId">Customer ID</param>
/// <returns>Cart Details</returns>
[ProducesResponseType(typeof(Order), StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status400BadRequest)]
[ProducesResponseType(StatusCodes.Status500InternalServerError)]
[HttpGet("{customerId}/cart")]
public async Task<IActionResult> GetCart([FromRoute] string customerId)
{
// Get the customer's cart by id, using the ! operator to assert that the document exists.
// If the document does not exist, Fauna will throw a document_not_found error.
var query = Query.FQL($"""
let order: Any = Customer.byId({customerId})!.cart
// Return the cart as an OrderResponse object.
{QuerySnippets.OrderResponse()}
""");
// Connect to fauna using the client. The query method accepts an FQL query
// as a parameter and a generic type parameter representing the return type.
var res = await client.QueryAsync<Order>(query);
return Ok(res.Data);
}
}