diff --git a/src/drafting/Duration/index.ts b/src/drafting/Duration/index.ts new file mode 100644 index 0000000..82837ca --- /dev/null +++ b/src/drafting/Duration/index.ts @@ -0,0 +1,45 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +type Duration = { + amount: number; + unit: string; +}; + +/** + * Type guard to check if a value is a valid Duration + */ +function isDuration(value: unknown): value is Duration { + return ( + value != null && + typeof value === 'object' && + 'amount' in value && + 'unit' in value && + typeof (value as Duration).amount === 'number' && + typeof (value as Duration).unit === 'string' + ); +} + +/** + * Creates a drafter for Duration/Period types + * @param {unknown} value the duration or period (validated at runtime) + * @returns {string} the text (e.g., "2 days") + */ +export default function durationDrafter(value: unknown): string { + if (!isDuration(value)) { + return '0 unknown'; + } + + return `${value.amount} ${value.unit}`; +} diff --git a/src/drafting/index.ts b/src/drafting/index.ts index d7c7f1c..99df566 100644 --- a/src/drafting/index.ts +++ b/src/drafting/index.ts @@ -18,6 +18,7 @@ import booleanDrafter from './Boolean'; import dateTimeDrafter from './DateTime'; import doubleDrafter from './Double'; import integerDrafter from './Integer'; +import durationDrafter from './Duration'; import longDrafter from './Long'; import monetaryAmountDrafter from './MonetaryAmount'; import { DraftFormat } from './DraftFormat'; @@ -31,6 +32,8 @@ export function getDrafter(typeName: string) : ((value:any, format?:DraftFormat) case 'Integer': return integerDrafter; case 'Long': return longDrafter; case 'org.accordproject.money@0.3.0.MonetaryAmount': return monetaryAmountDrafter; + case 'org.accordproject.time@0.3.0.Duration': return durationDrafter; + case 'org.accordproject.time@0.3.0.Period': return durationDrafter; case 'String': return stringDrafter; default: return null; } diff --git a/test/DurationDrafter.test.ts b/test/DurationDrafter.test.ts new file mode 100644 index 0000000..f4619a2 --- /dev/null +++ b/test/DurationDrafter.test.ts @@ -0,0 +1,37 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import durationDrafter from '../src/drafting/Duration'; + +describe('Duration Drafter', () => { + test('should format Duration with days', () => { + const duration = { amount: 2, unit: 'days' }; + expect(durationDrafter(duration)).toBe('2 days'); + }); + + test('should format Duration with hours', () => { + const duration = { amount: 24, unit: 'hours' }; + expect(durationDrafter(duration)).toBe('24 hours'); + }); + + test('should format Period with months', () => { + const period = { amount: 3, unit: 'months' }; + expect(durationDrafter(period)).toBe('3 months'); + }); + + test('should format Duration with singular unit', () => { + const duration = { amount: 1, unit: 'day' }; + expect(durationDrafter(duration)).toBe('1 day'); + }); +}); diff --git a/test/__snapshots__/TemplateArchiveProcessor.test.ts.snap b/test/__snapshots__/TemplateArchiveProcessor.test.ts.snap index a25d1df..a454eaf 100644 --- a/test/__snapshots__/TemplateArchiveProcessor.test.ts.snap +++ b/test/__snapshots__/TemplateArchiveProcessor.test.ts.snap @@ -4,8 +4,8 @@ exports[`template archive processor should draft a template 1`] = ` "Late Delivery and Penalty ---- -In case of delayed delivery except for Force Majeure cases, the Seller shall pay to the Buyer for every {"$class":"org.accordproject.time@0.3.0.Duration","amount":2,"unit":"days"} of delay penalty amounting to 10.5% of the total value of the Equipment whose delivery has been delayed. +In case of delayed delivery except for Force Majeure cases, the Seller shall pay to the Buyer for every 2 days of delay penalty amounting to 10.5% of the total value of the Equipment whose delivery has been delayed. 1. Any fractional part of a days is to be considered a full days. 2. The total amount of penalty shall not however, exceed 55.0% of the total value of the Equipment involved in late delivery. -3. If the delay is more than {"$class":"org.accordproject.time@0.3.0.Duration","amount":15,"unit":"days"}, the Buyer is entitled to terminate this Contract." +3. If the delay is more than 15 days, the Buyer is entitled to terminate this Contract." `;