@shisyamo4131/air-guard-v2-schemas 2.4.2-dev.7 → 2.4.2-dev.70

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 (44) hide show
  1. package/index.js +9 -0
  2. package/package.json +45 -47
  3. package/src/Agreement.js +17 -24
  4. package/src/AgreementV2.js +185 -0
  5. package/src/ArrangementNotification.js +8 -8
  6. package/src/Billing.js +5 -34
  7. package/src/Company.js +162 -25
  8. package/src/Customer.js +39 -59
  9. package/src/Employee.js +595 -297
  10. package/src/Insurance.js +388 -0
  11. package/src/Operation.js +272 -280
  12. package/src/OperationBilling.js +126 -192
  13. package/src/OperationDetail.js +115 -85
  14. package/src/OperationResult.js +257 -254
  15. package/src/OperationResultDetail.js +65 -56
  16. package/src/Site.js +160 -141
  17. package/src/SiteOperationSchedule.js +187 -247
  18. package/src/SiteOperationScheduleDetail.js +75 -65
  19. package/src/SiteOrder.js +18 -29
  20. package/src/User.js +5 -1
  21. package/src/WorkTimeBase.js +205 -0
  22. package/src/WorkingResult.js +83 -255
  23. package/src/constants/day-type.js +20 -12
  24. package/src/constants/index.js +4 -0
  25. package/src/constants/insurance-status.js +15 -0
  26. package/src/constants/shift-type.js +5 -2
  27. package/src/errorDefinitions.js +173 -0
  28. package/src/parts/fieldDefinitions/array.js +8 -0
  29. package/src/parts/fieldDefinitions/check.js +20 -0
  30. package/src/parts/fieldDefinitions/code.js +8 -0
  31. package/src/parts/fieldDefinitions/constants.js +9 -0
  32. package/src/parts/fieldDefinitions/dateAt.js +58 -0
  33. package/src/parts/fieldDefinitions/dateTimeAt.js +8 -0
  34. package/src/parts/fieldDefinitions/defaultDefinition.js +118 -0
  35. package/src/parts/fieldDefinitions/multipleLine.js +12 -0
  36. package/src/parts/fieldDefinitions/number.js +69 -0
  37. package/src/parts/fieldDefinitions/object.js +38 -0
  38. package/src/parts/fieldDefinitions/oneLine.js +306 -0
  39. package/src/parts/fieldDefinitions/radio.js +8 -0
  40. package/src/parts/fieldDefinitions/select.js +240 -0
  41. package/src/parts/fieldDefinitions/time.js +8 -0
  42. package/src/parts/fieldDefinitions.js +46 -669
  43. package/src/utils/CutoffDate.js +11 -15
  44. package/src/utils/index.js +44 -8
@@ -1,61 +1,70 @@
1
1
  /*****************************************************************************
2
- * OperationResultDetail Model ver 1.0.0
2
+ * @file ./src/OperationResultDetail.js
3
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
4
+ * @description 稼働実績明細クラス
5
+ *
6
+ * @class
7
+ * @extends OperationDetail
8
+ *
9
+ * @property {Date} dateAt - 日付 (変更されると `dayType` が自動的に更新されます)
10
+ * @property {string} shiftType - 勤務区分
11
+ * @property {string} startTime - 開始時刻 (HH:MM 形式)
12
+ * @property {string} endTime - 終了時刻 (HH:MM 形式)
13
+ * @property {boolean} isStartNextDay - 翌日開始フラグ
14
+ * - `true` の場合、実際の勤務は `dateAt` の翌日であることを意味します。
15
+ * @property {number} breakMinutes - 休憩時間 (分)
16
+ * @property {string} date - `dateAt` に基づく YYYY-MM-DD 形式の日付文字列 (読み取り専用)
17
+ * - `dateAt` に基づいて YYYY-MM-DD 形式の文字列を返します。
18
+ * @property {Date} startAt - 開始日時 (Date オブジェクト) (読み取り専用)
19
+ * - `dateAt` に基づいて `startTime` を設定した Date オブジェクトを返します。
20
+ * - `isStartNextDay` true の場合、1日加算します。
21
+ * @property {Date} endAt - 終了日時 (Date オブジェクト) (読み取り専用)
22
+ * - `startAt` を起点に、最初に現れる `endTime` Date オブジェクトを返します。
23
+ * @property {boolean} isSpansNextDay - 翌日跨ぎフラグ (読み取り専用)
24
+ * - `true` の場合、`startAt` と `endAt` の日付が異なることを意味します。
25
+ * @property {number} regulationWorkMinutes - 規定労働時間 (分)
26
+ * - `startAt` から `endAt` までの時間から `breakMinutes` を差し引いた時間のうち、
27
+ * 規定内として扱う労働時間(分)です。
28
+ * - 実際の労働時間から残業時間を算出するための基準となる値です。
29
+ * - この値があることで、取極めに柔軟な設定を行うことが可能になる他、労働基準法の 1 日の所定労働時間上限が変更された際に
30
+ * 影響を最小限に抑えることができます。
31
+ * 例) 8:00 から 17:00 までの勤務で休憩が 60 分の場合
32
+ * - 規定労働時間を 8 時間 (480 分) とし、実際の勤務が 8 時間 (480 分) を超えた分が残業時間として扱われます。
33
+ * 例) 8:00 から 16:00 までの勤務で休憩が 60 分の場合
34
+ * - 規定労働時間を 7 時間 (420 分) とすると、実際の勤務が 7 時間 (420 分) を超えた分が残業時間として扱われます。
35
+ * - 規定労働時間を 8 時間 (480 分) とすると、実際の勤務が 8 時間 (480 分) を超えた分が残業時間として扱われます。
36
+ * 例) 7:00 から 翌日 7:00 までの勤務で休憩が 60 分の場合
37
+ * - 規定労働時間を 8 時間 (480 分) とすると、実際の勤務が 8 時間 (480 ) を超えた分が残業時間として扱われます。
38
+ * この場合、最初の 8 時間までは基本単価が適用され、残りの 8 時間は残業単価が適用されるといった設定が可能になります。
39
+ * - 規定労働時間を 24 時間 (1440 分) とすると、実際の勤務が 24 時間 (1440 分) を超えた分が残業時間として扱われます。
40
+ * この場合、全ての勤務時間が基本単価で扱われるといった設定が可能になります。
41
+ * @property {string} dayType - 曜日区分
42
+ * @property {number} totalWorkMinutes - 総労働時間 (休憩時間を除く) () (読み取り専用)
43
+ * @property {number} regularTimeWorkMinutes - 所定労働時間 (分) (読み取り専用)
44
+ * @property {number} overtimeWorkMinutes - 残業時間 (分) (読み取り専用)
45
+ * @property {string} id - 従業員ID または 外注先ID
46
+ * @property {number} index - 外注先の識別用インデックス (従業員の場合は常に0)
47
+ * @property {boolean} isEmployee - 従業員フラグ (true: 従業員, false: 外注先)
48
+ * @property {number} amount - 配置人数 (常に1で固定)
49
+ * @property {string} siteId - 現場ID
50
+ * @property {boolean} isQualified - 資格者フラグ
51
+ * @property {boolean} isOjt - OJTフラグ
52
+ * @property {string} workerId - 作業者ID (読み取り専用)
53
+ * - 従業員の場合は `id` と同じ、外注先の場合は `id` と `index` を `:` で結合した文字列を返します。
54
+ * @property {string|null} employeeId - 従業員ID (該当しない場合は null) (読み取り専用)
55
+ * @property {string|null} outsourcerId - 外注先ID (該当しない場合は null) (読み取り専用)
56
+ *
57
+ * @method setDateAtCallback - `dateAt` が設定されたときに呼び出されるコールバック関数
58
+ * @method getInvalidReasons - クラス特有のエラーの有無を返すメソッド
59
+ *
60
+ * @getter {boolean} isInvalid - クラス特有のエラーが存在するかどうかを返すプロパティ
61
+ * @getter {Array<string>} invalidReasons - クラス特有のエラーコードの配列を返すプロパティ
62
+ *
63
+ * @static SHIFT_TYPE - 勤務区分を定義する定数オブジェクト
64
+ * @static INVALID_REASON - クラス特有のエラーコードを定義する定数オブジェクト
65
+ * - `BREAK_MINUTES_NEGATIVE`: `breakMinutes` が負の値である場合のエラーコード
66
+ * - `REGULATION_WORK_MINUTES_NEGATIVE`: `regulationWorkMinutes` が負の値である場合のエラーコード
67
+ * @static DAY_TYPE - 曜日区分を定義する定数オブジェクト
59
68
  *****************************************************************************/
60
69
  import OperationDetail from "./OperationDetail.js";
61
70
 
package/src/Site.js CHANGED
@@ -1,7 +1,5 @@
1
- /**
2
- * @file src/Site.js
3
- * @author shisyamo4131
4
- *
1
+ /*****************************************************************************
2
+ * @file ./src/Site.js
5
3
  * NOTE: `customerId`, `customer` プロパティについて
6
4
  * - 仮登録
7
5
  * - 取引先未定での現場登録のシチュエーションを考慮して現場情報は仮登録を可能とする。
@@ -12,32 +10,20 @@
12
10
  * - 自身の従属先データを持たせる場合に `XxxxxMinimal` クラスを使用するが、アプリ側でオブジェクト選択を行う場合に
13
11
  * `Xxxxx` クラスにするのか `XxxxxMinimal` クラスにするのかを判断できないため、docId を持たせて
14
12
  * `beforeCreate` フックでオブジェクトを取得するようにする。
15
- */
13
+ *****************************************************************************/
16
14
  import { default as FireModel } from "@shisyamo4131/air-firebase-v2";
17
15
  import { defField } from "./parts/fieldDefinitions.js";
18
16
  import { defAccessor } from "./parts/accessorDefinitions.js";
19
17
  import Customer from "./Customer.js";
20
- import Agreement from "./Agreement.js";
18
+ import AgreementV2 from "./AgreementV2.js";
21
19
  import { VALUES } from "./constants/site-status.js";
22
20
  import { GeocodableMixin } from "./mixins/GeocodableMixin.js";
23
21
 
24
22
  const classProps = {
25
- // customerId: defField("customerId", {
26
- // required: true,
27
- // component: {
28
- // attrs: {
29
- // disabled: ({ editMode }) => {
30
- // return editMode !== "CREATE";
31
- // },
32
- // },
33
- // },
34
- // }),
35
23
  customerId: defField("customerId", {
36
24
  component: {
37
25
  attrs: {
38
- /**
39
- * `_beforeData.customerId` が存在する場合(本登録後の編集時を表す)には `customerId` を必須とする。
40
- */
26
+ /** `_beforeData.customerId` が存在する場合(本登録後の編集時を表す)には `customerId` を必須とする。 */
41
27
  required: ({ item }) => {
42
28
  return !!item._beforeData.customerId;
43
29
  },
@@ -45,21 +31,12 @@ const classProps = {
45
31
  },
46
32
  }),
47
33
  customer: defField("customer", { hidden: true, customClass: Customer }),
48
- customerName: defField("name", {
49
- label: "取引先名",
50
- required: ({ item }) => {
51
- return !item.customerId; // isTemporary プロパティでの判定でも良いか?
52
- },
53
- component: {
54
- attrs: {
55
- rules: [
56
- (value) =>
57
- (value && value.length >= 2) ||
58
- "取引先名を2文字以上で入力してください。",
59
- ],
60
- },
61
- },
62
- }),
34
+
35
+ /**
36
+ * 取引先名
37
+ * - `customerId` が未設定の場合に必須(仮登録状態で取引先の名前だけ登録したい場合を想定)
38
+ */
39
+ customerName: defField("customerName"),
63
40
  code: defField("code", { label: "現場コード" }),
64
41
  name: defField("name", {
65
42
  label: "現場名",
@@ -78,38 +55,37 @@ const classProps = {
78
55
  building: defField("building"),
79
56
  location: defField("location"),
80
57
  remarks: defField("multipleLine", { label: "備考" }),
81
- agreements: defField("array", { label: "取極め", customClass: Agreement }),
58
+ // agreements: defField("array", { label: "取極め", customClass: Agreement }),
59
+ agreementsV2: defField("array", {
60
+ label: "取極め",
61
+ customClass: AgreementV2,
62
+ }),
82
63
  status: defField("siteStatus", { required: true }),
83
64
  };
84
65
 
85
66
  /*****************************************************************************
67
+ * @class Site
68
+ * @author shisyamo4131
69
+ *
86
70
  * @property {string} customerId - 取引先ドキュメントID
87
71
  *
88
72
  * @property {object} customer - 取引先オブジェクト
89
- * - `beforeCreate`, `beforeUpdate` `customerId` に該当する `Customer` オブジェクトと自動的に同期されます。
90
- * - `Customer` が更新された場合は Cloud Functions で同期される必要があります。
91
- *
92
- * @property {string} code - Site code.
93
- * @property {string} name - Site name.
94
- * @property {string} nameKana - Site name in Kana.
73
+ * @property {string} customerName - 取引先名
74
+ * @property {string} code - 現場コード
75
+ * @property {string} name - 現場名
76
+ * @property {string} nameKana - 現場名カナ
95
77
  * @property {string} zipcode - Postal code.
96
78
  * @property {string} prefCode - Prefecture code.
97
- *
98
79
  * @property {string} prefecture - Prefecture name derived from `prefCode` (read-only)
99
- *
100
80
  * @property {string} city - City name.
101
81
  * @property {string} address - Address details.
102
82
  * @property {string} building - Building name.
103
- *
104
83
  * @property {string} fullAddress - Full address combining prefecture, city, and address (read-only)
105
- *
106
84
  * @property {object} location - Geographical location.
107
85
  * @property {string} remarks - Additional remarks.
108
- * @property {array} agreements - List of agreements (Agreement).
109
- * - Enhanced with custom methods: `add()`, `change()`, `remove()`
86
+ * @property {array} agreementsV2 - 取極めの配列(バージョン2)。`AgreementV2` クラスのインスタンスを要素とする。
110
87
  *
111
88
  * @property {string} status - Site status.
112
- *
113
89
  * @property {boolean} isTemporary - 仮登録状態かどうかを表すフラグ
114
90
  *
115
91
  * @function getAgreement
@@ -119,24 +95,6 @@ const classProps = {
119
95
  * @param {string} args.dayType - Day type (e.g., "WEEKDAY", "SATURDAY").
120
96
  * @param {string} args.shiftType - Shift type (e.g., "DAY", "NIGHT").
121
97
  * @returns {Agreement|null} - Matching agreement or null if not found.
122
- *
123
- * @memberof agreements
124
- * @function add
125
- * Adds Agreement instance to agreements array.
126
- * @param {Agreement} agreement - Agreement instance to add.
127
- * @throws {Error} If argument is not an Agreement instance.
128
- *
129
- * @memberof agreements
130
- * @function change
131
- * Replaces existing agreement by key matching.
132
- * @param {Agreement} newAgreement - New Agreement instance to replace existing one.
133
- * @throws {Error} If argument is not an Agreement instance or if agreement not found.
134
- *
135
- * @memberof agreements
136
- * @function remove
137
- * Removes agreement from array by key matching.
138
- * @param {Agreement} agreement - Agreement instance to remove.
139
- * @throws {Error} If agreement not found.
140
98
  *****************************************************************************/
141
99
  export default class Site extends GeocodableMixin(FireModel) {
142
100
  static className = "現場";
@@ -185,6 +143,8 @@ export default class Site extends GeocodableMixin(FireModel) {
185
143
  /**
186
144
  * ドキュメント作成直前の処理です。
187
145
  * - `customerId` に該当する `Customer` インスタンスを取得して `customer` プロパティにセットします。
146
+ * - 取引先が未設定のまま現場を仮登録することを許容しますが、その場合は `customerName` プロパティに取引先名を入力する必要があります。
147
+ * - `customerId` と `customerName` の両方が未設定の場合はエラーをスローします。
188
148
  * @param {Object} args - Creation options.
189
149
  * @param {string} [args.docId] - Document ID to use (optional).
190
150
  * @param {boolean} [args.useAutonumber=true] - Whether to use auto-numbering.
@@ -192,26 +152,29 @@ export default class Site extends GeocodableMixin(FireModel) {
192
152
  * @param {Function} [args.callBack] - Callback function.
193
153
  * @param {string} [args.prefix] - Path prefix.
194
154
  * @returns {Promise<void>}
155
+ * @throws {Error} `customerId` と `customerName` の両方が未設定の場合にスローされます。
195
156
  */
196
157
  async beforeCreate(args = {}) {
197
158
  await super.beforeCreate(args);
198
- // if (!this.customerId) return;
199
- // const customerInstance = new Customer();
200
- // const isExist = await customerInstance.fetch({
201
- // ...args,
202
- // docId: this.customerId,
203
- // });
204
- // if (!isExist) {
205
- // return Promise.reject(
206
- // new Error("Invalid customerId: Customer does not exist.")
207
- // );
208
- // }
209
- // this.customer = customerInstance;
159
+
160
+ /**
161
+ * 取引先IDが指定されておらず、かつ取引先名が指定されていない場合はエラーをスロー
162
+ */
163
+ if (!this.customerId && !this.customerName) {
164
+ throw new Error(
165
+ "Either customerId or customerName must be provided for temporary registration.",
166
+ );
167
+ }
168
+
210
169
  await this._setCustomer();
211
170
  }
212
171
 
213
172
  /**
214
- * Override beforeUpdate to prevent changing customer reference.
173
+ * ドキュメント更新直前の処理です。
174
+ * - `customerId` に該当する `Customer` インスタンスを取得して `customer` プロパティにセットします。
175
+ * - 一度設定した取引先を未設定に戻すことはできません。
176
+ * - 取引先が変更されていた場合は `customer` プロパティを更新します。
177
+ * - `customerId` と `customerName` の両方が未設定の場合はエラーをスローします。
215
178
  * @param {Object} args - Creation options.
216
179
  * @param {Object} [args.transaction] - Firestore transaction.
217
180
  * @param {Function} [args.callBack] - Callback function.
@@ -221,13 +184,7 @@ export default class Site extends GeocodableMixin(FireModel) {
221
184
  async beforeUpdate(args = {}) {
222
185
  await super.beforeUpdate(args);
223
186
 
224
- // if (this.customer.docId !== this._beforeData.customer.docId) {
225
- // return Promise.reject(
226
- // new Error("Not allowed to change customer reference.")
227
- // );
228
- // }
229
-
230
- // 取引先を未設定に戻すことはできない。
187
+ // 一度設定した取引先を未設定に戻すことはできない。
231
188
  if (this._beforeData.customerId && !this.customerId) {
232
189
  throw new Error("Cannot unset customerId once it is set.");
233
190
  }
@@ -236,11 +193,28 @@ export default class Site extends GeocodableMixin(FireModel) {
236
193
  if (this.customerId !== this._beforeData.customerId) {
237
194
  await this._setCustomer();
238
195
  }
196
+
197
+ /**
198
+ * 取引先IDが指定されておらず、かつ取引先名が指定されていない場合はエラーをスロー
199
+ */
200
+ if (!this.customerId && !this.customerName) {
201
+ throw new Error(
202
+ "Either customerId or customerName must be provided for temporary registration.",
203
+ );
204
+ }
239
205
  }
240
206
 
207
+ /**
208
+ * Override `afterInitialize` to define custom accessors and methods.
209
+ * - Defines `fullAddress`, `prefecture`, and `isTemporary` accessors.
210
+ * - Enhances `agreements` array with `add`, `change`, and `remove` methods.
211
+ * @param {Object} item - Initial data item.
212
+ * @return {void}
213
+ */
241
214
  afterInitialize(item = {}) {
242
215
  super.afterInitialize(item);
243
216
 
217
+ /** Define `fullAddress`, `prefecture`, and `isTemporary` accessors. */
244
218
  Object.defineProperties(this, {
245
219
  fullAddress: defAccessor("fullAddress"),
246
220
  prefecture: defAccessor("prefecture"),
@@ -248,64 +222,105 @@ export default class Site extends GeocodableMixin(FireModel) {
248
222
  configurable: true,
249
223
  enumerable: true,
250
224
  get() {
251
- return !!this.customerId;
225
+ return !this.customerId;
252
226
  },
253
227
  set() {},
254
228
  },
255
229
  });
256
230
 
257
- const self = this;
231
+ /** 2026-03-31 Deprecated */
232
+ // /**
233
+ // * `Agreement` プロパティに対するカスタムメソッドを定義します。
234
+ // * - add(agreement): `Agreement` インスタンスを追加します。
235
+ // * - change(newAgreement): `key` プロパティを基に既存の `Agreement` を置き換えます。
236
+ // * - remove(agreement): `key` プロパティを基に `Agreement` を削除します。
237
+ // */
238
+ // const self = this;
239
+ // Object.defineProperties(this.agreements, {
240
+ // add: {
241
+ // value: function (agreement) {
242
+ // if (!(agreement instanceof Agreement)) {
243
+ // throw new Error("Argument must be an instance of Agreement");
244
+ // }
245
+ // self.agreements.push(agreement);
246
+ // },
247
+ // writable: false,
248
+ // enumerable: false,
249
+ // },
250
+ // change: {
251
+ // value: function (newAgreement) {
252
+ // if (!(newAgreement instanceof Agreement)) {
253
+ // throw new Error("Argument must be an instance of Agreement");
254
+ // }
255
+ // const index = self.agreements.findIndex(
256
+ // (agr) => agr.key === newAgreement._beforeData.key,
257
+ // );
258
+ // if (index !== -1) {
259
+ // self.agreements[index] = newAgreement;
260
+ // } else {
261
+ // throw new Error("Agreement not found");
262
+ // }
263
+ // },
264
+ // writable: false,
265
+ // enumerable: false,
266
+ // },
267
+ // remove: {
268
+ // value: function (agreement) {
269
+ // const index = self.agreements.findIndex(
270
+ // (agr) => agr.key === agreement._beforeData.key,
271
+ // );
272
+ // if (index !== -1) {
273
+ // self.agreements.splice(index, 1);
274
+ // } else {
275
+ // throw new Error("Agreement not found");
276
+ // }
277
+ // },
278
+ // },
279
+ // });
280
+ }
258
281
 
259
- /**
260
- * `Agreement` プロパティに対するカスタムメソッドを定義します。
261
- * - add(agreement): `Agreement` インスタンスを追加します。
262
- * - change(newAgreement): `key` プロパティを基に既存の `Agreement` を置き換えます。
263
- * - remove(agreement): `key` プロパティを基に `Agreement` を削除します。
264
- */
265
- Object.defineProperties(this.agreements, {
266
- add: {
267
- value: function (agreement) {
268
- if (!(agreement instanceof Agreement)) {
269
- throw new Error("Argument must be an instance of Agreement");
270
- }
271
- self.agreements.push(agreement);
272
- },
273
- writable: false,
274
- enumerable: false,
275
- },
276
- change: {
277
- value: function (newAgreement) {
278
- if (!(newAgreement instanceof Agreement)) {
279
- throw new Error("Argument must be an instance of Agreement");
280
- }
281
- const index = self.agreements.findIndex(
282
- (agr) => agr.key === newAgreement._beforeData.key
283
- );
284
- if (index !== -1) {
285
- self.agreements[index] = newAgreement;
286
- } else {
287
- throw new Error("Agreement not found");
288
- }
289
- },
290
- writable: false,
291
- enumerable: false,
292
- },
293
- remove: {
294
- value: function (agreement) {
295
- const index = self.agreements.findIndex(
296
- (agr) => agr.key === agreement._beforeData.key
297
- );
298
- if (index !== -1) {
299
- self.agreements.splice(index, 1);
300
- } else {
301
- throw new Error("Agreement not found");
302
- }
303
- },
304
- },
282
+ /**
283
+ * 指定された日付、勤務区分で有効な取極めオブジェクトを返します。
284
+ * - 日付が指定されなかった場合は、登録されている最新の取極めオブジェクトを返します。
285
+ * - 条件に合致する取極めオブジェクトが存在しない場合は `null` を返します。
286
+ * @param {string} date - 日付 (YYYY-MM-DD形式)
287
+ * @param {string} shiftType - 勤務区分
288
+ * @returns {Object|null} - 有効な取極めオブジェクトまたは `null`
289
+ */
290
+ getValidAgreement({ date = null, shiftType = null } = {}) {
291
+ const filtered = this.agreementsV2.filter((agr) => {
292
+ return agr.shiftType === shiftType;
305
293
  });
294
+ if (filtered.length === 0) return null;
295
+ filtered.sort((a, b) => b.date.localeCompare(a.date));
296
+ if (!date) return filtered[0];
297
+ return filtered.find((agr) => agr.date <= date) || null;
298
+ }
299
+
300
+ /***************************************************************************
301
+ * FOR DEPRECATED PROPERTIES
302
+ ***************************************************************************/
303
+ /**
304
+ * @deprecated `agreements` property is deprecated. Use `agreementsV2` instead.
305
+ */
306
+ get agreements() {
307
+ console.warn(
308
+ "Warning: `agreements` is deprecated. Use `agreementsV2` instead.",
309
+ );
310
+ return [];
311
+ }
312
+
313
+ /**
314
+ * @deprecated `agreements` property is deprecated. Use `agreementsV2` instead.
315
+ */
316
+ set agreements(newValue) {
317
+ console.warn(
318
+ "Warning: `agreements` is deprecated. Use `agreementsV2` instead.",
319
+ );
306
320
  }
307
321
 
308
322
  /**
323
+ * @deprecated `getAgreement` method is deprecated. Use `getValidAgreement` instead.
309
324
  * Returns the applicable agreement based on the given date, dayType, and shiftType.
310
325
  * Filters agreements by dayType and shiftType, sorts them by startDate in descending order,
311
326
  * and returns the first agreement where date is less than or equal to the given date.
@@ -317,13 +332,17 @@ export default class Site extends GeocodableMixin(FireModel) {
317
332
  * @returns {Object|null} - The matching agreement object or null if not found.
318
333
  */
319
334
  getAgreement(args = {}) {
320
- const { date, dayType, shiftType } = args;
321
- if (!date || !dayType || !shiftType) return null;
322
- return (
323
- this.agreements
324
- .filter((agr) => agr.dayType === dayType && agr.shiftType === shiftType)
325
- .sort((a, b) => b.date.localeCompare(a.date))
326
- .find((agr) => agr.date <= date) || null
335
+ // const { date, dayType, shiftType } = args;
336
+ // if (!date || !dayType || !shiftType) return null;
337
+ // return (
338
+ // this.agreements
339
+ // .filter((agr) => agr.dayType === dayType && agr.shiftType === shiftType)
340
+ // .sort((a, b) => b.date.localeCompare(a.date))
341
+ // .find((agr) => agr.date <= date) || null
342
+ // );
343
+ console.warn(
344
+ "Warning: `getAgreement` is deprecated. Use `getValidAgreement` instead.",
327
345
  );
346
+ return null;
328
347
  }
329
348
  }