duson-price-calculation

songyoungsoo's avatarfrom songyoungsoo

두손기획 인쇄 시스템의 9개 품목별 가격 계산 로직. 데이터베이스 테이블, PHP API, JavaScript 계산 로직의 관계를 정의합니다. 가격 계산 관련 작업 시 이 문서를 참조하세요. Keywords: 가격, 계산, calculate, price, ajax, 전단지, 명함, 봉투, 스티커, 포스터

⭐0stars🔀0forks📁View on GitHub🕐Updated Jan 10, 2026⬇️1downloads

When & Why to Use This Skill

This Claude skill serves as a comprehensive technical reference and knowledge base for the Duson Planning printing price calculation system. It meticulously defines the architecture and logic flow between database tables, PHP APIs, and JavaScript components for nine distinct printing categories. By centralizing complex pricing formulas, VAT rules, and API parameter mappings, it provides a robust framework for maintaining and scaling e-commerce printing platforms.

Use Cases

  • System Debugging: Identifying and resolving logic errors in PHP-based price calculation APIs or JavaScript UI updates.
  • Database Management: Referencing specific SQL table structures (e.g., mlangprintauto_inserted) and column definitions for printing options.
  • API Integration: Developing and testing AJAX-based price requests with precise parameter mapping for different product types like stickers or business cards.
  • Feature Expansion: Implementing new printing products by following the established architectural patterns for price calculation and basket integration.
  • Technical Documentation: Providing developers with a clear map of file locations and functional dependencies within the printing system.
nameduson-price-calculation
description두손기획 인쇄 시스템의 9개 품목별 가격 계산 로직. 데이터베이스 테이블, PHP API, JavaScript 계산 로직의 관계를 정의합니다. 가격 계산 관련 작업 시 이 문서를 참조하세요. Keywords: 가격, 계산, calculate, price, ajax, 전단지, 명함, 봉투, 스티커, 포스터

두손기획 가격 계산 시스템

[개요] 아키텍처

[사용자 입력] → [JavaScript] → [AJAX] → [PHP API] → [DB 조회] → [가격 계산] → [JSON 응답] → [UI 업데이트]

공통 파일 구조 (각 품목):

mlangprintauto/[product]/
├── index.php                    # 제품 페이지 (인라인 JS 포함)
├── calculate_price_ajax.php     # 가격 계산 API
├── calculator.js                # 계산 로직 (일부 품목)
├── add_to_basket.php            # 장바구니 저장
└── get_*.php                    # 옵션 데이터 API

[품목 1] 전단지 (inserted)

파일 위치

용도 파일
가격 API mlangprintauto/inserted/calculate_price_ajax.php
JS 계산 mlangprintauto/inserted/calculator.js
장바구니 mlangprintauto/inserted/add_to_basket.php

데이터베이스 테이블

메인: mlangprintauto_inserted

-- 주요 컬럼
style        VARCHAR(100)   -- 인쇄색상 코드
Section      VARCHAR(200)   -- 용지 규격
TreeSelect   INT            -- 용지 종류
quantity     FLOAT          -- 수량 (0.5, 1, 1.5 등)
POtype       VARCHAR(50)    -- 인쇄면 (1=단면, 2=양면)
money        VARCHAR(200)   -- 기본 인쇄비
DesignMoney  INT            -- 편집비 (기본 10000)
quantityTwo  VARCHAR(100)   -- 매수 표시 ("2000장" 등)

추가 옵션: additional_options_config

  • 코팅: option_category='coating'
  • 오시: option_category='creasing'

API 파라미터 (GET)

MY_type      : 인쇄색상 코드 (style 매칭)
PN_type      : 용지 규격 (Section 매칭)
MY_Fsd       : 용지 종류 (TreeSelect 매칭)
MY_amount    : 수량 (float: 0.5, 1, 1.5)
POtype       : 인쇄면 (1 또는 2)
ordertype    : 주문유형 (print/design/total)

가격 계산 공식

$base_price = intval($row['money']);
$design_price = ($ordertype === 'total') ? intval($row['DesignMoney']) : 0;
$subtotal = $base_price + $design_price + $additional_options_total;
$vat = floor($subtotal / 10);
$total = $subtotal + $vat;

API 응답 형식

{
  "success": true,
  "data": {
    "Price": "200,000",
    "DS_Price": "30,000",
    "Order_Price": "253,000",
    "PriceForm": 200000,
    "DS_PriceForm": 30000,
    "VAT_PriceForm": 23000,
    "Total_PriceForm": 253000,
    "MY_amountRight": "2000장"
  }
}

JavaScript 핵심 함수

function calculatePriceAjax() {
  var params = "MY_type=" + form.MY_type.value +
               "&PN_type=" + form.PN_type.value +
               "&MY_Fsd=" + form.MY_Fsd.value +
               "&MY_amount=" + form.MY_amount.value +
               "&POtype=" + form.POtype.value +
               "&ordertype=" + form.ordertype.value;

  // AJAX 호출 후 응답 처리
  window.currentPriceData = {
    total_price: data.Order_PriceForm,
    vat_price: data.Total_PriceForm
  };
}

하위 유형: 리플렛 (leaflet)

리플렛은 전단지 가격 + 접지/코팅/오시 추가금으로 계산되는 전단지의 하위 유형입니다.

추가 파일:

용도 파일
가격 API mlangprintauto/leaflet/calculate_price_ajax.php
JS 계산 mlangprintauto/leaflet/calculator.js
접지 API mlangprintauto/leaflet/get_fold_types.php
코팅 API mlangprintauto/leaflet/get_coating_types.php
오시 API mlangprintauto/leaflet/get_creasing_types.php
장바구니 mlangprintauto/leaflet/add_to_basket.php

추가 테이블: 접지 옵션 (mlangprintauto_leaflet_fold)

no               INT PRIMARY KEY
fold_type        VARCHAR(50)    -- 접지방식 (2fold, 3fold 등)
additional_price INT            -- 추가금액
description      VARCHAR(255)
display_order    INT
is_active        TINYINT(1)

접지 옵션 가격:

fold_type 이름 가격
2fold 2단접지 40,000원
3fold 3단접지 40,000원
4fold 4단접지 80,000원
accordion 병풍접지 80,000원
gate 대문접지 100,000원
zfold Z접지 60,000원

리플렛 가격 계산 공식:

// 1. 전단지 기본 가격 조회 (mlangprintauto_inserted)
$base_price = getInsertedPrice($params);

// 2. 접지 추가금 조회 (mlangprintauto_leaflet_fold)
$fold_price = getFoldPrice($fold_type);

// 3. 코팅 추가금 조회 (additional_options_config)
$coating_price = getCoatingPrice($coating_type);

// 4. 오시 추가금 조회 (additional_options_config)
$creasing_price = getCreasingPrice($creasing_type);

// 5. 합산
$subtotal = $base_price + $design_price + $fold_price + $coating_price + $creasing_price;
$vat = floor($subtotal / 10);
$total = $subtotal + $vat;

[품목 2] 명함 (namecard)

파일 위치

용도 파일
가격 API mlangprintauto/namecard/calculate_price_ajax.php
장바구니 mlangprintauto/namecard/add_to_basket.php

데이터베이스 테이블

메인: mlangprintauto_namecard

style        VARCHAR(100)
Section      VARCHAR(200)
quantity     FLOAT
POtype       VARCHAR(50)
money        VARCHAR(200)
DesignMoney  INT

프리미엄 옵션 (하드코딩)

$premium_prices = [
    'foil' => 30000,        // 박
    'numbering' => 60000,   // 넘버링
    'perforation' => 20000, // 미싱
    'rounding' => 20000,    // 귀돌이
    'creasing' => 20000     // 오시
];

API 파라미터 (GET/POST)

MY_type      : 스타일 (style)
Section      : 섹션
POtype       : 인쇄 타입
MY_amount    : 수량
ordertype    : 주문 유형
premium_options : JSON (선택사항)

가격 계산 공식

$base_price = intval($row['money']);
$design_price = ($ordertype === 'total') ? intval($row['DesignMoney']) : 0;
$premium_total = array_sum($selected_premium_prices);
$subtotal = $base_price + $design_price + $premium_total;
$total_with_vat = floor($subtotal * 1.1);

특이사항

  • POtype 없이 조회하는 폴백 메커니즘 있음
  • 프리미엄 옵션은 DB가 아닌 PHP에서 하드코딩

[품목 3] 봉투 (envelope)

파일 위치

용도 파일
가격 API mlangprintauto/envelope/calculate_price_ajax.php
장바구니 mlangprintauto/envelope/add_to_basket.php

데이터베이스 테이블

메인: mlangprintauto_envelope

style        VARCHAR(100)
Section      VARCHAR(200)
quantity     FLOAT
POtype       VARCHAR(50)
money        VARCHAR(200)
DesignMoney  VARCHAR(200)

추가 옵션: 양면테이프

// 테이프 가격 계산
if ($envelope_tape_enabled) {
    if ($quantity == 500) {
        $tape_price = 25000;  // 고정
    } else {
        $tape_price = $quantity * 40;  // 40원/매
    }
}

가격 계산 공식

$total_price = $base_price + $design_price + $tape_price;
$total_with_vat = floor($total_price * 1.1);

[품목 4] 스티커 (sticker_new)

파일 위치

용도 파일
가격 API mlangprintauto/sticker_new/calculate_price_ajax.php
장바구니 mlangprintauto/sticker_new/add_to_basket.php

데이터베이스 테이블

메인: mlangprintauto_sticker (재질별 단가)

jong         VARCHAR(100)   -- 재질 코드
shop_d1      INT            -- 도무송 기본비
shop_d2      INT            -- 도무송 추가비
shop_d3      INT            -- 특수용지비
shop_d4      INT            -- 기타

API 파라미터 (POST 필수)

jong         : 재질 코드 (예: "jil아트지")
garo         : 가로 사이즈 (mm, 최대 590)
sero         : 세로 사이즈 (mm, 최대 590)
mesu         : 수량 (최대 10000)
uhyung       : 특수 효과 추가비용
domusong     : 도무송 정보

수량별 요율 테이블

function getYoyoAndMg($mesu) {
    if ($mesu <= 1000) return ['yoyo' => 0.15, 'mg' => 7000];
    if ($mesu <= 4000) return ['yoyo' => 0.14, 'mg' => 6500];
    if ($mesu <= 5000) return ['yoyo' => 0.13, 'mg' => 6500];
    if ($mesu <= 9000) return ['yoyo' => 0.12, 'mg' => 6000];
    if ($mesu <= 10000) return ['yoyo' => 0.11, 'mg' => 5500];
    if ($mesu <= 50000) return ['yoyo' => 0.10, 'mg' => 5000];
    return ['yoyo' => 0.09, 'mg' => 5000];
}

가격 계산 공식 (복잡)

// 사이즈 계산 (여백 4mm 추가)
$size = ($garo + 4) * ($sero + 4);

// 도무송 비용 계산
if ($mesu == 500) {
    $d1_cost = (($d1 + $d2 * 20) * 900 / 1000) + (900 * $ts);
} elseif ($mesu == 1000) {
    $d1_cost = (($d1 + $d2 * 20) * $mesu / 1000) + ($mesu * $ts);
} else {
    $d1_cost = (($d1 + $d2 * 20) * $mesu / 1000) + ($mesu * ($ts / 9));
}

// 최종 가격
if ($mesu == 500) {
    $st_price = round(($size * ($mesu + 400) * $yoyo) + $jsp + $jka + $cka + $d1_cost, -3)
                * $gase + $uhyung + ($mg * ($mesu + 400) / 1000);
} else {
    $st_price = round(($size * $mesu * $yoyo) + $jsp + $jka + $cka + $d1_cost, -3)
                * $gase + $uhyung + ($mg * $mesu / 1000);
}

$st_price_vat = floor($st_price * 1.1);

특이사항

  • DB에서 가격을 직접 조회하지 않고 공식으로 계산
  • 실제 사이즈(mm) 입력 기반
  • 가장 복잡한 계산 로직

[품목 5] 자석스티커 (msticker)

파일 위치

용도 파일
가격 API mlangprintauto/msticker/calculate_price_ajax.php
장바구니 mlangprintauto/msticker/add_to_basket.php

데이터베이스 테이블

메인: mlangprintauto_msticker

Section      VARCHAR(200)   -- 규격 (style 대신 사용)
quantity     FLOAT
money        VARCHAR(200)
DesignMoney  INT
-- POtype 없음

가격 계산 공식

$base_price = intval($row['money']);
$design_price = ($ordertype === 'total') ? intval($row['DesignMoney']) : 0;
$total_with_vat = floor(($base_price + $design_price) * 1.1);

특이사항

  • 가장 단순한 구조
  • POtype 필드 없음
  • Section 필드로 규격 구분

[품목 6] 카다록 (cadarok)

파일 위치

용도 파일
가격 API mlangprintauto/cadarok/calculate_price_ajax.php
장바구니 mlangprintauto/cadarok/add_to_basket.php

데이터베이스 테이블

메인: mlangprintauto_cadarok

style        VARCHAR(100)
Section      VARCHAR(200)
quantity     FLOAT
POtype       VARCHAR(50)    -- 선택사항
money        VARCHAR(200)
DesignMoney  INT

가격 계산 공식

$base_price = intval($row['money']);
$design_price = ($ordertype === 'total') ? intval($row['DesignMoney']) : 0;
$additional_total = intval($_GET['additional_options_total'] ?? 0);
$subtotal = $base_price + $design_price + $additional_total;
$total_with_vat = floor($subtotal * 1.1);

특이사항

  • POtype 없이 조회하는 폴백 메커니즘 있음
  • additional_options_total 파라미터 지원

[품목 7] 포스터 (littleprint)

파일 위치

용도 파일
가격 API mlangprintauto/littleprint/calculate_price_ajax.php
장바구니 mlangprintauto/littleprint/add_to_basket.php

데이터베이스 테이블

메인: mlangprintauto_littleprint

style        VARCHAR(100)
Section      VARCHAR(200)
quantity     FLOAT
money        VARCHAR(200)
DesignMoney  INT

Section 매핑 로직

// 재질 코드 → 기본값(610)으로 변환
$section_map = [
    '604' => '610',  // 120아트/스노우
    '605' => '610',  // 150아트/스노우
    '606' => '610',  // 180아트/스노우
    '607' => '610',  // 200아트/스노우
    '608' => '610',  // 220아트/스노우
    '609' => '610',  // 250아트/스노우
];
$section = $section_map[$section] ?? $section;

특이사항

  • 테이블 우선순위: littleprint > namecard (폴백)
  • Section 매핑으로 다양한 재질을 하나로 통합

[품목 8] 상품권 (merchandisebond)

파일 위치

용도 파일
가격 API mlangprintauto/merchandisebond/calculate_price_ajax.php
장바구니 mlangprintauto/merchandisebond/add_to_basket.php

데이터베이스 테이블

메인: mlangprintauto_merchandisebond

style        VARCHAR(100)
Section      VARCHAR(200)
quantity     FLOAT
POtype       VARCHAR(50)
money        VARCHAR(200)
DesignMoney  INT

프리미엄 옵션 (명함과 동일)

$premium_prices = [
    'foil' => 30000,        // 박
    'numbering' => 60000,   // 넘버링
    'perforation' => 20000, // 미싱
    'rounding' => 20000,    // 귀돌이
    'creasing' => 20000     // 오시
];

API 응답 형식 (JS 호환)

{
  "success": true,
  "data": {
    "PriceForm": 50000,
    "DS_PriceForm": 10000,
    "Premium_PriceForm": 30000,
    "Total_PriceForm": 99000
  }
}

[품목 9] 양식지 (ncrflambeau)

파일 위치

용도 파일
가격 API mlangprintauto/ncrflambeau/calculate_price_ajax.php
장바구니 mlangprintauto/ncrflambeau/add_to_basket.php

데이터베이스 테이블

메인: mlangprintauto_ncrflambeau

style        VARCHAR(100)
Section      VARCHAR(200)
TreeSelect   INT
quantity     FLOAT
money        VARCHAR(200)
DesignMoney  INT

API 특징 (POST 필수)

// Prepared Statement 사용 (가장 안전)
$query = "SELECT * FROM mlangprintauto_ncrflambeau
          WHERE style = ? AND Section = ? AND TreeSelect = ? AND quantity = ?";
$stmt = mysqli_prepare($db, $query);
mysqli_stmt_bind_param($stmt, "sssi", $style, $section, $tree_select, $quantity);

응답 형식 (상세)

{
  "success": true,
  "message": "가격 계산 완료",
  "data": {
    "base_price": 50000,
    "design_price": 10000,
    "total_price": 66000,
    "formatted": {
      "base_price": "50,000원",
      "design_price": "10,000원",
      "total_price": "66,000원"
    }
  }
}

[공통] 추가 옵션 테이블

additional_options_config 구조

CREATE TABLE additional_options_config (
    id               INT AUTO_INCREMENT PRIMARY KEY,
    option_category  VARCHAR(20),   -- coating, creasing, folding, envelope_tape
    option_type      VARCHAR(20),   -- single, double, 1line, 2line 등
    option_name      VARCHAR(50),   -- 표시용 이름
    base_price       INT,           -- 추가 금액
    is_active        TINYINT(1) DEFAULT 1,
    sort_order       INT DEFAULT 0,
    created_at       TIMESTAMP,
    updated_at       TIMESTAMP
);

옵션 카테고리별 데이터

코팅 (coating):

type name price
single_glossy 단면유광코팅 80,000
double_glossy 양면유광코팅 160,000
single_matte 단면무광코팅 80,000
double_matte 양면무광코팅 160,000

오시 (creasing):

type name price
1line 1줄 32,000
2line 2줄 32,000
3line 3줄 40,000

[공통] JavaScript → 장바구니 연계

window.currentPriceData 설정

// 모든 품목에서 공통으로 사용
window.currentPriceData = {
    total_price: data.Order_PriceForm || data.total_price,
    vat_price: data.Total_PriceForm || data.total_with_vat,
    additional_options_total: additionalTotal
};

FormData 구성 (add_to_basket.php 호출)

const formData = new FormData();
formData.append("calculated_price", Math.round(window.currentPriceData.total_price));
formData.append("calculated_vat_price", Math.round(window.currentPriceData.vat_price));
formData.append("product_type", "[product]");
formData.append("MY_amountRight", document.getElementById("MY_amountRight")?.value || "");

fetch("add_to_basket.php", { method: "POST", body: formData })
    .then(r => r.json())
    .then(result => {
        if (result.success) {
            // 장바구니 추가 성공
        }
    });

shop_temp 테이블 저장

-- 장바구니 저장 컬럼
st_price          INT        -- calculated_price
st_price_vat      INT        -- calculated_vat_price
product_type      VARCHAR    -- 품목 코드
unit              VARCHAR    -- 단위 (연/매/부)
mesu              INT        -- 매수 (전단지만)

[품목별 비교표] (9개 품목)

계산 방식

품목 가격 소스 옵션 특이사항
inserted DB money 코팅, 오시 quantityTwo 매수
↳ leaflet inserted + 추가 접지, 코팅, 오시 전단지 하위 유형
namecard DB money 박, 넘버링 등 프리미엄 하드코딩
envelope DB money 양면테이프 테이프 수량 계산
sticker 공식 계산 도무송 사이즈 입력
msticker DB money 없음 가장 단순
cadarok DB money 추가옵션 폴백 메커니즘
littleprint DB money 없음 Section 매핑
merchandisebond DB money 박, 넘버링 등 명함과 동일
ncrflambeau DB money 없음 Prepared Stmt

API 방식

품목 HTTP 응답 형식
inserted GET PriceForm 스타일
↳ leaflet GET PriceForm + Fold/Coating
namecard GET/POST PriceForm 스타일
envelope GET base_price 스타일
sticker POST st_price 스타일
msticker GET base_price 스타일
cadarok GET base_price 스타일
littleprint GET base_price 스타일
merchandisebond GET PriceForm 스타일
ncrflambeau POST formatted 포함

[주의사항]

1. float 타입 비교 주의

// 수량 비교 시 floatval() 사용 필수
$db_quantity = floatval($row['quantity']);
$input_quantity = floatval($_GET['MY_amount']);

if (abs($db_quantity - $input_quantity) < 0.001) {
    // 일치
}

2. money 컬럼은 VARCHAR

// DB에서 조회 후 반드시 정수 변환
$base_price = intval($row['money']);  // "54000" → 54000

3. VAT 계산 방식 통일

// 방식 1: 나누기 10 (전단지, 리플렛)
$vat = floor($subtotal / 10);
$total = $subtotal + $vat;

// 방식 2: 곱하기 1.1 (기타 품목)
$total_with_vat = floor($subtotal * 1.1);

4. 폴백 메커니즘 패턴

// 1차: 모든 조건 포함
$result = query("WHERE style=? AND Section=? AND POtype=?");

if (empty($result)) {
    // 2차: POtype 제외
    $result = query("WHERE style=? AND Section=?");
}

[관련 문서]

  • [duson-print-rules] - 수량 표기 규칙, 규격/옵션 표기 규칙
  • CLAUDE.md - 프로젝트 전체 규칙
  • CLAUDE_DOCS/03_PRODUCTS/ - 제품별 상세 가이드

Last Updated: 2025-12-29 적용 범위: 두손기획 인쇄 시스템 가격 계산