@shisyamo4131/air-guard-v2-schemas 1.0.0

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.
Files changed (38) hide show
  1. package/index.js +15 -0
  2. package/package.json +44 -0
  3. package/src/Agreement.js +262 -0
  4. package/src/ArrangementNotification.js +505 -0
  5. package/src/Billing.js +159 -0
  6. package/src/Company.js +176 -0
  7. package/src/Customer.js +98 -0
  8. package/src/Employee.js +201 -0
  9. package/src/Operation.js +779 -0
  10. package/src/OperationBilling.js +193 -0
  11. package/src/OperationDetail.js +147 -0
  12. package/src/OperationResult.js +437 -0
  13. package/src/OperationResultDetail.js +72 -0
  14. package/src/Outsourcer.js +46 -0
  15. package/src/RoundSetting.js +123 -0
  16. package/src/Site.js +192 -0
  17. package/src/SiteOperationSchedule.js +503 -0
  18. package/src/SiteOperationScheduleDetail.js +99 -0
  19. package/src/SiteOrder.js +62 -0
  20. package/src/Tax.js +39 -0
  21. package/src/User.js +41 -0
  22. package/src/WorkingResult.js +297 -0
  23. package/src/apis/index.js +9 -0
  24. package/src/constants/arrangement-notification-status.js +68 -0
  25. package/src/constants/billing-unit-type.js +15 -0
  26. package/src/constants/contract-status.js +15 -0
  27. package/src/constants/day-type.js +44 -0
  28. package/src/constants/employment-status.js +15 -0
  29. package/src/constants/gender.js +11 -0
  30. package/src/constants/index.js +9 -0
  31. package/src/constants/prefectures.js +56 -0
  32. package/src/constants/shift-type.js +20 -0
  33. package/src/constants/site-status.js +15 -0
  34. package/src/parts/accessorDefinitions.js +109 -0
  35. package/src/parts/fieldDefinitions.js +642 -0
  36. package/src/utils/ContextualError.js +49 -0
  37. package/src/utils/CutoffDate.js +223 -0
  38. package/src/utils/index.js +48 -0
@@ -0,0 +1,437 @@
1
+ /*****************************************************************************
2
+ * OperationResult Model ver 1.0.0
3
+ * @author shisyamo4131
4
+ * ---------------------------------------------------------------------------
5
+ * - Extends Operation class to represent the result of an operation.
6
+ * - Also incorporates Agreement class properties for pricing and billing information.
7
+ * - Prevents deletion if the instance has `siteOperationScheduleId`.
8
+ * - Provides comprehensive billing calculations including statistics, sales amounts, and tax.
9
+ * - Supports both daily and hourly billing with adjusted quantities.
10
+ * ---------------------------------------------------------------------------
11
+ * @props {string|null} siteOperationScheduleId - Associated SiteOperationSchedule document ID
12
+ * - If this OperationResult was created from a SiteOperationSchedule, this property holds that ID.
13
+ * - If this property is set, the instance cannot be deleted.
14
+ * @props {boolean} useAdjustedQuantity - Flag to indicate if adjusted quantities are used for billing
15
+ * @props {number} adjustedQuantityBase - Adjusted quantity for base workers
16
+ * - Quantity used for billing base workers when `useAdjustedQuantity` is true.
17
+ * @props {number} adjustedOvertimeBase - Adjusted overtime for base workers
18
+ * - Overtime used for billing base workers when `useAdjustedQuantity` is true.
19
+ * @props {number} adjustedQuantityQualified - Adjusted quantity for qualified workers
20
+ * - Quantity used for billing qualified workers when `useAdjustedQuantity` is true.
21
+ * @props {number} adjustedOvertimeQualified - Adjusted overtime for qualified workers
22
+ * - Overtime used for billing qualified workers when `useAdjustedQuantity` is true.
23
+ * @props {Date} billingDateAt - Billing date
24
+ * ---------------------------------------------------------------------------
25
+ * @computed {Object} statistics - Statistics of workers (read-only)
26
+ * - Contains counts and total work minutes for base and qualified workers, including OJT breakdowns.
27
+ * - Structure: { base: {...}, qualified: {...}, total: {...} }
28
+ * - Each category contains: quantity, regularTimeWorkMinutes, overtimeWorkMinutes, totalWorkMinutes, breakMinutes
29
+ * - Each category also has an 'ojt' subcategory with the same structure.
30
+ * @computed {Object} sales - Sales amounts (read-only)
31
+ * - Contains sales calculations for base and qualified workers, including overtime breakdowns.
32
+ * - Structure: { base: {...}, qualified: {...} }
33
+ * - Each category contains: unitPrice, quantity, regularAmount, overtimeUnitPrice, overtimeMinutes, overtimeAmount, total
34
+ * - Calculations respect `useAdjustedQuantity`, `billingUnitType`, and `includeBreakInBilling` settings.
35
+ * @computed {number} salesAmount - Total sales amount (read-only)
36
+ * - Sum of sales amounts for base and qualified workers with rounding applied.
37
+ * @computed {number} tax - Calculated tax amount (read-only)
38
+ * - Calculated using the `Tax` utility based on `salesAmount` and `date`.
39
+ * @computed {number} billingAmount - Total billing amount including tax (read-only)
40
+ * - Sum of `salesAmount` and `tax`.
41
+ * ---------------------------------------------------------------------------
42
+ * @inherited - The following properties are inherited from Operation:
43
+ * @props {string} siteId - Site document ID (trigger property)
44
+ * - Automatically synchronizes to all `employees` and `outsourcers` when changed.
45
+ * @props {number} requiredPersonnel - Required number of personnel
46
+ * @props {boolean} qualificationRequired - Qualification required flag
47
+ * @props {string} workDescription - Work description
48
+ * @props {string} remarks - Remarks
49
+ * @props {Array<OperationResultDetail>} employees - Assigned employees
50
+ * - Array of `OperationResultDetail` instances representing assigned employees
51
+ * @props {Array<OperationResultDetail>} outsourcers - Assigned outsourcers
52
+ * - Array of `OperationResultDetail` instances representing assigned outsourcers
53
+ * ---------------------------------------------------------------------------
54
+ * @inherited - The following properties are inherited from Agreement (via Operation):
55
+ * @props {number} unitPriceBase - Base unit price (JPY)
56
+ * @props {number} overtimeUnitPriceBase - Overtime unit price (JPY/hour)
57
+ * @props {number} unitPriceQualified - Qualified unit price (JPY)
58
+ * @props {number} overtimeUnitPriceQualified - Qualified overtime unit price (JPY/hour)
59
+ * @props {string} billingUnitType - Billing unit type
60
+ * @props {boolean} includeBreakInBilling - Whether to include break time in billing if `billingUnitType` is `PER_HOUR`.
61
+ * @props {number} cutoffDate - Cutoff date value from CutoffDate.VALUES
62
+ * - The cutoff date for billing, using values defined in the CutoffDate utility class.
63
+ * ---------------------------------------------------------------------------
64
+ * @inherited - The following properties are inherited from WorkingResult (via Operation):
65
+ * @props {Date} dateAt - Date of operation (placement date) (trigger property)
66
+ * - Automatically synchronizes to all `employees` and `outsourcers` when changed.
67
+ * @props {string} dayType - Day type (e.g., `WEEKDAY`, `WEEKEND`, `HOLIDAY`)
68
+ * @props {string} shiftType - `DAY` or `NIGHT` (trigger property)
69
+ * - Automatically synchronizes to all `employees` and `outsourcers` when changed.
70
+ * @props {string} startTime - Start time (HH:MM format)
71
+ * @props {boolean} isStartNextDay - Next day start flag
72
+ * - `true` if the actual work starts the day after the placement date `dateAt`
73
+ * @props {string} endTime - End time (HH:MM format)
74
+ * @props {number} breakMinutes - Break time (minutes)
75
+ * @props {number} regulationWorkMinutes - Regulation work minutes (trigger property)
76
+ * - Indicates the maximum working time treated as regular working hours.
77
+ * - Automatically synchronizes to all `employees` and `outsourcers` when changed.
78
+ * ---------------------------------------------------------------------------
79
+ * @inherited - The following computed properties are inherited from Operation:
80
+ * @computed {Array<string>} employeeIds - Array of employee IDs from `employees` (read-only)
81
+ * @computed {Array<string>} outsourcerIds - Array of outsourcer IDs from `outsourcers` (read-only)
82
+ * @computed {number} employeesCount - Count of assigned employees (read-only)
83
+ * @computed {number} outsourcersCount - Count of assigned outsourcers (sum of amounts) (read-only)
84
+ * @computed {boolean} isPersonnelShortage - Indicates if there is a shortage of personnel (read-only)
85
+ * - `true` if the sum of `employeesCount` and `outsourcersCount` is less than `requiredPersonnel`
86
+ * @computed {Array<OperationResultDetail>} workers - Combined array of `employees` and `outsourcers`
87
+ * - Getter: Returns concatenated array of employees and outsourcers
88
+ * - Setter: Splits array into employees and outsourcers based on `isEmployee` property
89
+ * ---------------------------------------------------------------------------
90
+ * @inherited - The following computed properties are inherited from WorkingResult (via Operation):
91
+ * @computed {string} date - Date string in YYYY-MM-DD format based on `dateAt` (read-only)
92
+ * - Returns a string in the format YYYY-MM-DD based on `dateAt`.
93
+ * @computed {Date} startAt - Start date and time (Date object) (read-only)
94
+ * - Returns a Date object with `startTime` set based on `dateAt`.
95
+ * - If `isStartNextDay` is true, add 1 day.
96
+ * @computed {Date} endAt - End date and time (Date object) (read-only)
97
+ * - Returns a Date object with `endTime` set based on `dateAt`.
98
+ * - If `isStartNextDay` is true, add 1 day.
99
+ * - If `isSpansNextDay` is true, add 1 day.
100
+ * @computed {boolean} isSpansNextDay - Flag indicating whether the date spans from start date to end date (read-only)
101
+ * - `true` if `startTime` is later than `endTime`
102
+ * @computed {number} totalWorkMinutes - Total working time in minutes (excluding break time) (read-only)
103
+ * - Calculated as the difference between `endAt` and `startAt` minus `breakMinutes`
104
+ * @computed {number} regularTimeWorkMinutes - Regular working time in minutes (read-only)
105
+ * - The portion of `totalWorkMinutes` that is considered within the contract's `regulationWorkMinutes`.
106
+ * @computed {number} overtimeWorkMinutes - Overtime work in minutes (read-only)
107
+ * - Calculated as `totalWorkMinutes` minus `regulationWorkMinutes`
108
+ * ---------------------------------------------------------------------------
109
+ * @inherited - The following getter properties are inherited from Operation:
110
+ * @getter {string} groupKey - Combines `siteId`, `shiftType`, and `date` to indicate operation grouping (read-only)
111
+ * @getter {boolean} isEmployeesChanged - Indicates whether the employees have changed (read-only)
112
+ * - Returns true if the employee IDs have changed compared to `_beforeData`
113
+ * @getter {boolean} isOutsourcersChanged - Indicates whether the outsourcers have changed (read-only)
114
+ * - Returns true if the outsourcer IDs have changed compared to `_beforeData`
115
+ * @getter {Array<OperationResultDetail>} addedWorkers - An array of workers that have been added (read-only)
116
+ * - Workers that exist in current data but not in `_beforeData`
117
+ * @getter {Array<OperationResultDetail>} removedWorkers - An array of workers that have been removed (read-only)
118
+ * - Workers that exist in `_beforeData` but not in current data
119
+ * @getter {Array<OperationResultDetail>} updatedWorkers - An array of workers that have been updated (read-only)
120
+ * - Workers whose `startTime`, `isStartNextDay`, `endTime`, `breakMinutes`, `isQualified`, or `isOjt` have changed
121
+ * ---------------------------------------------------------------------------
122
+ * @inherited - The following getter properties are inherited from WorkingResult (via Operation):
123
+ * @getter {number} startHour - Start hour (0-23) (read-only)
124
+ * - Extracted from `startTime`.
125
+ * @getter {number} startMinute - Start minute (0-59) (read-only)
126
+ * - Extracted from `startTime`.
127
+ * @getter {number} endHour - End hour (0-23) (read-only)
128
+ * - Extracted from `endTime`.
129
+ * @getter {number} endMinute - End minute (0-59) (read-only)
130
+ * - Extracted from `endTime`.
131
+ * ---------------------------------------------------------------------------
132
+ * @method {function} beforeDelete - Override method to prevent deletion with siteOperationScheduleId
133
+ * - Prevents deletion if the instance has `siteOperationScheduleId`.
134
+ * - Throws an error if deletion is attempted on an instance created from SiteOperationSchedule.
135
+ * ---------------------------------------------------------------------------
136
+ * @inherited - The following methods are inherited from Operation:
137
+ * @method {function} addWorker - Adds a new worker (employee or outsourcer)
138
+ * - @param {Object} options - Options for adding a worker
139
+ * - @param {string} options.id - The worker ID (employeeId or outsourcerId)
140
+ * - @param {boolean} [options.isEmployee=true] - Whether the worker is an employee
141
+ * - @param {number} [index=0] - Insertion position. If -1, adds to the end
142
+ * @method {function} moveWorker - Moves the position of a worker (employee or outsourcer)
143
+ * - @param {Object} options - Options for changing worker position
144
+ * - @param {number} options.oldIndex - The original index
145
+ * - @param {number} options.newIndex - The new index
146
+ * - @param {boolean} [options.isEmployee=true] - True for employee, false for outsourcer
147
+ * @method {function} changeWorker - Changes the details of a worker
148
+ * - @param {Object} newWorker - New worker object
149
+ * @method {function} removeWorker - Removes a worker (employee or outsourcer)
150
+ * - @param {Object} options - Options for removing a worker
151
+ * - @param {string} options.workerId - The ID of the employee or outsourcer
152
+ * - @param {boolean} [options.isEmployee=true] - True for employee, false for outsourcer
153
+ * @method {function} setSiteIdCallback - Callback method called when `siteId` is set
154
+ * - Override this method in subclasses to add custom behavior when `siteId` changes.
155
+ * - By default, does nothing.
156
+ * - @param {string} v - The new `siteId` value
157
+ * @method {function} setShiftTypeCallback - Callback method called when `shiftType` is set
158
+ * - Override this method in subclasses to add custom behavior when `shiftType` changes.
159
+ * - By default, does nothing.
160
+ * - @param {string} v - The new `shiftType` value
161
+ * @method {function} setRegulationWorkMinutesCallback - Callback method called when `regulationWorkMinutes` is set
162
+ * - Override this method in subclasses to add custom behavior when `regulationWorkMinutes` changes.
163
+ * - By default, does nothing.
164
+ * - @param {number} v - The new `regulationWorkMinutes` value
165
+ * @static
166
+ * @method groupKeyDivider
167
+ * Returns an array dividing the key into siteId, shiftType, and date.
168
+ * @param {Object|string} key - The combined key string or object
169
+ * @returns {Array<string>} - Array containing [siteId, shiftType, date]
170
+ * @throws {Error} - If the key is invalid.
171
+ * ---------------------------------------------------------------------------
172
+ * @inherited - The following method is inherited from WorkingResult (via Operation):
173
+ * @method {function} setDateAtCallback - Callback method called when `dateAt` is set
174
+ * - Override this method in subclasses to add custom behavior when `dateAt` changes.
175
+ * - By default, updates `dayType` based on the new `dateAt` value and synchronizes to workers.
176
+ * - @param {Date} v - The new `dateAt` value
177
+ *****************************************************************************/
178
+ import Operation from "./Operation.js";
179
+ import Agreement from "./Agreement.js";
180
+ import { ContextualError } from "./utils/ContextualError.js";
181
+ import OperationResultDetail from "./OperationResultDetail.js";
182
+ import { defField } from "./parts/fieldDefinitions.js";
183
+ import Tax from "./tax.js";
184
+ import { BILLING_UNIT_TYPE_PER_HOUR } from "./constants/billing-unit-type.js";
185
+ import RoundSetting from "./RoundSetting.js";
186
+ import CutoffDate from "./utils/CutoffDate.js";
187
+
188
+ const classProps = {
189
+ ...Operation.classProps,
190
+ ...Agreement.classProps,
191
+ cutoffDate: defField("select", {
192
+ label: "締日区分",
193
+ default: CutoffDate.VALUES.END_OF_MONTH,
194
+ required: true,
195
+ hidden: true,
196
+ component: {
197
+ attrs: {
198
+ items: CutoffDate.OPTIONS,
199
+ },
200
+ },
201
+ }),
202
+ siteOperationScheduleId: defField("oneLine", { hidden: true }),
203
+ useAdjustedQuantity: defField("check", {
204
+ label: "調整数量を使用",
205
+ default: false,
206
+ }),
207
+ adjustedQuantityBase: defField("number", {
208
+ label: "基本人工(調整)",
209
+ default: 0,
210
+ }),
211
+ adjustedOvertimeBase: defField("number", {
212
+ label: "基本残業(調整)",
213
+ default: 0,
214
+ }),
215
+ adjustedQuantityQualified: defField("number", {
216
+ label: "資格人工(調整)",
217
+ default: 0,
218
+ }),
219
+ adjustedOvertimeQualified: defField("number", {
220
+ label: "資格残業(調整)",
221
+ default: 0,
222
+ }),
223
+ billingDateAt: defField("dateAt", { label: "請求日付", required: true }),
224
+ employees: defField("array", { customClass: OperationResultDetail }),
225
+ outsourcers: defField("array", {
226
+ customClass: OperationResultDetail,
227
+ }),
228
+ };
229
+
230
+ export default class OperationResult extends Operation {
231
+ static className = "稼働実績";
232
+ static collectionPath = "OperationResults";
233
+ static useAutonumber = false;
234
+ static logicalDelete = false;
235
+ static classProps = classProps;
236
+
237
+ static headers = [
238
+ { title: "日付", key: "dateAt" },
239
+ { title: "現場", key: "siteId", value: "siteId" },
240
+ ];
241
+
242
+ /**
243
+ * afterInitialize
244
+ */
245
+ afterInitialize() {
246
+ super.afterInitialize();
247
+
248
+ /** Computed properties */
249
+ Object.defineProperties(this, {
250
+ statistics: {
251
+ configurable: true,
252
+ enumerable: true,
253
+ get() {
254
+ const initialValues = {
255
+ quantity: 0,
256
+ regularTimeWorkMinutes: 0,
257
+ overtimeWorkMinutes: 0,
258
+ totalWorkMinutes: 0,
259
+ breakMinutes: 0,
260
+ };
261
+ const result = {
262
+ base: { ...initialValues, ojt: { ...initialValues } },
263
+ qualified: { ...initialValues, ojt: { ...initialValues } },
264
+ total: { ...initialValues, ojt: { ...initialValues } },
265
+ };
266
+
267
+ // 各カテゴリに値を追加する関数
268
+ const addToCategory = (categoryObj, worker, isOjt) => {
269
+ const target = isOjt ? categoryObj.ojt : categoryObj;
270
+ target.quantity += 1;
271
+ target.regularTimeWorkMinutes += worker.regularTimeWorkMinutes;
272
+ target.overtimeWorkMinutes += worker.overtimeWorkMinutes;
273
+ target.totalWorkMinutes += worker.totalWorkMinutes;
274
+ target.breakMinutes += worker.breakMinutes;
275
+ };
276
+
277
+ this.workers.forEach((worker) => {
278
+ const category = worker.isQualified ? "qualified" : "base";
279
+ const isOjt = worker.isOjt;
280
+
281
+ // 該当カテゴリ(base/qualified)に追加
282
+ addToCategory(result[category], worker, isOjt);
283
+
284
+ // 全体合計に追加
285
+ addToCategory(result.total, worker, isOjt);
286
+ });
287
+
288
+ return result;
289
+ },
290
+ set(v) {},
291
+ },
292
+ sales: {
293
+ configurable: true,
294
+ enumerable: true,
295
+ get() {
296
+ const createInitialValues = () => ({
297
+ unitPrice: 0,
298
+ quantity: 0,
299
+ regularAmount: 0,
300
+ overtimeUnitPrice: 0,
301
+ overtimeMinutes: 0,
302
+ overtimeAmount: 0,
303
+ total: 0,
304
+ });
305
+
306
+ const calculateCategorySales = (category) => {
307
+ const isQualified = category === "qualified";
308
+ const categoryStats = this.statistics?.[category];
309
+
310
+ // 統計データが存在しない場合は警告を出力して初期値を返す
311
+ if (!categoryStats) {
312
+ console.warn(
313
+ `[OperationResult] Statistics data for category '${category}' is missing.`,
314
+ {
315
+ docId: this.docId,
316
+ dateAt: this.dateAt,
317
+ siteId: this.siteId,
318
+ category,
319
+ statistics: this.statistics,
320
+ }
321
+ );
322
+ return createInitialValues();
323
+ }
324
+
325
+ const unitPrice = isQualified
326
+ ? this.unitPriceQualified || 0
327
+ : this.unitPriceBase || 0;
328
+ const overtimeUnitPrice = isQualified
329
+ ? this.overtimeUnitPriceQualified || 0
330
+ : this.overtimeUnitPriceBase || 0;
331
+ const isPerHour =
332
+ this.billingUnitType === BILLING_UNIT_TYPE_PER_HOUR;
333
+
334
+ const result = createInitialValues();
335
+
336
+ // 基本情報の設定
337
+ result.unitPrice = unitPrice;
338
+ result.overtimeUnitPrice = overtimeUnitPrice;
339
+
340
+ // 調整値の使用判定
341
+ if (this.useAdjustedQuantity) {
342
+ result.quantity = isQualified
343
+ ? this.adjustedQuantityQualified || 0
344
+ : this.adjustedQuantityBase || 0;
345
+ result.overtimeMinutes = isQualified
346
+ ? this.adjustedOvertimeQualified || 0
347
+ : this.adjustedOvertimeBase || 0;
348
+ } else {
349
+ // result.quantity = isPerHour
350
+ // ? (categoryStats.totalWorkMinutes || 0) / 60
351
+ // : categoryStats.quantity || 0;
352
+ // result.overtimeMinutes = categoryStats.overtimeWorkMinutes || 0;
353
+ if (isPerHour) {
354
+ // 時間単位請求の場合
355
+ let totalMinutes = categoryStats.totalWorkMinutes || 0;
356
+
357
+ // 休憩時間を請求に含める場合は休憩時間を追加
358
+ if (this.includeBreakInBilling) {
359
+ totalMinutes += categoryStats.breakMinutes || 0;
360
+ }
361
+
362
+ result.quantity = totalMinutes / 60;
363
+ } else {
364
+ // 日単位請求の場合(休憩時間は関係なし)
365
+ result.quantity = categoryStats.quantity || 0;
366
+ }
367
+ result.overtimeMinutes = categoryStats.overtimeWorkMinutes || 0;
368
+ }
369
+
370
+ // 金額計算(RoundSettingを適用)
371
+ result.regularAmount = RoundSetting.apply(
372
+ result.quantity * unitPrice
373
+ );
374
+ result.overtimeAmount = RoundSetting.apply(
375
+ (result.overtimeMinutes * overtimeUnitPrice) / 60
376
+ );
377
+ result.total = result.regularAmount + result.overtimeAmount;
378
+
379
+ return result;
380
+ };
381
+
382
+ const base = calculateCategorySales("base");
383
+ const qualified = calculateCategorySales("qualified");
384
+
385
+ return { base, qualified };
386
+ },
387
+ set(v) {},
388
+ },
389
+ salesAmount: {
390
+ configurable: true,
391
+ enumerable: true,
392
+ get() {
393
+ const amount = this.sales.base.total + this.sales.qualified.total;
394
+ return RoundSetting.apply(amount);
395
+ },
396
+ set(v) {},
397
+ },
398
+ tax: {
399
+ configurable: true,
400
+ enumerable: true,
401
+ get() {
402
+ try {
403
+ return Tax.calc(this.salesAmount, this.date);
404
+ } catch (error) {
405
+ throw new ContextualError("Failed to calculate tax", {
406
+ method: "OperationResult.tax (computed)",
407
+ arguments: { amount: this.salesAmount, date: this.date },
408
+ error,
409
+ });
410
+ }
411
+ },
412
+ set(v) {},
413
+ },
414
+ billingAmount: {
415
+ configurable: true,
416
+ enumerable: true,
417
+ get() {
418
+ return this.salesAmount + this.tax;
419
+ },
420
+ set(v) {},
421
+ },
422
+ });
423
+ }
424
+
425
+ /**
426
+ * Override `beforeDelete`.
427
+ * - Prevents deletion if the instance has `siteOperationScheduleId`.
428
+ */
429
+ async beforeDelete() {
430
+ await super.beforeDelete();
431
+ if (this.siteOperationScheduleId) {
432
+ throw new Error(
433
+ "この稼働実績は現場稼働予定から作成されているため、削除できません。"
434
+ );
435
+ }
436
+ }
437
+ }
@@ -0,0 +1,72 @@
1
+ /*****************************************************************************
2
+ * OperationResultDetail Model ver 1.0.0
3
+ * @author shisyamo4131
4
+ * ---------------------------------------------------------------------------
5
+ * - Model representing the details of an operation result.
6
+ * - Extends OperationDetail.
7
+ * ---------------------------------------------------------------------------
8
+ * @inherited - The following properties are inherited from OperationDetail:
9
+ * @props {string} id - Employee or Outsourcer document ID
10
+ * @props {number} index - Identifier index for Outsourcer (always 0 for Employee)
11
+ * @props {boolean} isEmployee - Employee flag (true: Employee, false: Outsourcer)
12
+ * @props {number} amount - Number of placements (always fixed at 1)
13
+ * @props {string} siteId - Site ID
14
+ * @props {boolean} isQualified - Qualified flag
15
+ * @props {boolean} isOjt - OJT flag
16
+ * @props {Date} dateAt - Placement date
17
+ * @props {string} dayType - Day type (e.g., `WEEKDAY`, `WEEKEND`, `HOLIDAY`)
18
+ * @props {string} shiftType - `DAY` or `NIGHT`
19
+ * @props {string} startTime - Start time (HH:MM format)
20
+ * @props {boolean} isStartNextDay - Next day start flag
21
+ * @props {string} endTime - End time (HH:MM format)
22
+ * @props {number} breakMinutes - Break time (minutes)
23
+ * @props {number} regulationWorkMinutes - Regulation work minutes
24
+ * --------------------------------------------------------------------------
25
+ * @inherited - The following computed properties are inherited from OperationDetail:
26
+ * @computed {string} workerId - Worker ID
27
+ * - For Employee, it's the same as `id`, for Outsourcer, it's a concatenation of `id` and `index` with ':'
28
+ * @computed {string|null} employeeId - Employee ID (null if not applicable)
29
+ * @computed {string|null} outsourcerId - Outsourcer ID (null if not applicable)
30
+ * @computed {number} overtimeWorkMinutes - Overtime work in minutes
31
+ * - Calculated as `totalWorkMinutes` minus `regulationWorkMinutes`
32
+ * - Overtime work is not negative; the minimum is 0.
33
+ * @computed {string} key - Unique key combining `date`, `dayType`, and `shiftType`
34
+ * @computed {string} date - Date string in YYYY-MM-DD format based on `dateAt`
35
+ * @computed {boolean} isSpansNextDay - Flag indicating whether the date spans from start date to end date
36
+ * @computed {Date} startAt - Start date and time (Date object)
37
+ * @computed {Date} endAt - End date and time (Date object)
38
+ * @computed {number} totalWorkMinutes - Total working time in minutes (excluding break time)
39
+ * @computed {number} regularTimeWorkMinutes - Regular working time in minutes
40
+ * --------------------------------------------------------------------------
41
+ * @inherited - The following accessor properties are inherited from OperationDetail:
42
+ * @accessor {number} startHour - Start hour (0-23)
43
+ * - Extracted from `startTime`.
44
+ * @accessor {number} startMinute - Start minute (0-59)
45
+ * - Extracted from `startTime`.
46
+ * @accessor {number} endHour - End hour (0-23)
47
+ * - Extracted from `endTime`.
48
+ * @accessor {number} endMinute - End minute (0-59)
49
+ * - Extracted from `endTime`.
50
+ * @accessor {number} breakHours - Break time in hours (converts to/from breakMinutes)
51
+ * - Accessor for break time in hours.
52
+ * @accessor {number} overtimeWorkHours - Overtime work in hours (converts to/from overtimeWorkMinutes)
53
+ * ---------------------------------------------------------------------------
54
+ * @inherited - The following method is inherited from WorkingResult:
55
+ * @method {function} setDateAtCallback - Callback method called when `dateAt` is set
56
+ * - Override this method in subclasses to add custom behavior when `dateAt` changes.
57
+ * - By default, updates `dayType` based on the new `dateAt` value.
58
+ * - @param {Date} v - The new `dateAt` value
59
+ *****************************************************************************/
60
+ import OperationDetail from "./OperationDetail.js";
61
+
62
+ const headers = [
63
+ { title: "名前", key: "displayName" },
64
+ { title: "開始", key: "startTime" },
65
+ { title: "終了", key: "endTime" },
66
+ { title: "休憩", key: "breakMinutes" },
67
+ { title: "残業", key: "overtimeWorkMinutes" },
68
+ ];
69
+ export default class OperationResultDetail extends OperationDetail {
70
+ static className = "稼働実績明細";
71
+ static headers = headers;
72
+ }
@@ -0,0 +1,46 @@
1
+ /**
2
+ * @file src/Outsourcer.js
3
+ * @author shisyamo4131
4
+ * @version 1.0.0
5
+ */
6
+ import FireModel from "@shisyamo4131/air-firebase-v2";
7
+ import { defField } from "./parts/fieldDefinitions.js";
8
+ import { VALUES } from "./constants/contract-status.js";
9
+
10
+ const classProps = {
11
+ code: defField("code", { label: "外注先コード" }),
12
+ name: defField("name", { required: true }),
13
+ nameKana: defField("nameKana", { required: true }),
14
+ displayName: defField("displayName", { label: "略称", required: true }),
15
+ contractStatus: defField("contractStatus", { required: true }),
16
+ remarks: defField("multipleLine", { label: "備考" }),
17
+ };
18
+
19
+ /**
20
+ * @extends FireModel
21
+ *
22
+ * @props {string} code - Outsourcer code.
23
+ * @props {string} name - Outsourcer name.
24
+ * @props {string} nameKana - Outsourcer name in Kana.
25
+ * @props {string} displayName - Abbreviated name.
26
+ * @props {string} contractStatus - Contract status.
27
+ * @props {string} remarks - Additional remarks.
28
+ */
29
+ export default class Outsourcer extends FireModel {
30
+ static className = "外注先";
31
+ static collectionPath = "Outsourcers";
32
+ static useAutonumber = false;
33
+ static logicalDelete = true;
34
+ static classProps = classProps;
35
+
36
+ static tokenFields = ["name", "nameKana", "displayName"];
37
+
38
+ static headers = [
39
+ { title: "外注先コード", key: "code" },
40
+ { title: "外注先名", key: "name" },
41
+ { title: "略称", key: "displayName" },
42
+ ];
43
+
44
+ static STATUS_ACTIVE = VALUES.ACTIVE.value;
45
+ static STATUS_TERMINATED = VALUES.TERMINATED.value;
46
+ }
@@ -0,0 +1,123 @@
1
+ /*****************************************************************************
2
+ * RoundSetting Model ver 1.0.0
3
+ * @author shisyamo4131
4
+ * ---------------------------------------------------------------------------
5
+ * - A class for managing rounding settings.
6
+ * - Provides static states for easy access to rounding modes.
7
+ * - Can get current rounding mode via `RoundSetting` directly.
8
+ * ---------------------------------------------------------------------------
9
+ * @props {string} operationResultSales - Rounding mode for operation result sales
10
+ * @props {string} operationResultTax - Rounding mode for operation result tax
11
+ * ---------------------------------------------------------------------------
12
+ * @static FLOOR - Rounding mode: Floor
13
+ * @static ROUND - Rounding mode: Round
14
+ * @static CEIL - Rounding mode: Ceil
15
+ * ---------------------------------------------------------------------------
16
+ * @method static set(value) - Sets the rounding mode
17
+ * @method static validate(value) - Validates the rounding mode
18
+ * @method static round(value, mode, precision) - Rounds a number based on the specified mode and precision
19
+ * @method static apply(value, precision) - Rounds a number using the current setting
20
+ * ---------------------------------------------------------------------------
21
+ * @example
22
+ * // Rounding examples
23
+ * RoundSetting.round(123.456, RoundSetting.FLOOR); // Returns: 123
24
+ * RoundSetting.round(123.456, RoundSetting.ROUND); // Returns: 123
25
+ * RoundSetting.round(123.456, RoundSetting.CEIL); // Returns: 124
26
+ * RoundSetting.round(123.456, RoundSetting.ROUND, 2); // Returns: 123.46
27
+ *
28
+ * // Using current setting
29
+ * RoundSetting.set(RoundSetting.ROUND); // Set to Round mode
30
+ * RoundSetting.apply(123.456); // Uses current setting
31
+ */
32
+ const _DEFINITIONS = Object.freeze({
33
+ FLOOR: { key: "FLOOR", label: "切り捨て", order: 0 },
34
+ ROUND: { key: "ROUND", label: "四捨五入", order: 1 },
35
+ CEIL: { key: "CEIL", label: "切り上げ", order: 2 },
36
+ });
37
+
38
+ const _ARRAY = Object.values(_DEFINITIONS).map((def) => ({
39
+ key: def.key,
40
+ label: def.label,
41
+ }));
42
+
43
+ const _ITEMS = _ARRAY.map((item) => ({
44
+ title: item.label,
45
+ value: item.key,
46
+ }));
47
+
48
+ export default class RoundSetting {
49
+ /** Provides all rounding modes */
50
+ static FLOOR = _DEFINITIONS.FLOOR.key;
51
+ static ROUND = _DEFINITIONS.ROUND.key;
52
+ static CEIL = _DEFINITIONS.CEIL.key;
53
+
54
+ static ITEMS = _ITEMS;
55
+
56
+ /** Static states */
57
+ static _mode = _DEFINITIONS.ROUND.key;
58
+ static set(value) {
59
+ this.validate(value);
60
+ this._mode = value;
61
+ }
62
+ static [Symbol.toPrimitive]() {
63
+ return this._mode;
64
+ }
65
+
66
+ static label(value) {
67
+ this.validate(value);
68
+ return _DEFINITIONS[value].label;
69
+ }
70
+
71
+ static validate(value) {
72
+ if (!Object.values(_DEFINITIONS).some((def) => def.key === value)) {
73
+ throw new Error(`Invalid rounding value: ${value}`);
74
+ }
75
+ return true;
76
+ }
77
+
78
+ /**
79
+ * Rounds a number based on the specified rounding mode
80
+ * @param {number} value - The number to round
81
+ * @param {string} mode - The rounding mode (FLOOR, ROUND, CEIL)
82
+ * @param {number} precision - Number of decimal places (default: 0)
83
+ * @returns {number} The rounded number
84
+ */
85
+ static round(value, mode = null, precision = 0) {
86
+ if (typeof value !== "number" || isNaN(value)) {
87
+ throw new Error("Value must be a valid number");
88
+ }
89
+
90
+ const roundingMode = mode || this._mode;
91
+ this.validate(roundingMode);
92
+
93
+ const factor = Math.pow(10, precision);
94
+ const scaledValue = value * factor;
95
+
96
+ let result;
97
+ switch (roundingMode) {
98
+ case this.FLOOR:
99
+ result = Math.floor(scaledValue);
100
+ break;
101
+ case this.ROUND:
102
+ result = Math.round(scaledValue);
103
+ break;
104
+ case this.CEIL:
105
+ result = Math.ceil(scaledValue);
106
+ break;
107
+ default:
108
+ throw new Error(`Unsupported rounding mode: ${roundingMode}`);
109
+ }
110
+
111
+ return result / factor;
112
+ }
113
+
114
+ /**
115
+ * Rounds using current setting
116
+ * @param {number} value - The number to round
117
+ * @param {number} precision - Number of decimal places (default: 0)
118
+ * @returns {number} The rounded number
119
+ */
120
+ static apply(value, precision = 0) {
121
+ return this.round(value, this._mode, precision);
122
+ }
123
+ }