washday-sdk 1.0.2 → 1.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +127 -0
- package/babel.config.js +8 -0
- package/dist/api/attendance/delete.js +2 -0
- package/dist/api/attendance/get.js +89 -0
- package/dist/api/attendance/index.js +4 -0
- package/dist/api/attendance/post.js +39 -0
- package/dist/api/attendance/put.js +25 -0
- package/dist/api/auth/index.js +3 -0
- package/dist/api/auth/post.js +170 -0
- package/dist/api/axiosInstance.js +15 -11
- package/dist/api/cashierbox/delete.js +40 -0
- package/dist/api/cashierbox/get.js +63 -0
- package/dist/api/cashierbox/post.js +42 -0
- package/dist/api/cashierbox/put.js +42 -0
- package/dist/api/cashups/delete.js +25 -0
- package/dist/api/cashups/get.js +60 -0
- package/dist/api/cashups/index.js +4 -0
- package/dist/api/cashups/post.js +25 -0
- package/dist/api/cashups/put.js +52 -0
- package/dist/api/cfdi/delete.js +25 -0
- package/dist/api/cfdi/get.js +126 -0
- package/dist/api/cfdi/index.js +4 -0
- package/dist/api/cfdi/post.js +41 -0
- package/dist/api/cfdi/put.js +52 -0
- package/dist/api/companies/get.js +29 -0
- package/dist/api/companies/post.js +41 -0
- package/dist/api/companies/put.js +57 -0
- package/dist/api/countries/get.js +29 -0
- package/dist/api/countries/post.js +1 -0
- package/dist/api/countries/put.js +1 -0
- package/dist/api/csv/get.js +325 -0
- package/dist/api/csv/index.js +1 -0
- package/dist/api/customers/delete.js +40 -0
- package/dist/api/customers/get.js +75 -20
- package/dist/api/customers/index.js +4 -1
- package/dist/api/customers/post.js +41 -0
- package/dist/api/customers/put.js +52 -0
- package/dist/api/discounts/get.js +120 -0
- package/dist/api/discounts/post.js +40 -0
- package/dist/api/discounts/put.js +68 -0
- package/dist/api/index.js +316 -8
- package/dist/api/inventory/delete.js +26 -0
- package/dist/api/inventory/get.js +62 -0
- package/dist/api/inventory/index.js +4 -0
- package/dist/api/inventory/post.js +26 -0
- package/dist/api/inventory/put.js +41 -0
- package/dist/api/order/delete.js +40 -0
- package/dist/api/order/get.js +181 -0
- package/dist/api/order/index.js +4 -0
- package/dist/api/order/post.js +115 -0
- package/dist/api/order/put.js +202 -0
- package/dist/api/outsourcedOrders/delete.js +25 -0
- package/dist/api/outsourcedOrders/get.js +62 -0
- package/dist/api/outsourcedOrders/index.js +4 -0
- package/dist/api/outsourcedOrders/post.js +25 -0
- package/dist/api/outsourcedOrders/put.js +25 -0
- package/dist/api/partners/delete.js +25 -0
- package/dist/api/partners/get.js +40 -0
- package/dist/api/partners/index.js +4 -0
- package/dist/api/partners/post.js +25 -0
- package/dist/api/partners/put.js +25 -0
- package/dist/api/pdf/get.js +43 -0
- package/dist/api/pdf/index.js +1 -0
- package/dist/api/products/delete.js +40 -0
- package/dist/api/products/get.js +25 -0
- package/dist/api/products/index.js +4 -0
- package/dist/api/products/post.js +60 -0
- package/dist/api/products/put.js +40 -0
- package/dist/api/publics/get.js +26 -0
- package/dist/api/publics/index.js +1 -0
- package/dist/api/reports/get.js +303 -0
- package/dist/api/reports/index.js +1 -0
- package/dist/api/reviews/delete.js +15 -0
- package/dist/api/reviews/get.js +41 -0
- package/dist/api/reviews/index.js +4 -0
- package/dist/api/reviews/post.js +20 -0
- package/dist/api/reviews/put.js +52 -0
- package/dist/api/routes/delete.js +25 -0
- package/dist/api/routes/get.js +95 -0
- package/dist/api/routes/index.js +4 -0
- package/dist/api/routes/post.js +67 -0
- package/dist/api/routes/put.js +54 -0
- package/dist/api/sections/delete.js +25 -0
- package/dist/api/sections/get.js +71 -0
- package/dist/api/sections/index.js +4 -0
- package/dist/api/sections/post.js +26 -0
- package/dist/api/sections/put.js +25 -0
- package/dist/api/staff/delete.js +26 -0
- package/dist/api/staff/get.js +40 -0
- package/dist/api/staff/post.js +26 -0
- package/dist/api/staff/put.js +26 -0
- package/dist/api/stores/get.js +110 -0
- package/dist/api/stores/post.js +61 -0
- package/dist/api/stores/put.js +44 -0
- package/dist/api/stripe/get.js +1 -0
- package/dist/api/stripe/post.js +71 -0
- package/dist/api/stripe/put.js +1 -0
- package/dist/api/supplies/delete.js +26 -0
- package/dist/api/supplies/get.js +62 -0
- package/dist/api/supplies/post.js +26 -0
- package/dist/api/supplies/put.js +41 -0
- package/dist/api/users/delete.js +26 -0
- package/dist/api/users/post.js +25 -0
- package/dist/api/users/put.js +29 -0
- package/dist/enum/index.js +12 -7
- package/dist/index.js +3 -33
- package/dist/interfaces/Api.js +1 -3
- package/dist/interfaces/Apple.js +16 -0
- package/dist/interfaces/Attendance.js +1 -0
- package/dist/interfaces/Customer.js +1 -2
- package/dist/interfaces/Order.js +1 -2
- package/dist/interfaces/Permission.js +1 -2
- package/dist/interfaces/Product.js +1 -2
- package/dist/interfaces/Section.js +1 -2
- package/dist/interfaces/Store.js +1 -2
- package/dist/interfaces/StoreImage.js +1 -2
- package/dist/interfaces/User.js +1 -2
- package/dist/utils/apiUtils.js +9 -0
- package/dist/utils/index.js +2 -17
- package/dist/utils/orders/calculateOrderTotal.js +30 -21
- package/dist/utils/orders/calculateTotalTaxesIncluded.js +55 -29
- package/dist/utils/orders/calculateTotalTaxesOverPrice.js +56 -45
- package/dist/utils/orders/helpers.js +126 -17
- package/dist/utils/orders/index.js +3 -5
- package/dist/utils/receipt/generateReceiptHTML.js +157 -0
- package/dist/utils/util.js +63 -0
- package/docs/README.md +67 -0
- package/docs/examples/common-use-cases.md +487 -0
- package/docs/getting-started.md +237 -0
- package/docs/modules/attendance.md +404 -0
- package/jest.config.js +0 -0
- package/package.json +12 -4
- package/src/api/attendance/delete.ts +1 -0
- package/src/api/attendance/get.ts +88 -0
- package/src/api/attendance/index.ts +4 -0
- package/src/api/attendance/post.ts +38 -0
- package/src/api/attendance/put.ts +20 -0
- package/src/api/auth/index.ts +3 -0
- package/src/api/auth/post.ts +198 -0
- package/src/api/axiosInstance.ts +13 -3
- package/src/api/cashierbox/delete.ts +28 -0
- package/src/api/cashierbox/get.ts +53 -0
- package/src/api/cashierbox/post.ts +39 -0
- package/src/api/cashierbox/put.ts +32 -0
- package/src/api/cashups/delete.ts +15 -0
- package/src/api/cashups/get.ts +52 -0
- package/src/api/cashups/index.ts +4 -0
- package/src/api/cashups/post.ts +23 -0
- package/src/api/cashups/put.ts +53 -0
- package/src/api/cfdi/delete.ts +21 -0
- package/src/api/cfdi/get.ts +119 -0
- package/src/api/cfdi/index.ts +4 -0
- package/src/api/cfdi/post.ts +60 -0
- package/src/api/cfdi/put.ts +53 -0
- package/src/api/companies/get.ts +23 -0
- package/src/api/companies/post.ts +29 -0
- package/src/api/companies/put.ts +43 -0
- package/src/api/countries/get.ts +23 -0
- package/src/api/countries/post.ts +0 -0
- package/src/api/countries/put.ts +0 -0
- package/src/api/csv/get.ts +354 -0
- package/src/api/csv/index.ts +1 -0
- package/src/api/customers/delete.ts +29 -0
- package/src/api/customers/get.ts +80 -8
- package/src/api/customers/index.ts +4 -0
- package/src/api/customers/post.ts +48 -0
- package/src/api/customers/put.ts +68 -0
- package/src/api/discounts/get.ts +100 -0
- package/src/api/discounts/post.ts +35 -0
- package/src/api/discounts/put.ts +66 -0
- package/src/api/index.ts +318 -11
- package/src/api/inventory/delete.ts +16 -0
- package/src/api/inventory/get.ts +53 -0
- package/src/api/inventory/index.ts +4 -0
- package/src/api/inventory/post.ts +22 -0
- package/src/api/inventory/put.ts +35 -0
- package/src/api/order/delete.ts +29 -0
- package/src/api/order/get.ts +207 -0
- package/src/api/order/index.ts +4 -0
- package/src/api/order/post.ts +118 -0
- package/src/api/order/put.ts +224 -0
- package/src/api/outsourcedOrders/delete.ts +15 -0
- package/src/api/outsourcedOrders/get.ts +54 -0
- package/src/api/outsourcedOrders/index.ts +4 -0
- package/src/api/outsourcedOrders/post.ts +24 -0
- package/src/api/outsourcedOrders/put.ts +21 -0
- package/src/api/partners/delete.ts +15 -0
- package/src/api/partners/get.ts +28 -0
- package/src/api/partners/index.ts +4 -0
- package/src/api/partners/post.ts +21 -0
- package/src/api/partners/put.ts +21 -0
- package/src/api/pdf/get.ts +43 -0
- package/src/api/pdf/index.ts +1 -0
- package/src/api/products/delete.ts +28 -0
- package/src/api/products/get.ts +16 -0
- package/src/api/products/index.ts +4 -0
- package/src/api/products/post.ts +73 -0
- package/src/api/products/put.ts +49 -0
- package/src/api/publics/get.ts +16 -0
- package/src/api/publics/index.ts +1 -0
- package/src/api/reports/get.ts +329 -0
- package/src/api/reports/index.ts +1 -0
- package/src/api/reviews/delete.ts +15 -0
- package/src/api/reviews/get.ts +31 -0
- package/src/api/reviews/index.ts +4 -0
- package/src/api/reviews/post.ts +20 -0
- package/src/api/reviews/put.ts +53 -0
- package/src/api/routes/delete.ts +15 -0
- package/src/api/routes/get.ts +86 -0
- package/src/api/routes/index.ts +4 -0
- package/src/api/routes/post.ts +60 -0
- package/src/api/routes/put.ts +44 -0
- package/src/api/sections/delete.ts +15 -0
- package/src/api/sections/get.ts +67 -0
- package/src/api/sections/index.ts +4 -0
- package/src/api/sections/post.ts +22 -0
- package/src/api/sections/put.ts +23 -0
- package/src/api/staff/delete.ts +16 -0
- package/src/api/staff/get.ts +29 -0
- package/src/api/staff/post.ts +17 -0
- package/src/api/staff/put.ts +17 -0
- package/src/api/stores/get.ts +93 -0
- package/src/api/stores/post.ts +49 -0
- package/src/api/stores/put.ts +35 -0
- package/src/api/stripe/get.ts +0 -0
- package/src/api/stripe/post.ts +59 -0
- package/src/api/stripe/put.ts +0 -0
- package/src/api/supplies/delete.ts +16 -0
- package/src/api/supplies/get.ts +53 -0
- package/src/api/supplies/post.ts +26 -0
- package/src/api/supplies/put.ts +33 -0
- package/src/api/users/delete.ts +16 -0
- package/src/api/users/post.ts +18 -0
- package/src/api/users/put.ts +36 -0
- package/src/enum/index.ts +9 -1
- package/src/index.ts +1 -4
- package/src/interfaces/Api.ts +307 -2
- package/src/interfaces/Apple.ts +74 -0
- package/src/interfaces/Attendance.ts +45 -0
- package/src/interfaces/Customer.ts +15 -11
- package/src/interfaces/Order.ts +38 -1
- package/src/interfaces/Product.ts +1 -0
- package/src/interfaces/Store.ts +41 -0
- package/src/utils/apiUtils.ts +11 -0
- package/src/utils/index.ts +6 -1
- package/src/utils/orders/calculateOrderTotal.test.js +930 -0
- package/src/utils/orders/calculateOrderTotal.ts +60 -15
- package/src/utils/orders/calculateTotalTaxesIncluded.ts +57 -25
- package/src/utils/orders/calculateTotalTaxesOverPrice.ts +57 -41
- package/src/utils/orders/helpers.ts +195 -47
- package/src/utils/orders/index.ts +3 -1
- package/src/utils/receipt/generateReceiptHTML.ts +163 -0
- package/src/utils/util.ts +65 -0
- package/tsconfig.json +13 -9
|
@@ -0,0 +1,487 @@
|
|
|
1
|
+
# 📋 Common Use Cases
|
|
2
|
+
|
|
3
|
+
This guide provides practical examples for common scenarios you'll encounter when integrating with the Washday API.
|
|
4
|
+
|
|
5
|
+
## 🏢 Store Management
|
|
6
|
+
|
|
7
|
+
### Get Store Information
|
|
8
|
+
```typescript
|
|
9
|
+
const client = new WashdayClient('your-token');
|
|
10
|
+
|
|
11
|
+
// Get a specific store
|
|
12
|
+
const store = await client.stores.getStoreById('store-id');
|
|
13
|
+
console.log(`Store: ${store.data.name} - ${store.data.city}`);
|
|
14
|
+
|
|
15
|
+
// Get all active stores
|
|
16
|
+
const stores = await client.stores.getStores({ isActive: 'true' });
|
|
17
|
+
stores.data.forEach(store => {
|
|
18
|
+
console.log(`${store.name}: ${store.phone}`);
|
|
19
|
+
});
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
### Update Store Settings
|
|
23
|
+
```typescript
|
|
24
|
+
// Update store configuration
|
|
25
|
+
await client.stores.updateStoreById('store-id', {
|
|
26
|
+
phone: '+1-555-0123',
|
|
27
|
+
allowPrePaid: true,
|
|
28
|
+
attendanceConfig: {
|
|
29
|
+
maxShiftHours: 10,
|
|
30
|
+
requireClockInOnLogin: true
|
|
31
|
+
}
|
|
32
|
+
});
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
## 👥 Employee Management
|
|
36
|
+
|
|
37
|
+
### Complete Attendance Workflow
|
|
38
|
+
```typescript
|
|
39
|
+
async function manageEmployeeShift(storeId: string) {
|
|
40
|
+
const client = new WashdayClient('your-token');
|
|
41
|
+
|
|
42
|
+
// Check if employee is already clocked in
|
|
43
|
+
const status = await client.attendance.getStatus({ storeId });
|
|
44
|
+
|
|
45
|
+
if (status.active) {
|
|
46
|
+
console.log('Employee is already clocked in');
|
|
47
|
+
|
|
48
|
+
// Clock out
|
|
49
|
+
const clockOut = await client.attendance.clockOut({
|
|
50
|
+
notes: 'End of shift'
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
console.log(`Shift duration: ${clockOut.data.shiftDuration.hours}h ${clockOut.data.shiftDuration.minutes}m`);
|
|
54
|
+
} else {
|
|
55
|
+
// Clock in
|
|
56
|
+
await client.attendance.clockIn({
|
|
57
|
+
storeId,
|
|
58
|
+
notes: 'Starting shift'
|
|
59
|
+
});
|
|
60
|
+
console.log('Successfully clocked in');
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
### Generate Attendance Report
|
|
66
|
+
```typescript
|
|
67
|
+
async function generateWeeklyReport(storeId: string) {
|
|
68
|
+
const client = new WashdayClient('your-token');
|
|
69
|
+
|
|
70
|
+
const startDate = new Date();
|
|
71
|
+
startDate.setDate(startDate.getDate() - 7);
|
|
72
|
+
|
|
73
|
+
const report = await client.attendance.getStoreReport(storeId, {
|
|
74
|
+
startDate: startDate.toISOString().split('T')[0],
|
|
75
|
+
endDate: new Date().toISOString().split('T')[0]
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
console.log(`Weekly Report for ${report.data.storeName}`);
|
|
79
|
+
report.data.employees.forEach(emp => {
|
|
80
|
+
console.log(`${emp.employee.name}: ${emp.totalHours} hours, ${emp.totalShifts} shifts`);
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
## 🛒 Customer & Order Processing
|
|
86
|
+
|
|
87
|
+
### Create Customer and First Order
|
|
88
|
+
```typescript
|
|
89
|
+
async function createCustomerWithOrder(storeId: string) {
|
|
90
|
+
const client = new WashdayClient('your-token');
|
|
91
|
+
|
|
92
|
+
// Create customer
|
|
93
|
+
const customer = await client.customers.create({
|
|
94
|
+
name: 'Jane Smith',
|
|
95
|
+
email: 'jane@example.com',
|
|
96
|
+
phone: '+1234567890',
|
|
97
|
+
address: '123 Main St, City, State',
|
|
98
|
+
isActive: true
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
// Create order for the customer
|
|
102
|
+
const order = await client.orders.createOrderUsersApp({
|
|
103
|
+
customer: customer.data._id,
|
|
104
|
+
store: storeId,
|
|
105
|
+
delivery: true,
|
|
106
|
+
pickup: false,
|
|
107
|
+
express: false,
|
|
108
|
+
phone: customer.data.phone,
|
|
109
|
+
address: customer.data.address,
|
|
110
|
+
products: [
|
|
111
|
+
{
|
|
112
|
+
storeProductId: 'product-id',
|
|
113
|
+
quantity: 2,
|
|
114
|
+
properties: ['Large', 'Cotton']
|
|
115
|
+
}
|
|
116
|
+
],
|
|
117
|
+
status: 'pending',
|
|
118
|
+
paymentMethod: 'cash',
|
|
119
|
+
notifyBy: 'email'
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
console.log(`Created order ${order.data.sequence} for ${customer.data.name}`);
|
|
123
|
+
}
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
### Process Orders in Bulk
|
|
127
|
+
```typescript
|
|
128
|
+
async function processOrdersBatch(storeId: string) {
|
|
129
|
+
const client = new WashdayClient('your-token');
|
|
130
|
+
|
|
131
|
+
// Get all pending orders
|
|
132
|
+
const pendingOrders = await client.orders.getList({
|
|
133
|
+
storeId,
|
|
134
|
+
status: 'pending',
|
|
135
|
+
limit: '50'
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
console.log(`Processing ${pendingOrders.data.length} pending orders`);
|
|
139
|
+
|
|
140
|
+
// Accept all pending orders
|
|
141
|
+
for (const order of pendingOrders.data) {
|
|
142
|
+
try {
|
|
143
|
+
await client.orders.setOrderAcceptedBySequence(order.sequence, storeId);
|
|
144
|
+
console.log(`✅ Accepted order ${order.sequence}`);
|
|
145
|
+
} catch (error) {
|
|
146
|
+
console.error(`❌ Failed to accept order ${order.sequence}:`, error.message);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
### Order Status Updates
|
|
153
|
+
```typescript
|
|
154
|
+
async function updateOrderLifecycle(sequence: string, storeId: string) {
|
|
155
|
+
const client = new WashdayClient('your-token');
|
|
156
|
+
|
|
157
|
+
try {
|
|
158
|
+
// Accept order
|
|
159
|
+
await client.orders.setOrderAcceptedBySequence(sequence, storeId);
|
|
160
|
+
console.log('Order accepted');
|
|
161
|
+
|
|
162
|
+
// Mark as cleaning
|
|
163
|
+
await client.orders.setOrderCleaningBySequence(sequence, storeId);
|
|
164
|
+
console.log('Order in cleaning');
|
|
165
|
+
|
|
166
|
+
// Mark as cleaned and ready
|
|
167
|
+
await client.orders.setOrderCleanedBySequence(sequence, storeId, {
|
|
168
|
+
cleanedDateTime: new Date().toISOString(),
|
|
169
|
+
readyDateTime: new Date().toISOString()
|
|
170
|
+
});
|
|
171
|
+
console.log('Order cleaned and ready');
|
|
172
|
+
|
|
173
|
+
// Mark as collected
|
|
174
|
+
await client.orders.setOrderCollectedBySequence(sequence, storeId, {
|
|
175
|
+
collectedDateTime: new Date().toISOString()
|
|
176
|
+
});
|
|
177
|
+
console.log('Order collected');
|
|
178
|
+
|
|
179
|
+
} catch (error) {
|
|
180
|
+
console.error('Failed to update order:', error.message);
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
## 💰 Financial Operations
|
|
186
|
+
|
|
187
|
+
### Daily Cash-Up Process
|
|
188
|
+
```typescript
|
|
189
|
+
async function performDailyCashUp(storeId: string, cashierBoxId: string) {
|
|
190
|
+
const client = new WashdayClient('your-token');
|
|
191
|
+
|
|
192
|
+
// Get cash-up preview data
|
|
193
|
+
const previewData = await client.cashup.getPreviewDataForCashClose(storeId, cashierBoxId);
|
|
194
|
+
|
|
195
|
+
console.log('Daily totals:');
|
|
196
|
+
console.log(`Cash from orders: $${previewData.data.cashFromOrders}`);
|
|
197
|
+
console.log(`Card from orders: $${previewData.data.cardFromOrders}`);
|
|
198
|
+
|
|
199
|
+
// Perform cash-up
|
|
200
|
+
const cashUp = await client.cashup.create(storeId, cashierBoxId, {
|
|
201
|
+
cashierBox: cashierBoxId,
|
|
202
|
+
startingCash: 100.00,
|
|
203
|
+
declaredCash: previewData.data.expectedCash,
|
|
204
|
+
declaredCard: previewData.data.cardFromOrders,
|
|
205
|
+
declaredTransfer: previewData.data.transferFromOrders || 0,
|
|
206
|
+
cashToBank: 500.00,
|
|
207
|
+
notes: 'Daily cash-up completed'
|
|
208
|
+
});
|
|
209
|
+
|
|
210
|
+
console.log(`Cash-up completed. Variance: $${cashUp.data.variance}`);
|
|
211
|
+
}
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
### Payment Processing
|
|
215
|
+
```typescript
|
|
216
|
+
async function addPaymentToOrder(orderId: string, storeId: string) {
|
|
217
|
+
const client = new WashdayClient('your-token');
|
|
218
|
+
|
|
219
|
+
// Get order details
|
|
220
|
+
const order = await client.orders.getById(orderId);
|
|
221
|
+
const amountDue = order.data.total - order.data.amountPaid;
|
|
222
|
+
|
|
223
|
+
if (amountDue > 0) {
|
|
224
|
+
// Add payment line
|
|
225
|
+
await client.orders.createPaymentLine(orderId, {
|
|
226
|
+
amountPaid: amountDue,
|
|
227
|
+
cashierBox: 'cashier-box-id',
|
|
228
|
+
paymentMethod: 'card',
|
|
229
|
+
paymentDate: new Date()
|
|
230
|
+
});
|
|
231
|
+
|
|
232
|
+
console.log(`Added payment of $${amountDue} to order ${order.data.sequence}`);
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
## 📊 Reporting & Analytics
|
|
238
|
+
|
|
239
|
+
### Generate Sales Report
|
|
240
|
+
```typescript
|
|
241
|
+
async function generateMonthlySalesReport(storeId: string) {
|
|
242
|
+
const client = new WashdayClient('your-token');
|
|
243
|
+
|
|
244
|
+
const startDate = new Date();
|
|
245
|
+
startDate.setMonth(startDate.getMonth() - 1);
|
|
246
|
+
startDate.setDate(1);
|
|
247
|
+
|
|
248
|
+
const endDate = new Date();
|
|
249
|
+
endDate.setDate(0); // Last day of previous month
|
|
250
|
+
|
|
251
|
+
const salesReport = await client.reports.getSalesReport(storeId, {
|
|
252
|
+
fromDate: startDate.toISOString().split('T')[0],
|
|
253
|
+
toDate: endDate.toISOString().split('T')[0],
|
|
254
|
+
type: 'daily'
|
|
255
|
+
});
|
|
256
|
+
|
|
257
|
+
console.log('Monthly Sales Report:');
|
|
258
|
+
salesReport.data.forEach(day => {
|
|
259
|
+
console.log(`${day.date}: $${day.total} (${day.orders} orders)`);
|
|
260
|
+
});
|
|
261
|
+
}
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
### Export Data to CSV
|
|
265
|
+
```typescript
|
|
266
|
+
async function exportCustomersData(storeId: string) {
|
|
267
|
+
const client = new WashdayClient('your-token');
|
|
268
|
+
|
|
269
|
+
const csvData = await client.csvExports.exportCustomersList({
|
|
270
|
+
fromDate: '2025-01-01',
|
|
271
|
+
toDate: '2025-01-31',
|
|
272
|
+
limit: '1000',
|
|
273
|
+
pageNum: '1'
|
|
274
|
+
});
|
|
275
|
+
|
|
276
|
+
// Save CSV data to file
|
|
277
|
+
const fs = require('fs');
|
|
278
|
+
fs.writeFileSync('customers-export.csv', csvData);
|
|
279
|
+
console.log('Customer data exported to customers-export.csv');
|
|
280
|
+
}
|
|
281
|
+
```
|
|
282
|
+
|
|
283
|
+
## 🔄 Real-Time Operations
|
|
284
|
+
|
|
285
|
+
### Monitor Order Updates
|
|
286
|
+
```typescript
|
|
287
|
+
async function monitorOrderUpdates(storeId: string) {
|
|
288
|
+
const client = new WashdayClient('your-token');
|
|
289
|
+
|
|
290
|
+
// Poll for new orders every 30 seconds
|
|
291
|
+
setInterval(async () => {
|
|
292
|
+
try {
|
|
293
|
+
const recentOrders = await client.orders.getList({
|
|
294
|
+
storeId,
|
|
295
|
+
fromDate: new Date(Date.now() - 30000).toISOString(), // Last 30 seconds
|
|
296
|
+
status: 'pending'
|
|
297
|
+
});
|
|
298
|
+
|
|
299
|
+
if (recentOrders.data.length > 0) {
|
|
300
|
+
console.log(`${recentOrders.data.length} new orders received`);
|
|
301
|
+
|
|
302
|
+
// Process each new order
|
|
303
|
+
for (const order of recentOrders.data) {
|
|
304
|
+
console.log(`New order: ${order.sequence} - ${order.customer.name}`);
|
|
305
|
+
// Auto-accept order
|
|
306
|
+
await client.orders.setOrderAcceptedBySequence(order.sequence, storeId);
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
} catch (error) {
|
|
310
|
+
console.error('Error monitoring orders:', error.message);
|
|
311
|
+
}
|
|
312
|
+
}, 30000);
|
|
313
|
+
}
|
|
314
|
+
```
|
|
315
|
+
|
|
316
|
+
### Sync Inventory Levels
|
|
317
|
+
```typescript
|
|
318
|
+
async function syncInventoryLevels(storeId: string) {
|
|
319
|
+
const client = new WashdayClient('your-token');
|
|
320
|
+
|
|
321
|
+
// Get current inventory
|
|
322
|
+
const inventory = await client.inventory.getInventory(storeId);
|
|
323
|
+
|
|
324
|
+
// Check for low stock items
|
|
325
|
+
const lowStockItems = inventory.data.filter(item =>
|
|
326
|
+
item.stock <= item.alertOnStock
|
|
327
|
+
);
|
|
328
|
+
|
|
329
|
+
if (lowStockItems.length > 0) {
|
|
330
|
+
console.log('Low stock alert:');
|
|
331
|
+
lowStockItems.forEach(item => {
|
|
332
|
+
console.log(`${item.product.name}: ${item.stock} units (Alert level: ${item.alertOnStock})`);
|
|
333
|
+
});
|
|
334
|
+
|
|
335
|
+
// Optionally add stock automatically
|
|
336
|
+
for (const item of lowStockItems) {
|
|
337
|
+
await client.inventory.addStock(storeId, item._id, {
|
|
338
|
+
newStock: item.alertOnStock * 2, // Restock to double the alert level
|
|
339
|
+
date: new Date().toISOString()
|
|
340
|
+
});
|
|
341
|
+
console.log(`Restocked ${item.product.name}`);
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
```
|
|
346
|
+
|
|
347
|
+
## 🚨 Error Handling Patterns
|
|
348
|
+
|
|
349
|
+
### Robust API Calls with Retry Logic
|
|
350
|
+
```typescript
|
|
351
|
+
async function robustApiCall<T>(
|
|
352
|
+
apiCall: () => Promise<T>,
|
|
353
|
+
maxRetries: number = 3,
|
|
354
|
+
delay: number = 1000
|
|
355
|
+
): Promise<T> {
|
|
356
|
+
for (let attempt = 1; attempt <= maxRetries; attempt++) {
|
|
357
|
+
try {
|
|
358
|
+
return await apiCall();
|
|
359
|
+
} catch (error) {
|
|
360
|
+
console.log(`Attempt ${attempt} failed:`, error.message);
|
|
361
|
+
|
|
362
|
+
if (attempt === maxRetries) {
|
|
363
|
+
throw error;
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
// Wait before retrying
|
|
367
|
+
await new Promise(resolve => setTimeout(resolve, delay * attempt));
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
throw new Error('All retries failed');
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
// Usage
|
|
374
|
+
const orders = await robustApiCall(() =>
|
|
375
|
+
client.orders.getList({ storeId: 'store-id' })
|
|
376
|
+
);
|
|
377
|
+
```
|
|
378
|
+
|
|
379
|
+
### Batch Operations with Error Handling
|
|
380
|
+
```typescript
|
|
381
|
+
async function processBatchWithErrorHandling<T>(
|
|
382
|
+
items: T[],
|
|
383
|
+
processor: (item: T) => Promise<void>,
|
|
384
|
+
batchSize: number = 10
|
|
385
|
+
) {
|
|
386
|
+
const results = [];
|
|
387
|
+
|
|
388
|
+
for (let i = 0; i < items.length; i += batchSize) {
|
|
389
|
+
const batch = items.slice(i, i + batchSize);
|
|
390
|
+
|
|
391
|
+
const batchPromises = batch.map(async (item, index) => {
|
|
392
|
+
try {
|
|
393
|
+
await processor(item);
|
|
394
|
+
return { success: true, item, error: null };
|
|
395
|
+
} catch (error) {
|
|
396
|
+
console.error(`Failed to process item ${i + index}:`, error.message);
|
|
397
|
+
return { success: false, item, error: error.message };
|
|
398
|
+
}
|
|
399
|
+
});
|
|
400
|
+
|
|
401
|
+
const batchResults = await Promise.all(batchPromises);
|
|
402
|
+
results.push(...batchResults);
|
|
403
|
+
|
|
404
|
+
// Optional delay between batches
|
|
405
|
+
if (i + batchSize < items.length) {
|
|
406
|
+
await new Promise(resolve => setTimeout(resolve, 100));
|
|
407
|
+
}
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
return results;
|
|
411
|
+
}
|
|
412
|
+
```
|
|
413
|
+
|
|
414
|
+
## 🔧 Performance Optimization
|
|
415
|
+
|
|
416
|
+
### Pagination Helper
|
|
417
|
+
```typescript
|
|
418
|
+
async function getAllPages<T>(
|
|
419
|
+
fetcher: (pageNum: string, limit: string) => Promise<{ data: T[], totalPages: number }>,
|
|
420
|
+
limit: number = 50
|
|
421
|
+
): Promise<T[]> {
|
|
422
|
+
const allItems: T[] = [];
|
|
423
|
+
let currentPage = 1;
|
|
424
|
+
let totalPages = 1;
|
|
425
|
+
|
|
426
|
+
do {
|
|
427
|
+
const response = await fetcher(currentPage.toString(), limit.toString());
|
|
428
|
+
allItems.push(...response.data);
|
|
429
|
+
totalPages = response.totalPages;
|
|
430
|
+
currentPage++;
|
|
431
|
+
} while (currentPage <= totalPages);
|
|
432
|
+
|
|
433
|
+
return allItems;
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
// Usage
|
|
437
|
+
const allOrders = await getAllPages((page, limit) =>
|
|
438
|
+
client.orders.getList({
|
|
439
|
+
storeId: 'store-id',
|
|
440
|
+
pageNum: page,
|
|
441
|
+
limit
|
|
442
|
+
})
|
|
443
|
+
);
|
|
444
|
+
```
|
|
445
|
+
|
|
446
|
+
### Caching Wrapper
|
|
447
|
+
```typescript
|
|
448
|
+
class CachedWashdayClient {
|
|
449
|
+
private client: WashdayClient;
|
|
450
|
+
private cache: Map<string, { data: any, expiry: number }> = new Map();
|
|
451
|
+
private defaultTtl: number = 5 * 60 * 1000; // 5 minutes
|
|
452
|
+
|
|
453
|
+
constructor(token: string) {
|
|
454
|
+
this.client = new WashdayClient(token);
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
async getWithCache<T>(
|
|
458
|
+
key: string,
|
|
459
|
+
fetcher: () => Promise<T>,
|
|
460
|
+
ttl: number = this.defaultTtl
|
|
461
|
+
): Promise<T> {
|
|
462
|
+
const cached = this.cache.get(key);
|
|
463
|
+
|
|
464
|
+
if (cached && cached.expiry > Date.now()) {
|
|
465
|
+
return cached.data;
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
const data = await fetcher();
|
|
469
|
+
this.cache.set(key, {
|
|
470
|
+
data,
|
|
471
|
+
expiry: Date.now() + ttl
|
|
472
|
+
});
|
|
473
|
+
|
|
474
|
+
return data;
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
async getStoreById(storeId: string) {
|
|
478
|
+
return this.getWithCache(
|
|
479
|
+
`store:${storeId}`,
|
|
480
|
+
() => this.client.stores.getStoreById(storeId),
|
|
481
|
+
10 * 60 * 1000 // 10 minutes for store data
|
|
482
|
+
);
|
|
483
|
+
}
|
|
484
|
+
}
|
|
485
|
+
```
|
|
486
|
+
|
|
487
|
+
These examples should cover most common scenarios you'll encounter when building applications with the Washday SDK. Each example includes proper error handling and follows best practices for production use.
|
|
@@ -0,0 +1,237 @@
|
|
|
1
|
+
# 🚀 Getting Started
|
|
2
|
+
|
|
3
|
+
This guide will help you get up and running with the Washday SDK in just a few minutes.
|
|
4
|
+
|
|
5
|
+
## 📦 Installation
|
|
6
|
+
|
|
7
|
+
### NPM
|
|
8
|
+
```bash
|
|
9
|
+
npm install washday-sdk
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
### Yarn
|
|
13
|
+
```bash
|
|
14
|
+
yarn add washday-sdk
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
### CDN (Browser)
|
|
18
|
+
```html
|
|
19
|
+
<script src="https://unpkg.com/washday-sdk@latest/dist/index.js"></script>
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
## 🔑 Authentication
|
|
23
|
+
|
|
24
|
+
Before using the SDK, you'll need an API token from your Washday dashboard.
|
|
25
|
+
|
|
26
|
+
### Getting Your API Token
|
|
27
|
+
1. Log into your Washday admin panel
|
|
28
|
+
2. Navigate to **Settings** > **API Keys**
|
|
29
|
+
3. Generate a new API token
|
|
30
|
+
4. Copy the token (keep it secure!)
|
|
31
|
+
|
|
32
|
+
### Initialize the Client
|
|
33
|
+
|
|
34
|
+
```typescript
|
|
35
|
+
import { WashdayClient } from 'washday-sdk';
|
|
36
|
+
|
|
37
|
+
const client = new WashdayClient('your-api-token-here');
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
## 🎯 First API Call
|
|
41
|
+
|
|
42
|
+
Let's make your first API call to check if everything is working:
|
|
43
|
+
|
|
44
|
+
```typescript
|
|
45
|
+
import { WashdayClient } from 'washday-sdk';
|
|
46
|
+
|
|
47
|
+
async function testConnection() {
|
|
48
|
+
const client = new WashdayClient('your-api-token');
|
|
49
|
+
|
|
50
|
+
try {
|
|
51
|
+
// Get your stores
|
|
52
|
+
const stores = await client.stores.getStores({ isActive: 'true' });
|
|
53
|
+
console.log('Connected! Your stores:', stores.data);
|
|
54
|
+
} catch (error) {
|
|
55
|
+
console.error('Connection failed:', error.message);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
testConnection();
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
## 🏢 Common Setup Patterns
|
|
63
|
+
|
|
64
|
+
### Single Store Application
|
|
65
|
+
```typescript
|
|
66
|
+
const client = new WashdayClient('your-api-token');
|
|
67
|
+
const STORE_ID = 'your-store-id';
|
|
68
|
+
|
|
69
|
+
// Now you can use STORE_ID in all store-specific calls
|
|
70
|
+
const orders = await client.orders.getList({ storeId: STORE_ID });
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
### Multi-Store Application
|
|
74
|
+
```typescript
|
|
75
|
+
const client = new WashdayClient('your-api-token');
|
|
76
|
+
|
|
77
|
+
// Get all active stores first
|
|
78
|
+
const stores = await client.stores.getStores({ isActive: 'true' });
|
|
79
|
+
|
|
80
|
+
// Use stores dynamically
|
|
81
|
+
for (const store of stores.data) {
|
|
82
|
+
const orders = await client.orders.getList({ storeId: store._id });
|
|
83
|
+
console.log(`${store.name} has ${orders.data.length} orders`);
|
|
84
|
+
}
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
### Environment Configuration
|
|
88
|
+
```typescript
|
|
89
|
+
// Use environment variables for security
|
|
90
|
+
const client = new WashdayClient(process.env.WASHDAY_API_TOKEN);
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
## 📝 Basic Examples
|
|
94
|
+
|
|
95
|
+
### Customer Management
|
|
96
|
+
```typescript
|
|
97
|
+
// Create a new customer
|
|
98
|
+
const newCustomer = await client.customers.create({
|
|
99
|
+
name: 'John Doe',
|
|
100
|
+
email: 'john@example.com',
|
|
101
|
+
phone: '+1234567890',
|
|
102
|
+
isActive: true
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
// Get customer by ID
|
|
106
|
+
const customer = await client.customers.getCustomerById(newCustomer.data._id);
|
|
107
|
+
|
|
108
|
+
// Update customer
|
|
109
|
+
await client.customers.updateById(customer.data._id, {
|
|
110
|
+
name: 'John Smith'
|
|
111
|
+
});
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
### Order Processing
|
|
115
|
+
```typescript
|
|
116
|
+
// Get pending orders
|
|
117
|
+
const pendingOrders = await client.orders.getList({
|
|
118
|
+
storeId: 'your-store-id',
|
|
119
|
+
status: 'pending'
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
// Update order status
|
|
123
|
+
await client.orders.setOrderAcceptedBySequence(
|
|
124
|
+
'ORDER-123',
|
|
125
|
+
'your-store-id'
|
|
126
|
+
);
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
### Employee Attendance
|
|
130
|
+
```typescript
|
|
131
|
+
// Clock in employee
|
|
132
|
+
await client.attendance.clockIn({
|
|
133
|
+
storeId: 'your-store-id',
|
|
134
|
+
notes: 'Starting morning shift'
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
// Check current status
|
|
138
|
+
const status = await client.attendance.getStatus();
|
|
139
|
+
console.log('Currently clocked in:', status.active);
|
|
140
|
+
|
|
141
|
+
// Clock out
|
|
142
|
+
await client.attendance.clockOut({
|
|
143
|
+
notes: 'End of shift'
|
|
144
|
+
});
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
## 🔧 TypeScript Support
|
|
148
|
+
|
|
149
|
+
The SDK is built with TypeScript and provides full type definitions:
|
|
150
|
+
|
|
151
|
+
```typescript
|
|
152
|
+
import { WashdayClient, ICustomer, IOrder } from 'washday-sdk';
|
|
153
|
+
|
|
154
|
+
const client = new WashdayClient('your-token');
|
|
155
|
+
|
|
156
|
+
// Types are automatically inferred
|
|
157
|
+
const customer: ICustomer = await client.customers.getCustomerById('customer-id');
|
|
158
|
+
const orders: IOrder[] = await client.orders.getList({ storeId: 'store-id' });
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
## 🚨 Error Handling
|
|
162
|
+
|
|
163
|
+
Always wrap your API calls in try-catch blocks:
|
|
164
|
+
|
|
165
|
+
```typescript
|
|
166
|
+
try {
|
|
167
|
+
const result = await client.customers.create({
|
|
168
|
+
name: 'John Doe',
|
|
169
|
+
email: 'invalid-email' // This will cause a validation error
|
|
170
|
+
});
|
|
171
|
+
} catch (error) {
|
|
172
|
+
if (error.response) {
|
|
173
|
+
// API returned an error response
|
|
174
|
+
console.error('API Error:', error.response.status);
|
|
175
|
+
console.error('Details:', error.response.data.errors);
|
|
176
|
+
} else {
|
|
177
|
+
// Network or other error
|
|
178
|
+
console.error('Network Error:', error.message);
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
## 🎛️ Configuration Options
|
|
184
|
+
|
|
185
|
+
### Request Timeout
|
|
186
|
+
```typescript
|
|
187
|
+
// Configure axios defaults (the SDK uses axios internally)
|
|
188
|
+
import axios from 'axios';
|
|
189
|
+
|
|
190
|
+
axios.defaults.timeout = 10000; // 10 seconds
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
### Base URL (for self-hosted instances)
|
|
194
|
+
```typescript
|
|
195
|
+
import axiosInstance from 'washday-sdk/dist/api/axiosInstance';
|
|
196
|
+
|
|
197
|
+
// Only needed if you're using a self-hosted Washday instance
|
|
198
|
+
axiosInstance.defaults.baseURL = 'https://your-washday-instance.com';
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
## 📚 Next Steps
|
|
202
|
+
|
|
203
|
+
Now that you're set up, explore specific modules:
|
|
204
|
+
|
|
205
|
+
- [**Attendance Module**](./modules/attendance.md) - Employee time tracking
|
|
206
|
+
- [**Orders Module**](./modules/orders.md) - Order management
|
|
207
|
+
- [**Customers Module**](./modules/customers.md) - Customer data
|
|
208
|
+
- [**Common Examples**](./examples/common-use-cases.md) - Real-world scenarios
|
|
209
|
+
|
|
210
|
+
## 🆘 Troubleshooting
|
|
211
|
+
|
|
212
|
+
### Common Issues
|
|
213
|
+
|
|
214
|
+
**Invalid API Token**
|
|
215
|
+
```
|
|
216
|
+
Error: Request failed with status code 401
|
|
217
|
+
```
|
|
218
|
+
Solution: Check that your API token is correct and active.
|
|
219
|
+
|
|
220
|
+
**Store Not Found**
|
|
221
|
+
```
|
|
222
|
+
Error: Request failed with status code 400
|
|
223
|
+
Details: ["Store ID is required"]
|
|
224
|
+
```
|
|
225
|
+
Solution: Ensure you're passing a valid `storeId` parameter.
|
|
226
|
+
|
|
227
|
+
**Network Issues**
|
|
228
|
+
```
|
|
229
|
+
Error: Network Error
|
|
230
|
+
```
|
|
231
|
+
Solution: Check your internet connection and firewall settings.
|
|
232
|
+
|
|
233
|
+
### Getting Help
|
|
234
|
+
|
|
235
|
+
- 📖 Check the specific module documentation
|
|
236
|
+
- 🔍 Look at the [examples](./examples/) folder
|
|
237
|
+
- 💬 Contact support with your API logs
|