본문으로 건너뛰기
가이드

Copyable Template

행위자가 명시적으로 테넌트 소유로 복사하는 선택적 시작 콘텐츠를 제공하고, 복사본이 원본을 추적하지 않는 이유를 이해합니다.

운영자가 선택해서 복사하는 시작 데이터를 제공합니다. 적용 후 레코드는 테넌트가 직접 관리합니다.

템플릿 선언과 적용

SDK CopyableTemplateContribution을 구현합니다. templates()는 버전이 있는 원본을 반환하고 apply()는 App 레코드를 저장한 뒤 공개 참조를 TemplateApplicationResult로 돌려줍니다. 키와 원본 형식, 테넌트 또는 Legal Entity 범위를 검사하고, 재시도할 때 기존 수정값을 보존하세요. 현재 구현은 packages/talent/src/Contribution/TalentDataTemplates.php에서 볼 수 있습니다.

Host 적용 명령에는 테넌트와 사용자를 명시합니다. 정확한 명령과 범위는 설치 콘텐츠에 있습니다. 업무에 반드시 필요한 행이라면 필수 설치 콘텐츠의 migration 경로를 사용하세요.

TEMPLATE_TENANT_ID에 대상 테넌트 ID, TEMPLATE_ACTOR_ID에 그 테넌트의 권한 있는 사용자 ID를 지정한 뒤 적용합니다.

코드 예시
Shell
task artisan -- nexia-apps:apply-template payroll smb_basic_elements \
  --tenant="$TEMPLATE_TENANT_ID" --actor="$TEMPLATE_ACTOR_ID"

결과 확인

적용 이력에 원본·버전과 생성 참조가 남고, 사용자가 복사본을 수정할 수 있어야 합니다. 재적용으로 중복이 생기거나 새 원본 버전 배포만으로 기존 복사본이 덮어써져서는 안 됩니다. App 테스트하기에서 이 사례를 검사합니다.

적용과 출처 이력

copyable template은 테넌트가 복사하기를 선택할 수 있는 콘텐츠입니다. 적용하면 편집 가능한 테넌트 소유 행이 생기고 출처가 기록됩니다.

packages/payroll/src/Contribution/PayrollDataTemplates.php:

코드 예시
PHP
<?php

declare(strict_types=1);

namespace Amuzcorp\Nexia\Payroll\Contribution;

use Amuzcorp\Nexia\Payroll\Domain\PayrollElementCatalog;
use Amuzcorp\Nexia\Payroll\Models\PayrollElement;
use Nexia\Templates\Contracts\CopyableTemplateContribution;
use Nexia\Templates\CopyableTemplate;
use Nexia\Templates\TemplateApplicationContext;
use Nexia\Templates\TemplateApplicationResult;

/** Tenant-copyable SMB baseline; applying it creates editable Payroll-owned records. */
final class PayrollDataTemplates implements CopyableTemplateContribution
{
    private const KEY = 'smb_basic_elements';

    public function templates(): array
    {
        return [new CopyableTemplate('payroll', self::KEY, '2', CopyableTemplate::SCOPE_TENANT, PayrollElementCatalog::definitions())];
    }

    public function apply(CopyableTemplate $template, TemplateApplicationContext $context): TemplateApplicationResult
    {
        if ($template->key !== self::KEY || ! is_array($template->source)) {
            throw new \InvalidArgumentException('Unsupported Payroll data template.');
        }

        $refs = [];
        foreach ($template->source as $definition) {
            $element = PayrollElement::query()->firstOrCreate(
                ['code' => $definition['code']],
                $definition,
            );
            $refs[] = ['type' => 'payroll.payroll_element', 'id' => (string) $element->public_id, 'key' => $element->code, 'version' => 1];
        }

        return new TemplateApplicationResult($refs);
    }
}

인스턴스 메서드 둘입니다. templates()가 복사 가능한 것을 선언하고, apply()가 복사를 수행하며 만든 행의 참조를 돌려줍니다.

Contribution 발견

contribution 지점은 Nexia\Templates\Contracts\CopyableTemplateContribution으로 공개되어 있습니다. 새 App은 이것을 직접 구현할 수 있고, 호스트는 App이 선언한 contribution 위치에서 클래스를 발견합니다.

SDK는 CopyableTemplate, TemplateApplicationContext, TemplateApplicationResult도 공개하므로 선언과 적용 경계 전체가 Nexia\* 아래에 머뭅니다. 구현 사례는 packages/payroll과 packages/talent에서 확인할 수 있습니다.

값 객체

CopyableTemplate은 비어 있지 않은 app, key, version과 상수 둘 중 하나인 범위를 요구합니다.

상수값
CopyableTemplate::SCOPE_TENANTtenant
CopyableTemplate::SCOPE_LEGAL_ENTITYlegal_entity

다른 값에는 예외를 던집니다.

A copyable template requires an app, key, and version.
Unsupported copyable template scope [organization].

올바른 apply()의 세 성질

성질방법이유
멱등업무 식별자를 키로 firstOrCreate두 번 적용해도 중복되지 않아야 함
참조를 돌려줌public_id를 담은 ['type', 'id', 'key', 'version']출처 기록. 숫자 키는 절대 아님
입력을 검증소유하지 않은 키를 거부런타임이 걸러줬다고 가정하지 않음

출처 원장

템플릿을 적용하면 테넌트 로컬 template_applications 원장에 항목이 기록됩니다.

원장 필드내용
App 키소유 App
템플릿 키와 버전불변 원본 식별자
범위tenant 또는 legal_entity
Legal Entitynullable
행위자누가 적용했는가
결과 상태성공 또는 실패
실패 이유실패 시
생성된 resource 참조복사가 만든 것

원장은 출처 기록만입니다. 템플릿 원본 카탈로그가 되지 않고, 복사본의 이후 편집을 추적하지도 않습니다.

원본과 복사본의 변경

복사본은 만들어지는 순간 갈라집니다. 템플릿을 고쳐서 수정을 배포하고 기존 테넌트가 받기를 기대하지 마세요.

하는 일기존 복사본에 미치는 영향
템플릿 원본 편집없음
version 올림없음 — 이후 적용만 달라짐
템플릿 폐기없음 — 복사본은 테넌트 것

기존 테넌트에 새 콘텐츠를 전하려면 누군가 새 버전을 적용합니다. apply()가 업무 키에 대해 멱등하므로 없는 것만 추가됩니다.

현재 제약 둘

Approval form preset은 테넌트 범위입니다. nexia-apps:apply-template에 --legal-entity를 넘기면 그것들에 대해 실패합니다.

프로세스 템플릿은 이 경로를 전혀 쓰지 않습니다. 고르면 저장되지 않은 BPMN 편집기 문서가 바뀌고, 평범한 정의 저장·배포가 영속화와 짝 결정 배포를 소유합니다. 업무 프로세스를 보세요.

경계 규칙

initializer가 아닙니다. 템플릿은 설계상 생략 가능합니다. 그 행 없이 App이 고장난다면 설치에 속합니다.

demo data가 아닙니다. demo data는 폐기 가능하고 설치 전제 조건이 아니며 --force 없이는 프로덕션에서 거부됩니다.

여기서 아무것도 권한을 부여하지 않습니다. 복사된 행도 평범한 권한 검사를 받습니다.

원본은 사실상 불변입니다. 배포된 key와 version을 고정으로 취급하고, 동작 변경에는 새 버전을 붙이세요.

원본 위치: docs/developers/content/ko/platform-extensions/copyable-templates.md